diff --git a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt index e022256a5b6..332cafc0795 100644 --- a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt +++ b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt @@ -161,6 +161,12 @@ o2physics_add_dpl_workflow(diphoton-hadron-mpc-pcmpcm PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(compconvbuilder + SOURCES compconvbuilder.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(diphoton-hadron-mpc-pcmdalitzee SOURCES diphotonHadronMPCPCMDalitzEE.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore diff --git a/PWGEM/PhotonMeson/Tasks/compconvbuilder.cxx b/PWGEM/PhotonMeson/Tasks/compconvbuilder.cxx new file mode 100644 index 00000000000..5512191322c --- /dev/null +++ b/PWGEM/PhotonMeson/Tasks/compconvbuilder.cxx @@ -0,0 +1,889 @@ +// 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 compconvbuilder.cxx +/// \brief QA task for photons in the EM and LF builder +/// +/// \author S. Mrozinski, smrozins@cern.ch + +#include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" +#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" +#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" +#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "PWGLF/DataModel/LFStrangenessMLTables.h" +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TPCVDriftManager.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/McCollisionExtra.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::aod; +using namespace o2::soa; + +using namespace o2::aod::pwgem::photon; +using namespace o2::aod::pwgem::dilepton::utils::mcutil; +using namespace o2::aod::pwgem::photonmeson::utils::mcutil; + +using MyV0Photons = soa::Join; +using MyMCV0Legs = soa::Join; +using MyMCV0Leg = MyMCV0Legs::iterator; + +using MyCollisions = soa::Join; +using MyCollision = MyCollisions::iterator; + +using MyMCCollisions = soa::Join; +using MyMCCollision = MyMCCollisions::iterator; + +using MyStraCollisions = soa::Join; +using MyStraCollision = MyStraCollisions::iterator; + +using MyTracksIUMC = soa::Join; +using MyMCParticles = aod::McParticles; + +using V0DerivedMCDatas = soa::Join; + +using dauTracks = soa::Join; + +struct Convbuildercomp { + HistogramRegistry registry{"Convbuildercomp"}; + + enum conversionBuilderID { + EMBuilder = 0, + LFBuilder = 1, + EMOnly = 2, + LFOnly = 3, + Common = 4 + }; + + static constexpr std::string_view conversionBuilder[5] = {"EMBuilder/", "LFBuilder/", "EMOnly/", "LFOnly/", "Common/"}; + static constexpr std::string_view event_types[2] = {"before/", "after/"}; + + 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; + + 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); + } + + // Link V0-photons to their collision + Preslice perV0PhotonCollision = aod::v0photonkf::emeventId; + + void init(InitContext const& /*ctx*/) + { + + DefineEMEventCut(); + + for (int i = 0; i < 5; ++i) { + + registry.add(string(conversionBuilder[i]) + "hPt", ";p_{T} (GeV/c); Counts", kTH1F, {{1000, 0., 10.}}); + registry.add(string(conversionBuilder[i]) + "hR", ";R_{conv} (cm); Counts", kTH1F, {{100, 0., 100.}}); + + registry.add(string(conversionBuilder[i]) + "hEta", ";#eta; Counts", kTH1F, {{200, -1.0f, 1.0f}}); + + registry.add(string(conversionBuilder[i]) + "hcosPA", ";R_{conv} (cm); Counts", kTH1F, {{100, 0.99f, 1.0f}}); + + registry.add(string(conversionBuilder[i]) + "MatchedDeltaRec", ";#Delta colID_{rec};Counts", kTH1F, {{21, -10.5, 10.5}}); + + registry.add(string(conversionBuilder[i]) + "hZ", ";z (cm);Counts", kTH1F, {{200, -100, 100}}); + + registry.add(string(conversionBuilder[i]) + "hZR", "conversion point in RZ;Z (cm);R_{xy} (cm)", kTH2F, {{200, -100, 100}, {200, 0.0f, 100.0f}}); + + registry.add(string(conversionBuilder[i]) + "hAP", "AP plot;#alpha;q_{T} (GeV/c)", kTH2F, {{200, -1.0f, +1.0f}, {250, 0.0f, 0.25f}}); + + registry.add(string(conversionBuilder[i]) + "ResolutionGen/Z_res", "Conversion radius resolution;z_{conv, gen} (cm);R_{conv, gen} (cm);#varphi_{gen} (rad.);#eta_{gen};p_{T, gen};z_{conv, rec} - z_{conv, gen} (cm);", + kTHnSparseF, + {{200, -100, 100}, + {200, 0, 100}, + {90, 0, 2 * M_PI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + {120, -30, 30} + + }, + false); + + registry.add(string(conversionBuilder[i]) + "ResolutionGen/R_res", "Conversion radius resolution;z_{conv, gen} (cm);R_{conv, gen} (cm);#varphi_{gen} (rad.);#eta_{gen};p_{T, gen};R_{conv, rec} - R_{conv, gen} (cm);", + kTHnSparseF, + {{200, -100, 100}, + {200, 0, 100}, + {90, 0, 2 * M_PI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + {120, -30, 30} + + }, + false); + + registry.add(string(conversionBuilder[i]) + "ResolutionGen/Phi_res", "#varphi resolution;z_{conv, gen} (cm);R_{conv, gen} (cm);#varphi_{gen} (rad.);#eta_{gen};p_{T, gen};#varphi_{conv, rec} - #varphi_{conv, gen} (cm);", + kTHnSparseF, + {{200, -100, 100}, + {200, 0, 100}, + {90, 0, 2 * M_PI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + {100, -0.2f, 0.2f} + + }, + false); + + registry.add(string(conversionBuilder[i]) + "ResolutionGen/Pt_res", "Conversion radius resolution;z_{conv, gen} (cm);R_{conv, gen} (cm);#varphi_{gen} (rad.);#eta_{gen};p_{T, gen};p_{T, rec} - p_{T, gen}/p_{T, gen};", + kTHnSparseF, + {{200, -100, 100}, + {200, 0, 100}, + {90, 0, 2 * M_PI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + {200, -1.0f, 1.0f} + + }, + false); + + registry.add(string(conversionBuilder[i]) + "ResolutionGen/Eta_res", "Conversion radius resolution;z_{conv, gen} (cm);R_{conv, gen} (cm);#varphi_{gen} (rad.);#eta_{gen};p_{T, gen};#eta_{conv, rec} - #eta_{conv, gen} (cm);", + kTHnSparseF, + {{200, -100, 100}, + {200, 0, 100}, + {90, 0, 2 * M_PI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + {100, -0.5f, 0.5f} + + }, + false); + + registry.add(string(conversionBuilder[i]) + "ResolutionRec/Z_res", "Conversion radius resolution;z_{conv, rec} (cm);R_{conv, rec} (cm);#varphi_{rec} (rad.);#eta_{rec};p_{T, rec};z_{conv, rec} - z_{conv, gen} (cm);", + kTHnSparseF, + {{200, -100, 100}, + {200, 0, 100}, + {90, 0, 2 * M_PI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + {120, -30, 30} + + }, + false); + + registry.add(string(conversionBuilder[i]) + "ResolutionRec/R_res", "Conversion radius resolution;z_{conv, rec} (cm);R_{conv, rec} (cm);#varphi_{rec} (rad.);#eta_{rec};p_{T, rec};R_{conv, rec} - R_{conv, gen} (cm);", + kTHnSparseF, + {{200, -100, 100}, + {200, 0, 100}, + {90, 0, 2 * M_PI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + {120, -30, 30} + + }, + false); + + registry.add(string(conversionBuilder[i]) + "ResolutionRec/Phi_res", "#varphi resolution;z_{conv, rec} (cm);R_{conv, rec} (cm);#varphi_{rec} (rad.);#eta_{rec};p_{T, rec};#varphi_{conv, rec} - #varphi_{conv, gen} (cm);", + kTHnSparseF, + {{200, -100, 100}, + {200, 0, 100}, + {90, 0, 2 * M_PI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + {100, -0.2f, 0.2f} + + }, + false); + + registry.add(string(conversionBuilder[i]) + "ResolutionRec/Pt_res", "Conversion radius resolution;z_{conv, rec} (cm);R_{conv, rec} (cm);#varphi_{rec} (rad.);#eta_{rec};p_{T, rec};p_{T, rec} - p_{T, gen}/p_{T, gen};", + kTHnSparseF, + {{200, -100, 100}, + {200, 0, 100}, + {90, 0, 2 * M_PI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + {200, -1.0f, 1.0f} + + }, + false); + + registry.add(string(conversionBuilder[i]) + "ResolutionRec/Eta_res", "Conversion radius resolution;z_{conv, rec} (cm);R_{conv, rec} (cm);#varphi_{rec} (rad.);#eta_{rec};p_{T, rec};#eta_{conv, rec} - #eta_{conv, gen} (cm);", + kTHnSparseF, + {{200, -100, 100}, + {200, 0, 100}, + {90, 0, 2 * M_PI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + {100, -0.5f, 0.5f} + + }, + false); + registry.add(string(conversionBuilder[i]) + "ConvInfo", "Conversion radius resolution;x_{conv} (cm);y_{conv} (cm);z_{conv} (cm);R_{conv} (cm);#varphi (rad.);#eta;p_{T, gen};", + kTHnSparseF, + { + {200, -100, 100}, + {200, -100, 100}, + {200, -100, 100}, + {200, 0, 100}, + {90, 0, 2 * M_PI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + + }, + false); + + registry.add(string(conversionBuilder[i]) + "V0Leg/Asymmetry", "", kTH1F, {{100, 0, 1}}); + + auto hCollisionCounter = registry.add(string(conversionBuilder[i]) + "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(string(conversionBuilder[i]) + "Event/before/hZvtx", "vertex z; Z_{vtx} (cm)", kTH1F, {{100, -50, +50}}, false); + registry.add(string(conversionBuilder[i]) + "Event/before/hMultNTracksPV", "hMultNTracksPV; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); + registry.add(string(conversionBuilder[i]) + "Event/before/hMultNTracksPVeta1", "hMultNTracksPVeta1; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); + registry.add(string(conversionBuilder[i]) + "Event/before/hMultFT0", "hMultFT0;mult. FT0A;mult. FT0C", kTH2F, {{300, 0, 6000}, {300, 0, 6000}}, false); + registry.add(string(conversionBuilder[i]) + "Event/before/hCentFT0A", "hCentFT0A;centrality FT0A (%)", kTH1F, {{110, 0, 110}}, false); + registry.add(string(conversionBuilder[i]) + "Event/before/hCentFT0C", "hCentFT0C;centrality FT0C (%)", kTH1F, {{110, 0, 110}}, false); + registry.add(string(conversionBuilder[i]) + "Event/before/hCentFT0M", "hCentFT0M;centrality FT0M (%)", kTH1F, {{110, 0, 110}}, false); + registry.add(string(conversionBuilder[i]) + "Event/before/hCentFT0MvsMultNTracksPV", "hCentFT0MvsMultNTracksPV;centrality FT0M (%);N_{track} to PV", kTH2F, {{110, 0, 110}, {600, 0, 6000}}, false); + registry.add(string(conversionBuilder[i]) + "Event/before/hMultFT0MvsMultNTracksPV", "hMultFT0MvsMultNTracksPV;mult. FT0M;N_{track} to PV", kTH2F, {{600, 0, 6000}, {600, 0, 6000}}, false); + registry.addClone(string(conversionBuilder[i]) + "Event/before/", string(conversionBuilder[i]) + "Event/after/"); + } + + registry.add("truePhotons/hPt_Converted", "Converted Photons; p_{T} (GeV/c); Counts", kTH1F, {{100, 0., 10.}}); + registry.add("truePhotons/hR_Converted", "Converted Photons; R (cm); Counts", kTH1F, {{100, 0., 100.}}); + + registry.add("truePhotons/Sparse_Converted", "Conversion radius resolution;x_{conv} (cm);z_{conv} (cm);y_{conv} (cm);R_{conv} (cm);#varphi (rad.);#eta;p_{T, gen};", + kTHnSparseF, + {{200, -100, 100}, + {200, -100, 100}, + {200, -100, 100}, + {200, 0, 100}, + {90, 0, 2 * M_PI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}}, + false); + + auto h = registry.add("EMBuilder/hV0SignType", "Crosscheck", kTH1F, {{3, 0.5, 4.5}}, false); + h->GetXaxis()->SetBinLabel(1, "Same-sign"); + h->GetXaxis()->SetBinLabel(2, "Opposite-sign"); + h->GetXaxis()->SetBinLabel(3, "Zero-sign"); + + auto h2 = registry.add("EMBuilder/hV0ElectronPositronTrue", "pair in MC truth;;counts", kTH1F, {{2, -0.5, 1.5}}); + h2->GetXaxis()->SetBinLabel(1, "Mismatch"); + h2->GetXaxis()->SetBinLabel(2, "Good"); + } + + template + void fillEventInfo(TCollision const& collision, const float /*weight*/ = 1.f) + { + registry.fill(HIST(conversionBuilder[type]) + HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 1.0); + + if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + registry.fill(HIST(conversionBuilder[type]) + HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 2.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + registry.fill(HIST(conversionBuilder[type]) + HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 3.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + registry.fill(HIST(conversionBuilder[type]) + HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 4.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + registry.fill(HIST(conversionBuilder[type]) + HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 5.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + registry.fill(HIST(conversionBuilder[type]) + HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 6.0); + } + + if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + registry.fill(HIST(conversionBuilder[type]) + HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 7.0); + } + + if (collision.sel8()) { + registry.fill(HIST(conversionBuilder[type]) + HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 8.0); + } + if (std::fabs(collision.posZ()) < 10.0) { + registry.fill(HIST(conversionBuilder[type]) + HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 9.0); + } + + registry.fill(HIST(conversionBuilder[type]) + HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultNTracksPVeta1"), collision.multNTracksPVeta1()); + } + + template + void fillLegInfo(auto& v0, auto& posleg, auto& negleg) + { + if constexpr (type == 0) { + + float ptPos = posleg.pt(); + float ptNeg = negleg.pt(); + float asym = (ptPos - ptNeg) / (ptPos + ptNeg); + + registry.fill(HIST(conversionBuilder[type]) + HIST("V0Leg/Asymmetry"), asym); + + } else { + + float ptPos = v0.postrackpt(); + float ptNeg = negleg.negtrackpt(); + float asym = (ptPos - ptNeg) / (ptPos + ptNeg); + + registry.fill(HIST(conversionBuilder[type]) + HIST("V0Leg/Asymmetry"), asym); + } + } + + template + void fillV0Info(auto& v0, auto& v0MC, auto& mcleg) + { + registry.fill(HIST(conversionBuilder[type]) + HIST("hPt"), v0.pt()); + registry.fill(HIST(conversionBuilder[type]) + HIST("hEta"), v0.eta()); + registry.fill(HIST(conversionBuilder[type]) + HIST("hAP"), v0.alpha(), v0.qtarm()); + + if constexpr (type == 0 || type == 2) { + registry.fill(HIST(conversionBuilder[type]) + HIST("hZ"), v0.vz()); + registry.fill(HIST(conversionBuilder[type]) + HIST("hcosPA"), v0.cospa()); + registry.fill(HIST(conversionBuilder[type]) + HIST("hZR"), v0.vz(), v0.v0radius()); + + float deltapT = v0.pt() - v0MC.pt(); + float deltaZ = v0.vz() - mcleg.vz(); + float deltaPhi = v0.phi() - v0MC.phi(); + float deltaEta = v0.eta() - v0MC.eta(); + float deltaR = v0.v0radius() - std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ResolutionGen/Z_res"), + mcleg.vz(), + std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), + v0MC.phi(), + v0MC.eta(), + v0MC.pt(), + deltaZ); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ResolutionGen/R_res"), + mcleg.vz(), + std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), + v0MC.phi(), + v0MC.eta(), + v0MC.pt(), + deltaR); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ResolutionGen/Phi_res"), + mcleg.vz(), + std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), + v0MC.phi(), + v0MC.eta(), + v0MC.pt(), + deltaPhi); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ResolutionGen/Pt_res"), + mcleg.vz(), + std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), + v0MC.phi(), + v0MC.eta(), + v0MC.pt(), + deltapT); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ResolutionGen/Eta_res"), + mcleg.vz(), + std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), + v0MC.phi(), + v0MC.eta(), + v0MC.pt(), + deltaEta); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ResolutionRec/Z_res"), + v0.vz(), + v0.v0radius(), + v0.phi(), + v0.eta(), + v0.pt(), + deltaZ); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ResolutionRec/R_res"), + v0.vz(), + v0.v0radius(), + v0.phi(), + v0.eta(), + v0.pt(), + deltaR); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ResolutionRec/Phi_res"), + v0.vz(), + v0.v0radius(), + v0.phi(), + v0.eta(), + v0.pt(), + deltaPhi); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ResolutionRec/Pt_res"), + v0.vz(), + v0.v0radius(), + v0.phi(), + v0.eta(), + v0.pt(), + deltapT); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ResolutionRec/Eta_res"), + v0.vz(), + v0.v0radius(), + v0.phi(), + v0.eta(), + v0.pt(), + deltaEta); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ConvInfo"), + v0.vx(), // 0 + v0.vy(), // 1 + v0.vz(), // 2 + v0.v0radius(), // 3 + v0.phi(), // 4 + v0.eta(), // 5 + v0.pt()); // 6 + + } else { + registry.fill(HIST(conversionBuilder[type]) + HIST("hZ"), v0.z()); + registry.fill(HIST(conversionBuilder[type]) + HIST("hcosPA"), v0.v0cosPA()); + registry.fill(HIST(conversionBuilder[type]) + HIST("hZR"), v0.z(), v0.v0radius()); + + float deltaR = v0.v0radius() - std::hypot(v0MC.xMC(), v0MC.yMC()); + + float phiRec = v0.phi(); + if (phiRec < 0) { + phiRec += 2.0f * static_cast(M_PI); + } + + float phiMC = std::atan2(v0MC.pyMC(), v0MC.pxMC()); + if (phiMC < 0) { + phiMC += 2.0f * static_cast(M_PI); + } + + float deltaPhi = phiRec - phiMC; + if (deltaPhi < 0) { + deltaPhi += 2.0f * static_cast(M_PI); + } + + float etaGen = 0.5f * std::log((std::hypot(v0MC.pxMC(), v0MC.pyMC(), v0MC.pzMC()) + v0MC.pzMC()) / (std::hypot(v0MC.pxMC(), v0MC.pyMC(), v0MC.pzMC()) - v0MC.pzMC())); + + float etaRec = 0.5f * std::log((std::hypot(v0.px(), v0.py(), v0.pz()) + v0.pz()) / (std::hypot(v0.px(), v0.py(), v0.pz()) - v0.pz())); + + float deltapT = v0.pt() - v0MC.ptMC(); + float deltaEta = etaRec - etaGen; + float deltaZ = v0.z() - v0MC.zMC(); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ResolutionGen/Z_res"), + v0MC.zMC(), + std::hypot(v0MC.xMC(), v0MC.yMC()), + phiMC, + etaGen, + v0MC.ptMC(), + deltaZ); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ResolutionGen/R_res"), + v0MC.zMC(), + std::hypot(v0MC.xMC(), v0MC.yMC()), + phiMC, + etaGen, + v0MC.ptMC(), + deltaR); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ResolutionGen/Phi_res"), + v0MC.zMC(), + std::hypot(v0MC.xMC(), v0MC.yMC()), + phiMC, + etaGen, + v0MC.ptMC(), + deltaPhi); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ResolutionGen/Pt_res"), + v0MC.zMC(), + std::hypot(v0MC.xMC(), v0MC.yMC()), + phiMC, + etaGen, + v0MC.ptMC(), + deltapT); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ResolutionGen/Eta_res"), + v0MC.zMC(), + std::hypot(v0MC.xMC(), v0MC.yMC()), + phiMC, + etaGen, + v0MC.ptMC(), + deltaEta); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ResolutionRec/Z_res"), + v0.z(), + v0.v0radius(), + phiRec, + v0.eta(), + v0.pt(), + deltaZ); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ResolutionRec/R_res"), + v0.z(), + v0.v0radius(), + phiRec, + v0.eta(), + v0.pt(), + deltaR); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ResolutionRec/Phi_res"), + v0.z(), + v0.v0radius(), + phiRec, + v0.eta(), + v0.pt(), + deltaPhi); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ResolutionRec/Eta_res"), + v0.z(), + v0.v0radius(), + phiRec, + v0.eta(), + v0.pt(), + deltaEta); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ResolutionRec/Pt_res"), + v0.z(), + v0.v0radius(), + phiRec, + v0.eta(), + v0.pt(), + deltapT); + + registry.fill(HIST(conversionBuilder[type]) + HIST("ConvInfo"), + v0.x(), + v0.y(), + v0.z(), + v0.v0radius(), + phiRec, + v0.eta(), + v0.pt()); + } + + registry.fill(HIST(conversionBuilder[type]) + HIST("hR"), v0.v0radius()); + } + + Preslice perCollisionMCDerived = o2::aod::v0data::straCollisionId; + + void processLFV0sMC(MyStraCollisions const& stracollisions, + soa::Join const&, + V0DerivedMCDatas const& strangeV0s) + { + + for (auto& collision : stracollisions) { + + fillEventInfo<0, LFBuilder>(collision); + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + + fillEventInfo<1, LFBuilder>(collision); + + registry.fill(HIST((conversionBuilder[1])) + HIST("Event/before/hCollisionCounter"), 10.0); + registry.fill(HIST((conversionBuilder[1])) + HIST("Event/after/hCollisionCounter"), 10.0); // accepted + + auto myV0s = strangeV0s.sliceBy(perCollisionMCDerived, collision.globalIndex()); + + for (auto const& v0 : myV0s) { + if (!v0.has_v0MCCore()) { + continue; + } + + auto v0MC = v0.v0MCCore_as>(); + + if (v0MC.pdgCode() != 22 || !v0MC.isPhysicalPrimary()) { + continue; + } + + auto posTrack = v0.template posTrackExtra_as(); + + fillV0Info(v0, v0MC, posTrack); + } + } + } + + Preslice perCollision = aod::v0photonkf::emeventId; + + void processEMV0sMC(MyV0Photons const& v0s, aod::EMMCParticles const& mcparticles, MyMCV0Legs const&, MyCollisions const& collisions) + { + + for (auto& collision : collisions) { + + fillEventInfo<0, EMBuilder>(collision); + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + fillEventInfo<1, EMBuilder>(collision); + + registry.fill(HIST((conversionBuilder[0])) + HIST("Event/before/hCollisionCounter"), 10.0); // accepted + registry.fill(HIST((conversionBuilder[0])) + HIST("Event/after/hCollisionCounter"), 10.0); // accepted + + auto V0Photons_coll = v0s.sliceBy(perCollision, collision.globalIndex()); + + for (auto const& v0 : V0Photons_coll) { + + auto pos = v0.posTrack_as(); + auto ele = v0.negTrack_as(); + auto posmc = pos.template emmcparticle_as(); + auto elemc = ele.template emmcparticle_as(); + + int photonid = FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 22, mcparticles); + + auto mcphoton = mcparticles.iteratorAt(photonid); + + if (mcphoton.isPhysicalPrimary()) { + + fillV0Info(v0, mcphoton, elemc); + } + + if (pos.sign() * ele.sign() > 0) { + registry.fill(HIST("EMBuilder/hV0SignType"), 1); // same-sign + } else if (pos.sign() * ele.sign() < 0) { + registry.fill(HIST("EMBuilder/hV0SignType"), 2); // opposite-sign + } else { + registry.fill(HIST("EMBuilder/hV0SignType"), 3); // zero or undefined + } + + if ((posmc.pdgCode() == 11 && elemc.pdgCode() == -11) || (posmc.pdgCode() == -11 && elemc.pdgCode() == 11)) { + registry.fill(HIST("EMBuilder/hV0ElectronPositronTrue"), 1); // good + } else { + registry.fill(HIST("EMBuilder/hV0ElectronPositronTrue"), 0); // mismatch + } + } + } + } + + PresliceUnsorted perMcCollision = aod::emmcparticle::emmceventId; + + void processConvV0s(MyCollisions const& collisions, + aod::EMMCParticles const& mcparticles, + MyTracksIUMC const& tracks) + { + for (auto& collision : collisions) { + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + + auto mccollision = collision.template emmcevent_as(); + + auto mcstack = mcparticles.sliceBy(perMcCollision, mccollision.globalIndex()); + auto mctracks_coll = mcparticles.sliceBy(perMcCollision, mccollision.globalIndex()); + + std::unordered_map mc2trk; + for (auto& trk : tracks) { + if (trk.mcParticleId() >= 0) { + mc2trk[trk.mcParticleId()] = trk.globalIndex(); + } + } + + for (auto& mc : mctracks_coll) { + if (mc.pdgCode() != 22 || !mc.isPhysicalPrimary()) { + continue; + } + + auto daughters = mc.daughtersIds(); + if (daughters.size() != 2) { + continue; + } + + auto d1 = mcparticles.iteratorAt(daughters[0]); + auto d2 = mcparticles.iteratorAt(daughters[1]); + + if (std::abs(d1.pdgCode()) != 11 || std::abs(d2.pdgCode()) != 11) { + continue; + } + + float r = std::hypot(d1.vx(), d1.vy()); + if (r < 5.0f || r > 90.0f) { + continue; + } + + registry.fill(HIST("truePhotons/hPt_Converted"), mc.pt()); + registry.fill(HIST("truePhotons/hR_Converted"), r); + + registry.fill(HIST("truePhotons/Sparse_Converted"), d1.vx(), mc.y(), d1.vz(), r, mc.phi(), mc.eta(), mc.pt()); + + int id1 = mc2trk.count(d1.globalIndex()) ? mc2trk[d1.globalIndex()] : -1; + int id2 = mc2trk.count(d2.globalIndex()) ? mc2trk[d2.globalIndex()] : -1; + if (id1 < 0 || id2 < 0) { + continue; + } + } + } + } + + Preslice perEMCollision = aod::v0photonkf::emeventId; + + void processMatchCategories( + MyCollisions const& collisions, + MyTracksIUMC const& tracksgen, + MyV0Photons const& emV0s, + soa::Join const&, + V0DerivedMCDatas const& lfV0s, + MyMCV0Legs const&, + aod::McParticles const& mcparticles, + dauTracks const&) + { + std::unordered_map trackToMcLabel; + for (auto const& t : tracksgen) { + int label = t.mcParticleId(); + if (label >= 0) { + trackToMcLabel[t.globalIndex()] = label; + } + } + + for (auto& collision : collisions) { + if (!fEMEventCut.IsSelected(collision)) + continue; + + fillEventInfo<1, EMBuilder>(collision); + + auto emSlice = emV0s.sliceBy(perEMCollision, collision.globalIndex()); + auto lfSlice = lfV0s.sliceBy(perCollisionMCDerived, collision.globalIndex()); + + using EMIt = decltype(emSlice.begin()); + using LFIt = decltype(lfSlice.begin()); + struct Entry { + std::optional emIt; + std::optional lfIt; + }; + std::unordered_map table; + + for (EMIt it = emSlice.begin(); it != emSlice.end(); ++it) { + auto posmc = it.posTrack_as() + .emmcparticle_as(); + auto negmc = it.negTrack_as() + .emmcparticle_as(); + int pid = FindCommonMotherFrom2Prongs(posmc, negmc, + -11, 11, 22, mcparticles); + if (pid >= 0) + table[pid].emIt = it; + } + + for (LFIt it = lfSlice.begin(); it != lfSlice.end(); ++it) { + int posTrackIndex = it.posTrackId(); + auto negTrackIndex = it.negTrackId(); + + if (!trackToMcLabel.count(posTrackIndex) || !trackToMcLabel.count(negTrackIndex)) + continue; + auto posmc = mcparticles.iteratorAt(trackToMcLabel[posTrackIndex]); + auto negmc = mcparticles.iteratorAt(trackToMcLabel[negTrackIndex]); + int pid = FindCommonMotherFrom2Prongs(posmc, negmc, + -11, 11, 22, mcparticles); + if (pid >= 0) + table[pid].lfIt = it; + } + + for (auto const& [pid, entry] : table) { + auto mcphoton = mcparticles.iteratorAt(pid); + + if (entry.emIt.has_value() && entry.lfIt.has_value()) { + // --- Common V0 --- + auto& lfV0 = *entry.lfIt.value(); + auto v0MC = lfV0.template v0MCCore_as< + soa::Join>(); + auto posTrack = lfV0.template posTrackExtra_as(); + fillV0Info(lfV0, v0MC, posTrack); + + } else if (entry.emIt.has_value()) { + // --- EM-only V0 --- + auto& emV0 = *entry.emIt.value(); + auto negmc = emV0.negTrack_as() + .emmcparticle_as(); + fillV0Info(emV0, mcphoton, negmc); + + } else if (entry.lfIt.has_value()) { + // --- LF-only V0 --- + auto& lfV0 = *entry.lfIt.value(); + auto v0MC = lfV0.template v0MCCore_as< + soa::Join>(); + auto posTrack = lfV0.template posTrackExtra_as(); + fillV0Info(lfV0, v0MC, posTrack); + } + } + } + } + + PROCESS_SWITCH(Convbuildercomp, processMatchCategories, "Process V0s matched via MC photon", false); + PROCESS_SWITCH(Convbuildercomp, processLFV0sMC, "Process LF Builder V0s", true); + PROCESS_SWITCH(Convbuildercomp, processEMV0sMC, "Process EM Builder V0s", false); + PROCESS_SWITCH(Convbuildercomp, processConvV0s, "Process generated converted V0s", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfg) +{ + return WorkflowSpec{adaptAnalysisTask(cfg)}; +}