diff --git a/PWGCF/Femto/Core/closePairRejection.h b/PWGCF/Femto/Core/closePairRejection.h index 8e763b7affc..67c1e92f532 100644 --- a/PWGCF/Femto/Core/closePairRejection.h +++ b/PWGCF/Femto/Core/closePairRejection.h @@ -95,6 +95,7 @@ constexpr const char PrefixCprTrackLcPion[] = "CprTrackLcPion"; constexpr const char PrefixCprD0DaughterD0DaughterPos[] = "CprD0DaughterD0DaughterPos"; constexpr const char PrefixCprD0DaughterD0DaughterNeg[] = "CprD0DaughterD0DaughterNeg"; constexpr const char PrefixCprTrackResonanceDaughter[] = "CprTrackResonanceDaughter"; +constexpr const char PrefixCprTrackTwoPhotonResonanceDaughter[] = "CprTrackTwoPhotonResonanceDaughter"; constexpr const char PrefixCprTrackKinkDaughter[] = "CprTrackKinkDaughter"; constexpr const char PrefixCprV0DaughterV0DaughterPos[] = "CprV0DaughterV0DaughterPos"; constexpr const char PrefixCprV0DaughterV0DaughterNeg[] = "CprV0DaughterV0DaughterNeg"; @@ -113,6 +114,8 @@ using ConfCprTrackLcPion = ConfCpr; using ConfCprD0DaugherD0DaughterPos = ConfCpr; using ConfCprD0DaugherD0DaughterNeg = ConfCpr; using ConfCprTrackResonanceDaughter = ConfCpr; +// no cut by default: CPR is a no-op for two-photon resonances (see ClosePairRejectionTrackTwoPhotonResonance) +using ConfCprTrackTwoPhotonResonanceDaughter = ConfCpr; using ConfCprTrackKinkDaughter = ConfCpr; using ConfCprV0DaugherV0DaughterPos = ConfCpr; using ConfCprV0DaugherV0DaughterNeg = ConfCpr; @@ -152,6 +155,8 @@ constexpr char PrefixV0TwoTrackResonancePosMe[] = "CPR_V0Resonance_PosDau/ME/"; constexpr char PrefixV0TwoTrackResonanceNegMe[] = "CPR_V0Resonance_NegDau/ME/"; constexpr char PrefixTrackTwoTrackResonanceSe[] = "CPR_TrackResonanceDau/SE/"; constexpr char PrefixTrackTwoTrackResonanceMe[] = "CPR_TrackResonanceDau/ME/"; +constexpr char PrefixTrackTwoPhotonResonanceSe[] = "CPR_TrackTwoPhotonResonanceDau/SE/"; +constexpr char PrefixTrackTwoPhotonResonanceMe[] = "CPR_TrackTwoPhotonResonanceDau/ME/"; constexpr char PrefixTrackCascadeBachelorSe[] = "CPR_TrackCascadeBachelor/SE/"; constexpr char PrefixTrackCascadeBachelorMe[] = "CPR_TrackCascadeBachelor/ME/"; constexpr char PrefixTrackKinkSe[] = "CPR_TrackKink/SE/"; @@ -320,14 +325,22 @@ class CloseTrackRejection swapTracks = (mSwapDist(mRng) == 1); } - auto t1 = swapTracks ? track2 : track1; - auto t2 = swapTracks ? track1 : track2; + // get kinematics of the particles + // if configured, randomly swap particle 1 and particle 2 + float eta1 = swapTracks ? track2.eta() : track1.eta(); + float eta2 = swapTracks ? track1.eta() : track2.eta(); + float phi1 = swapTracks ? track2.phi() : track1.phi(); + float phi2 = swapTracks ? track1.phi() : track2.phi(); + float signedPt1 = swapTracks ? track2.signedPt() : track1.signedPt(); + float signedPt2 = swapTracks ? track1.signedPt() : track2.signedPt(); + int chargeAbs1 = swapTracks ? mChargeAbsTrack2 : mChargeAbsTrack1; + int chargeAbs2 = swapTracks ? mChargeAbsTrack1 : mChargeAbsTrack2; - mDeta = t1.eta() - t2.eta(); + mDeta = eta1 - eta2; for (size_t i = 0; i < TpcRadii.size(); i++) { - auto phistar1 = phistar(mMagField, TpcRadii.at(i), mChargeAbsTrack1 * t1.signedPt(), t1.phi()); - auto phistar2 = phistar(mMagField, TpcRadii.at(i), mChargeAbsTrack2 * t2.signedPt(), t2.phi()); + auto phistar1 = phistar(mMagField, TpcRadii.at(i), chargeAbs1 * signedPt1, phi1); + auto phistar2 = phistar(mMagField, TpcRadii.at(i), chargeAbs2 * signedPt2, phi2); if (phistar1 && phistar2) { mDphistar.at(i) = RecoDecay::constrainAngle(phistar1.value() - phistar2.value(), -o2::constants::math::PI); // constrain angular difference between -pi and pi mDphistarMask.at(i) = true; @@ -338,14 +351,14 @@ class CloseTrackRejection if (count > 0) { mAverageDphistar = std::accumulate(mDphistar.begin(), mDphistar.end(), 0.f) / count; // only average values if phistar could be computed } else { - mAverageDphistar = 0.f; // if computation at all radii fail, set it 0 + mAverageDphistar = 0.f; // if computation at all radii failed, set it 0 } if (mPlotAngularCorrelation) { - mPhi1 = t1.phi(); - mPhi2 = t2.phi(); - mEta1 = t1.eta(); - mEta2 = t2.eta(); + mPhi1 = phi1; + mPhi2 = phi2; + mEta1 = eta1; + mEta2 = eta2; } } @@ -731,6 +744,32 @@ class ClosePairRejectionTrackKink CloseTrackRejection mCtr; }; +// PCM photon daughters are, for now, not indexed into the track table (see photonBuilder.h): +// they are TPC-only tracks, so they cannot be confused for a global track the way two V0 +// daughters or a track and a V0 daughter can -- there is no detector-overlap effect to correct +// for. This is a no-op placeholder so Track-TwoPhotonResonance pairs can use the same generic +// pair-building code path. +template +class ClosePairRejectionTrackTwoPhotonResonance +{ + public: + template + void init(o2::framework::HistogramRegistry* /*registry*/, + std::map> const& /*specs*/, + T const& /*confCpr*/, + int /*absChargeTrack*/) + { + } + + void setMagField(float /*magField*/) {} + + template + [[nodiscard]] bool isClosePair(T1 const& /*track*/, T2 const& /*resonance*/, T3 const& /*photonTable*/, T4 const& /*pairHistManager*/) + { + return false; + } +}; + template class ClosePairRejectionMcParticleMcParticle { diff --git a/PWGCF/Femto/Core/femtoUtils.h b/PWGCF/Femto/Core/femtoUtils.h index d7a4a888e74..07b6e47705a 100644 --- a/PWGCF/Femto/Core/femtoUtils.h +++ b/PWGCF/Femto/Core/femtoUtils.h @@ -141,6 +141,12 @@ inline double getPdgMass(int pdgCode) case kOmegaMinus: mass = o2::constants::physics::MassOmegaMinus; break; + case kPi0: + mass = o2::constants::physics::MassPi0; + break; + case o2::constants::physics::kEta: + mass = o2::constants::physics::MassEta; + break; default: LOG(warn) << "PDG code " << pdgCode << " is not suppored. Return 0... "; } diff --git a/PWGCF/Femto/Core/modes.h b/PWGCF/Femto/Core/modes.h index 609effb965b..e4306101980 100644 --- a/PWGCF/Femto/Core/modes.h +++ b/PWGCF/Femto/Core/modes.h @@ -113,6 +113,7 @@ enum class Particle : o2::analysis::femto::datatypes::ParticleType { kKink = 4, kCascade = 5, kCharmHadron = 6, + kTwoPhotonResonance = 7, }; enum class McOrigin : o2::analysis::femto::datatypes::McOriginType { diff --git a/PWGCF/Femto/Core/pairBuilder.h b/PWGCF/Femto/Core/pairBuilder.h index 0b408b64487..9ad834301e7 100644 --- a/PWGCF/Femto/Core/pairBuilder.h +++ b/PWGCF/Femto/Core/pairBuilder.h @@ -29,6 +29,7 @@ #include "PWGCF/Femto/Core/pairProcessHelpers.h" #include "PWGCF/Femto/Core/particleCleaner.h" #include "PWGCF/Femto/Core/trackHistManager.h" +#include "PWGCF/Femto/Core/twoPhotonResonanceHistManager.h" #include "PWGCF/Femto/Core/twoTrackResonanceHistManager.h" #include "PWGCF/Femto/Core/v0HistManager.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" @@ -1384,6 +1385,129 @@ class PairTrackV0Builder int mMixingDepth = 5; }; +// Track-TwoPhotonResonance pair builder. +// Note: close pair rejection is a no-op (ClosePairRejectionTrackTwoPhotonResonance) and pair cleaning +// reuses the plain TrackTrackPairCleaner (globalIndex-only), since photon daughters are, for +// now, not indexed into FTracks: they are TPC-only tracks, so they cannot be confused for a +// global track the way two V0 daughters or a track and a V0 daughter can. +template +class PairTrackTwoPhotonResonanceBuilder +{ + public: + PairTrackTwoPhotonResonanceBuilder() = default; + ~PairTrackTwoPhotonResonanceBuilder() = default; + + template + void init(o2::framework::HistogramRegistry* registry, + T1 const& confCollisionBinning, + T2 const& confTrackSelection, + T3 const& confResonanceSelection, + T4 const& confCpr, + T5 const& confMixing, + T6 const& confPairBinning, + T7 const& confPairCuts, + T8 const& confDauQaBinning, + std::map> const& colHistSpec, + std::map> const& trackHistSpec, + std::map> const& resonanceHistSpec, + std::map> const& dauHistSpec, + std::map> const& pairHistSpec, + std::map> const& cprHistSpec, + std::map> const& pairCleanerHistSpec) + { + mColHistManager.template init(registry, colHistSpec, confCollisionBinning); + + mTrackHistManager.template init(registry, trackHistSpec, confTrackSelection); + mResonanceHistManager.template init(registry, resonanceHistSpec, dauHistSpec, confDauQaBinning); + + mPairHistManagerSe.template init(registry, pairHistSpec, confPairBinning, confPairCuts, confMixing); + mPairHistManagerSe.setMass(confTrackSelection.pdgCodeAbs.value, confResonanceSelection.pdgCodeAbs.value); + mPairHistManagerSe.setCharge(confTrackSelection.chargeAbs.value, 1); + mCprSe.init(registry, cprHistSpec, confCpr, confTrackSelection.chargeAbs.value); + + mPairHistManagerMe.template init(registry, pairHistSpec, confPairBinning, confPairCuts, confMixing); + mPairHistManagerMe.setMass(confTrackSelection.pdgCodeAbs.value, confResonanceSelection.pdgCodeAbs.value); + mPairHistManagerMe.setCharge(confTrackSelection.chargeAbs.value, 1); + mCprMe.init(registry, cprHistSpec, confCpr, confTrackSelection.chargeAbs.value); + + mPcSe.template init(registry, pairCleanerHistSpec, confPairCuts); + mPcMe.template init(registry, pairCleanerHistSpec, confPairCuts); + + // setup mixing + mMixingPolicy = static_cast(confMixing.policy.value); + mMixingDepth = confMixing.depth.value; + } + + /// \return true if at least one pair passed all pair selections (usable as pair trigger) + template + bool processSameEvent(T1 const& col, T2& trackPartition, T3& resonancePartition, T4& photonTable, T5& cache) + { + auto trackSlice = trackPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto resonanceSlice = resonancePartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (trackSlice.size() < nLimitPartitionParticles || resonanceSlice.size() < nLimitPartitionParticles) { + return false; + } + mColHistManager.template fill(col); + mCprSe.setMagField(col.magField()); + return pairprocesshelpers::processSameEvent(trackSlice, resonanceSlice, photonTable, col, mTrackHistManager, mResonanceHistManager, mPairHistManagerSe, mCprSe, mPcSe); + } + + template + void processMixedEvent(T1 const& cols, T2& trackPartition, T3& resonancePartition, T4& photonTable, T5& cache, T6& binsVtxMult, T7& binsVtxCent, T8& binsVtxMultCent) + { + switch (mMixingPolicy) { + case static_cast(pairhistmanager::kVtxMult): + pairprocesshelpers::processMixedEvent(cols, trackPartition, resonancePartition, photonTable, cache, binsVtxMult, mMixingDepth, mPairHistManagerMe, mCprMe, mPcMe); + break; + case static_cast(pairhistmanager::kVtxCent): + pairprocesshelpers::processMixedEvent(cols, trackPartition, resonancePartition, photonTable, cache, binsVtxCent, mMixingDepth, mPairHistManagerMe, mCprMe, mPcMe); + break; + case static_cast(pairhistmanager::kVtxMultCent): + pairprocesshelpers::processMixedEvent(cols, trackPartition, resonancePartition, photonTable, cache, binsVtxMultCent, mMixingDepth, mPairHistManagerMe, mCprMe, mPcMe); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } + + private: + colhistmanager::CollisionHistManager mColHistManager; + trackhistmanager::TrackHistManager mTrackHistManager; + twophotonresonancehistmanager::TwoPhotonResonanceHistManager mResonanceHistManager; + pairhistmanager::PairHistManager mPairHistManagerSe; + pairhistmanager::PairHistManager mPairHistManagerMe; + closepairrejection::ClosePairRejectionTrackTwoPhotonResonance mCprSe; + closepairrejection::ClosePairRejectionTrackTwoPhotonResonance mCprMe; + paircleaner::TrackTrackPairCleaner mPcSe; + paircleaner::TrackTrackPairCleaner mPcMe; + pairhistmanager::MixingPolicy mMixingPolicy = pairhistmanager::MixingPolicy::kVtxMult; + int mMixingDepth = 5; +}; + template +#include #include #include #include @@ -31,6 +32,7 @@ #include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include +#include #include @@ -58,26 +60,27 @@ using ConfEtaFilters = ConfTwoPhotonResonanceFilters; // unlike TWOTRACKRESONANCE_DEFAULT_SELECTION there is no pos/neg split and no momentum-threshold PID // switch: photon daughters are unordered and have no momentum-dependent PID regime. // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define TWOPHOTONRESONANCE_DEFAULT_SELECTION(defaultMassMin, defaultMassMax) \ - o2::framework::Configurable ptMin{"ptMin", 0.f, "Minimum pT"}; \ - o2::framework::Configurable ptMax{"ptMax", 10.f, "Maximum pT"}; \ - o2::framework::Configurable etaMin{"etaMin", -0.9f, "Minimum eta"}; \ - o2::framework::Configurable etaMax{"etaMax", 0.9f, "Maximum eta"}; \ - o2::framework::Configurable phiMin{"phiMin", 0.f, "Minimum phi"}; \ - o2::framework::Configurable phiMax{"phiMax", 1.f * o2::constants::math::TwoPI, "Maximum phi"}; \ - o2::framework::Configurable massMin{"massMin", (defaultMassMin), "Minimum invariant mass for the resonance"}; \ - o2::framework::Configurable massMax{"massMax", (defaultMassMax), "Maximum invariant mass for the resonance"}; \ - o2::framework::Configurable dau1Mask{"dau1Mask", 0, "Bitmask required for first photon daughter"}; \ +#define TWOPHOTONRESONANCE_DEFAULT_SELECTION(defaultMassMin, defaultMassMax, defaultPdgCodeAbs) \ + o2::framework::Configurable ptMin{"ptMin", 0.f, "Minimum pT"}; \ + o2::framework::Configurable ptMax{"ptMax", 10.f, "Maximum pT"}; \ + o2::framework::Configurable etaMin{"etaMin", -0.9f, "Minimum eta"}; \ + o2::framework::Configurable etaMax{"etaMax", 0.9f, "Maximum eta"}; \ + o2::framework::Configurable phiMin{"phiMin", 0.f, "Minimum phi"}; \ + o2::framework::Configurable phiMax{"phiMax", 1.f * o2::constants::math::TwoPI, "Maximum phi"}; \ + o2::framework::Configurable massMin{"massMin", (defaultMassMin), "Minimum invariant mass for the resonance"}; \ + o2::framework::Configurable massMax{"massMax", (defaultMassMax), "Maximum invariant mass for the resonance"}; \ + o2::framework::Configurable pdgCodeAbs{"pdgCodeAbs", (defaultPdgCodeAbs), "Absolute PDG code of the resonance, used to set its mass for kstar/kt/mt (not the reconstructed two-photon mass)"}; \ + o2::framework::Configurable dau1Mask{"dau1Mask", 0, "Bitmask required for first photon daughter"}; \ o2::framework::Configurable dau2Mask{"dau2Mask", 0, "Bitmask required for second photon daughter"}; struct ConfPi0Selection : o2::framework::ConfigurableGroup { std::string prefix = std::string("Pi0Selection1"); - TWOPHOTONRESONANCE_DEFAULT_SELECTION(0.1f, 0.17f) + TWOPHOTONRESONANCE_DEFAULT_SELECTION(0.1f, 0.17f, kPi0) }; struct ConfEtaSelection : o2::framework::ConfigurableGroup { std::string prefix = std::string("EtaSelection1"); - TWOPHOTONRESONANCE_DEFAULT_SELECTION(0.4f, 0.7f) + TWOPHOTONRESONANCE_DEFAULT_SELECTION(0.4f, 0.7f, o2::constants::physics::kEta) }; #undef TWOPHOTONRESONANCE_DEFAULT_SELECTION diff --git a/PWGCF/Femto/Tasks/CMakeLists.txt b/PWGCF/Femto/Tasks/CMakeLists.txt index 6d4bb461d62..1c31864d7f7 100644 --- a/PWGCF/Femto/Tasks/CMakeLists.txt +++ b/PWGCF/Femto/Tasks/CMakeLists.txt @@ -79,6 +79,11 @@ o2physics_add_dpl_workflow(femto-pair-track-two-track-resonance PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(femto-pair-track-two-photon-resonance + SOURCES femtoPairTrackTwoPhotonResonance.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(femto-pair-v0-two-track-resonance SOURCES femtoPairV0TwoTrackResonance.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/PWGCF/Femto/Tasks/femtoPairTrackTwoPhotonResonance.cxx b/PWGCF/Femto/Tasks/femtoPairTrackTwoPhotonResonance.cxx new file mode 100644 index 00000000000..2ed5afba3c2 --- /dev/null +++ b/PWGCF/Femto/Tasks/femtoPairTrackTwoPhotonResonance.cxx @@ -0,0 +1,204 @@ +// Copyright 2019-2025 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 femtoPairTrackTwoPhotonResonance.cxx +/// \brief Task that computes correlation between tracks and resonances decaying into two photons (pi0, eta) +/// \author Anton Riedel, TU München, anton.riedel@cern.ch + +#include "PWGCF/Femto/Core/closePairRejection.h" +#include "PWGCF/Femto/Core/collisionBuilder.h" +#include "PWGCF/Femto/Core/collisionHistManager.h" +#include "PWGCF/Femto/Core/modes.h" +#include "PWGCF/Femto/Core/pairBuilder.h" +#include "PWGCF/Femto/Core/pairCleaner.h" +#include "PWGCF/Femto/Core/pairHistManager.h" +#include "PWGCF/Femto/Core/partitions.h" +#include "PWGCF/Femto/Core/photonHistManager.h" +#include "PWGCF/Femto/Core/trackBuilder.h" +#include "PWGCF/Femto/Core/trackHistManager.h" +#include "PWGCF/Femto/Core/twoPhotonResonanceBuilder.h" +#include "PWGCF/Femto/Core/twoPhotonResonanceHistManager.h" +#include "PWGCF/Femto/DataModel/FemtoTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace o2::analysis::femto; + +struct FemtoPairTrackTwoPhotonResonance { + + // setup tables + using Collisions = o2::soa::Join; + using Collision = Collisions::iterator; + + using FilteredCollisions = o2::soa::Filtered; + using FilteredCollision = FilteredCollisions::iterator; + + using FemtoTracks = o2::soa::Join; + using FemtoPhotons = o2::soa::Join; + using FemtoPi0s = o2::soa::Join; + using FemtoEtas = o2::soa::Join; + + o2::framework::SliceCache cache; + + // setup collisions + collisionbuilder::ConfCollisionSelection collisionSelection; + o2::framework::expressions::Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); + colhistmanager::ConfCollisionBinning confCollisionBinning; + + // setup tracks + trackbuilder::ConfTrackSelection1 trackSelection; + trackhistmanager::ConfTrackBinning1 confTrackBinning; + o2::framework::Partition trackPartition = MAKE_TRACK_PARTITION(trackSelection); + o2::framework::Preslice perColTracks = o2::aod::femtobase::stored::fColId; + + // setup for photon daughters (shared between pi0 and eta -- unordered, no pos/neg or species asymmetry) + photonhistmanager::ConfPhotonBinning confPhotonDauBinning; + photonhistmanager::ConfPhotonQaBinning confPhotonDauQaBinning; + + // setup pi0s + twophotonresonancebuilder::ConfPi0Selection pi0Selection; + twophotonresonancehistmanager::ConfPi0Binning confPi0Binning; + o2::framework::Partition pi0Partition = MAKE_TWOPHOTONRESONANCE_PARTITION(pi0Selection); + o2::framework::Preslice perColPi0s = o2::aod::femtobase::stored::fColId; + + // setup etas + twophotonresonancebuilder::ConfEtaSelection etaSelection; + twophotonresonancehistmanager::ConfEtaBinning confEtaBinning; + o2::framework::Partition etaPartition = MAKE_TWOPHOTONRESONANCE_PARTITION(etaSelection); + o2::framework::Preslice perColEtas = o2::aod::femtobase::stored::fColId; + + // setup pairs + pairhistmanager::ConfPairBinning confPairBinning; + pairhistmanager::ConfPairCuts confPairCuts; + paircleaner::ConfPairCleanerBinning confPairCleaner; + + // setup for track-pi0 pairs + pairbuilder::PairTrackTwoPhotonResonanceBuilder< + trackhistmanager::PrefixTrack1, + twophotonresonancehistmanager::PrefixPi0, + photonhistmanager::PrefixTwoPhotonResonanceDau1Qa, + photonhistmanager::PrefixTwoPhotonResonanceDau2Qa, + pairhistmanager::PrefixTrackPi0Se, + pairhistmanager::PrefixTrackPi0Me, + closepairrejection::PrefixTrackTwoPhotonResonanceSe, + closepairrejection::PrefixTrackTwoPhotonResonanceMe, + modes::TwoPhotonResonance::kPi0> + pairTrackPi0Builder; + + // setup for track-eta pairs + pairbuilder::PairTrackTwoPhotonResonanceBuilder< + trackhistmanager::PrefixTrack1, + twophotonresonancehistmanager::PrefixEta, + photonhistmanager::PrefixTwoPhotonResonanceDau1Qa, + photonhistmanager::PrefixTwoPhotonResonanceDau2Qa, + pairhistmanager::PrefixTrackEtaSe, + pairhistmanager::PrefixTrackEtaMe, + closepairrejection::PrefixTrackTwoPhotonResonanceSe, + closepairrejection::PrefixTrackTwoPhotonResonanceMe, + modes::TwoPhotonResonance::kEta> + pairTrackEtaBuilder; + + // setup mixing + std::vector defaultVtxBins{10, -10, 10}; + std::vector defaultMultBins{50, 0, 200}; + std::vector defaultCentBins{10, 0, 100}; + o2::framework::ColumnBinningPolicy mixBinsVtxMult{{defaultVtxBins, defaultMultBins}}; + o2::framework::ColumnBinningPolicy mixBinsVtxCent{{defaultVtxBins, defaultCentBins}}; + o2::framework::ColumnBinningPolicy mixBinsVtxMultCent{{defaultVtxBins, defaultMultBins, defaultCentBins}}; + pairhistmanager::ConfMixing confMixing; + + o2::framework::HistogramRegistry hRegistry{"FemtoTrackTwoPhotonResonance", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject}; + + // setup cpr (no-op for two-photon resonances: PCM photon daughters are not indexed into the track + // table, so there is no trajectory to compare against a track's -- see closePairRejection.h) + closepairrejection::ConfCprTrackTwoPhotonResonanceDaughter confCpr; + + void init(o2::framework::InitContext&) + { + + if (static_cast(doprocessPi0SameEvent || doprocessPi0MixedEvent) + static_cast(doprocessEtaSameEvent || doprocessEtaMixedEvent) > 1) { + LOG(fatal) << "Can only process SE/ME for pi0-tracks or eta-tracks"; + } + + // setup columnpolicy for binning + // default values are used during instantiation, so we need to explicity update them here + mixBinsVtxMult = {{confMixing.vtxBins.value, confMixing.multBins.value}}; + mixBinsVtxCent = {{confMixing.vtxBins.value, confMixing.centBins.value}}; + mixBinsVtxMultCent = {{confMixing.vtxBins.value, confMixing.multBins.value, confMixing.centBins.value}}; + + // setup histograms + auto colHistSpec = colhistmanager::makeColHistSpecMap(confCollisionBinning); + auto trackHistSpec = trackhistmanager::makeTrackHistSpecMap(confTrackBinning); + auto dauHistSpec = photonhistmanager::makePhotonHistSpecMap(confPhotonDauBinning); + auto cprHistSpec = closepairrejection::makeCprHistSpecMap(confCpr); + auto pairCleanerHistSpec = paircleaner::makePairCleanerHistSpecMap(confPairCleaner); + + // setup for pi0 + if (doprocessPi0SameEvent || doprocessPi0MixedEvent) { + auto pi0HistSpec = twophotonresonancehistmanager::makeTwoPhotonResonanceHistSpecMap(confPi0Binning); + auto pairTrackPi0HistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning, confMixing); + pairTrackPi0Builder.init(&hRegistry, confCollisionBinning, trackSelection, pi0Selection, confCpr, confMixing, confPairBinning, confPairCuts, confPhotonDauQaBinning, colHistSpec, trackHistSpec, pi0HistSpec, dauHistSpec, pairTrackPi0HistSpec, cprHistSpec, pairCleanerHistSpec); + } + + // setup for eta + if (doprocessEtaSameEvent || doprocessEtaMixedEvent) { + auto etaHistSpec = twophotonresonancehistmanager::makeTwoPhotonResonanceHistSpecMap(confEtaBinning); + auto pairTrackEtaHistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning, confMixing); + pairTrackEtaBuilder.init(&hRegistry, confCollisionBinning, trackSelection, etaSelection, confCpr, confMixing, confPairBinning, confPairCuts, confPhotonDauQaBinning, colHistSpec, trackHistSpec, etaHistSpec, dauHistSpec, pairTrackEtaHistSpec, cprHistSpec, pairCleanerHistSpec); + } + + hRegistry.print(); + }; + + void processPi0SameEvent(FilteredCollision const& col, FemtoTracks const& /*tracks*/, FemtoPi0s const& /*pi0s*/, FemtoPhotons const& photons) + { + pairTrackPi0Builder.processSameEvent(col, trackPartition, pi0Partition, photons, cache); + } + PROCESS_SWITCH(FemtoPairTrackTwoPhotonResonance, processPi0SameEvent, "Enable same event processing for tracks and pi0s", true); + + void processPi0MixedEvent(FilteredCollisions const& cols, FemtoTracks const& /*tracks*/, FemtoPi0s const& /*pi0s*/, FemtoPhotons const& photons) + { + pairTrackPi0Builder.processMixedEvent(cols, trackPartition, pi0Partition, photons, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoPairTrackTwoPhotonResonance, processPi0MixedEvent, "Enable mixed event processing for tracks and pi0s", true); + + void processEtaSameEvent(FilteredCollision const& col, FemtoTracks const& /*tracks*/, FemtoEtas const& /*etas*/, FemtoPhotons const& photons) + { + pairTrackEtaBuilder.processSameEvent(col, trackPartition, etaPartition, photons, cache); + } + PROCESS_SWITCH(FemtoPairTrackTwoPhotonResonance, processEtaSameEvent, "Enable same event processing for tracks and etas", false); + + void processEtaMixedEvent(FilteredCollisions const& cols, FemtoTracks const& /*tracks*/, FemtoEtas const& /*etas*/, FemtoPhotons const& photons) + { + pairTrackEtaBuilder.processMixedEvent(cols, trackPartition, etaPartition, photons, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoPairTrackTwoPhotonResonance, processEtaMixedEvent, "Enable mixed event processing for tracks and etas", false); +}; + +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& context) +{ + o2::framework::WorkflowSpec workflow{ + adaptAnalysisTask(context), + }; + return workflow; +}