diff --git a/PWGUD/Core/UPCPairCuts.h b/PWGUD/Core/UPCPairCuts.h new file mode 100644 index 00000000000..6b0e37adca0 --- /dev/null +++ b/PWGUD/Core/UPCPairCuts.h @@ -0,0 +1,346 @@ +// 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. + +/// \brief Functions which cut on particle pairs (decays, conversions, two-track cuts) adapted for data from UD tables +/// Based on the code "PWGCF/Core/PairCuts.h" made by Jan Fiete Grosse-Oetringhaus +/// Author: + +#ifndef PWGUD_CORE_UPCPAIRCUTS_H_ +#define PWGUD_CORE_UPCPAIRCUTS_H_ + +#include + +#include "Framework/Logger.h" +#include "Framework/HistogramRegistry.h" +#include "CommonConstants/MathConstants.h" +#include "CommonConstants/PhysicsConstants.h" + +#include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" + +using namespace o2; +using namespace o2::framework; +using namespace constants::math; + +class UPCPairCuts +{ + public: + enum Particle { Photon = 0, + K0, + Lambda, + Phi, + Rho, + ParticlesLastEntry }; + + void setHistogramRegistry(HistogramRegistry* registry) { histogramRegistry = registry; } + + void setPairCut(Particle particle, float cut) + { + LOGF(info, "Enabled pair cut for %d with value %f", static_cast(particle), cut); + mCuts[particle] = cut; + if (histogramRegistry != nullptr && histogramRegistry->contains(HIST("ControlConvResonances")) == false) { + histogramRegistry->add("ControlConvResonances", "", {HistType::kTH2F, {{6, -0.5, 5.5, "id"}, {500, -0.5, 0.5, "delta mass"}}}); + } + } + + void setTwoTrackCuts(float distance = 0.02f, float radius = 0.8f) + { + LOGF(info, "Enabled two-track cut with distance %f and radius %f", distance, radius); + mTwoTrackDistance = distance; + mTwoTrackRadius = radius; + + if (histogramRegistry != nullptr && histogramRegistry->contains(HIST("TwoTrackDistancePt_0")) == false) { + histogramRegistry->add("TwoTrackDistancePt_0", "", {HistType::kTH3F, {{100, -0.15, 0.15, "#Delta#eta"}, {100, -0.05, 0.05, "#Delta#varphi^{*}_{min}"}, {20, 0, 10, "#Delta p_{T}"}}}); + histogramRegistry->addClone("TwoTrackDistancePt_0", "TwoTrackDistancePt_1"); + } + } + + template + bool conversionCuts(T const& track1, T const& track2); + + template + bool twoTrackCut(T const& track1, T const& track2); + + protected: + float mCuts[ParticlesLastEntry] = {-1}; + float mTwoTrackDistance = -1; // distance below which the pair is flagged as to be removed + float mTwoTrackRadius = 0.8f; // radius at which the two track cuts are applied + int magField = 5; // magField: B field in kG + + HistogramRegistry* histogramRegistry = nullptr; // if set, control histograms are stored here + + template + bool conversionCut(T const& track1, T const& track2, Particle conv, double cut); + + template + double getInvMassSquared(T const& track1, double m0_1, T const& track2, double m0_2); + + template + double getInvMassSquaredFast(T const& track1, double m0_1, T const& track2, double m0_2); + + template + float getDPhiStar(T const& track1, T const& track2, float radius, int magField); +}; + +template +bool UPCPairCuts::conversionCuts(T const& track1, T const& track2) +{ + // skip if like sign + if (track1.sign() * track2.sign() > 0) { + return false; + } + + for (int i = 0; i < static_cast(ParticlesLastEntry); i++) { + Particle particle = static_cast(i); + if (mCuts[i] > 0) { + if (conversionCut(track1, track2, particle, mCuts[i])) { + return true; + } + if (particle == Lambda) { + if (conversionCut(track2, track1, particle, mCuts[i])) { + return true; + } + } + } + } + + return false; +} + +template +bool UPCPairCuts::twoTrackCut(T const& track1, T const& track2) +{ + // the variables & cut have been developed in Run 1 by the CF - HBT group + // + // Parameters: + // magField: B field in kG + + auto deta = eta(track1.px(), track1.py(), track1.pz()) - eta(track2.px(), track2.py(), track2.pz()); + + // optimization + if (std::fabs(deta) < mTwoTrackDistance * 2.5 * 3) { + // check first boundaries to see if is worth to loop and find the minimum + float dphistar1 = getDPhiStar(track1, track2, mTwoTrackRadius, magField); + float dphistar2 = getDPhiStar(track1, track2, 2.5, magField); + + const float kLimit = mTwoTrackDistance * 3; + + if (std::fabs(dphistar1) < kLimit || std::fabs(dphistar2) < kLimit || dphistar1 * dphistar2 < 0) { + float dphistarminabs = 1e5; + float dphistarmin = 1e5; + for (Double_t rad = mTwoTrackRadius; rad < 2.51; rad += 0.01) { + float dphistar = getDPhiStar(track1, track2, rad, magField); + + float dphistarabs = std::fabs(dphistar); + + if (dphistarabs < dphistarminabs) { + dphistarmin = dphistar; + dphistarminabs = dphistarabs; + } + } + + if (histogramRegistry != nullptr) { + histogramRegistry->fill(HIST("TwoTrackDistancePt_0"), deta, dphistarmin, std::fabs(track1.pt() - track2.pt())); + } + + if (dphistarminabs < mTwoTrackDistance && std::fabs(deta) < mTwoTrackDistance) { + // LOGF(debug, "Removed track pair %ld %ld with %f %f %f %f %d %f %f %d %d", track1.index(), track2.index(), deta, dphistarminabs, track1.phi2(), track1.pt(), track1.sign(), track2.phi2(), track2.pt(), track2.sign(), magField); + return true; + } + + if (histogramRegistry != nullptr) { + histogramRegistry->fill(HIST("TwoTrackDistancePt_1"), deta, dphistarmin, std::fabs(track1.pt() - track2.pt())); + } + } + } + + return false; +} + +template +bool UPCPairCuts::conversionCut(T const& track1, T const& track2, Particle conv, double cut) +{ + // LOGF(info, "pt is %f %f", track1.pt(), track2.pt()); + + if (cut < 0) { + return false; + } + + double massD1, massD2, massM; + + switch (conv) { + case Photon: + massD1 = o2::constants::physics::MassElectron; + massD2 = o2::constants::physics::MassElectron; + massM = 0; + break; + case K0: + massD1 = o2::constants::physics::MassPiPlus; + massD2 = o2::constants::physics::MassPiPlus; + massM = o2::constants::physics::MassK0; + break; + case Lambda: + massD1 = o2::constants::physics::MassProton; + massD2 = o2::constants::physics::MassPiPlus; + massM = o2::constants::physics::MassLambda0; + break; + case Phi: + massD1 = o2::constants::physics::MassKPlus; + massD2 = o2::constants::physics::MassKPlus; + massM = o2::constants::physics::MassPhi; + break; + case Rho: + massD1 = o2::constants::physics::MassPiPlus; + massD2 = o2::constants::physics::MassPiPlus; + massM = 0.770; + break; + default: + LOGF(fatal, "Particle now known"); + return false; + break; + } + + auto massC = getInvMassSquaredFast(track1, massD1, track2, massD2); + + if (std::fabs(massC - massM * massM) > cut * 5) { + return false; + } + + massC = getInvMassSquared(track1, massD1, track2, massD2); + + if (histogramRegistry != nullptr) { + histogramRegistry->fill(HIST("ControlConvResonances"), static_cast(conv), massC - massM * massM); + } + + if (massC > (massM - cut) * (massM - cut) && massC < (massM + cut) * (massM + cut)) { + return true; + } + + return false; +} + +template +double UPCPairCuts::getInvMassSquared(T const& track1, double m0_1, T const& track2, double m0_2) +{ + // calculate inv mass squared + // same can be achieved, but with more computing time with + /*TLorentzVector photon, p1, p2; + p1.SetPtEtaPhiM(triggerParticle->Pt(), triggerEta, triggerParticle->Phi(), 0.510e-3); + p2.SetPtEtaPhiM(particle->Pt(), eta[j], particle->Phi(), 0.510e-3); + photon = p1+p2; + photon.M()*/ + + float tantheta1 = 1e10; + + if (eta(track1.px(), track1.py(), track1.pz()) < -1e-10 || eta(track1.px(), track1.py(), track1.pz()) > 1e-10) { + float expTmp = std::exp(-eta(track1.px(), track1.py(), track1.pz())); + tantheta1 = 2.0 * expTmp / (1.0 - expTmp * expTmp); + } + + float tantheta2 = 1e10; + if (eta(track2.px(), track2.py(), track2.pz()) < -1e-10 || eta(track2.px(), track2.py(), track2.pz()) > 1e-10) { + float expTmp = std::exp(-eta(track2.px(), track2.py(), track2.pz())); + tantheta2 = 2.0 * expTmp / (1.0 - expTmp * expTmp); + } + + float e1squ = m0_1 * m0_1 + track1.pt() * track1.pt() * (1.0 + 1.0 / tantheta1 / tantheta1); + float e2squ = m0_2 * m0_2 + track2.pt() * track2.pt() * (1.0 + 1.0 / tantheta2 / tantheta2); + + float mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2 * (std::sqrt(e1squ * e2squ) - (track1.pt() * track2.pt() * (std::cos(phi(track1.px(), track1.py()) - phi(track2.px(), track2.py())) + 1.0 / tantheta1 / tantheta2))); + + // LOGF(debug, "%f %f %f %f %f %f %f %f %f", pt1, eta1, phi1, pt2, eta2, phi2, m0_1, m0_2, mass2); + + return mass2; +} + +template +double UPCPairCuts::getInvMassSquaredFast(T const& track1, double m0_1, T const& track2, double m0_2) +{ + // calculate inv mass squared approximately + + const float eta1 = eta(track1.px(), track1.py(), track1.pz()); + const float eta2 = eta(track2.px(), track2.py(), track2.pz()); + const float phi1 = phi(track1.px(), track1.py()); + const float phi2 = phi(track2.px(), track2.py()); + const float pt1 = track1.pt(); + const float pt2 = track2.pt(); + + float tantheta1 = 1e10f; + + if (eta1 < -1e-10f || eta1 > 1e-10f) { + float expTmp = 1.0f - eta1 + eta1 * eta1 / 2.0f - eta1 * eta1 * eta1 / 6.0f + eta1 * eta1 * eta1 * eta1 / 24.0f; + tantheta1 = 2.0f * expTmp / (1.0f - expTmp * expTmp); + } + + float tantheta2 = 1e10f; + if (eta2 < -1e-10f || eta2 > 1e-10f) { + float expTmp = 1.0f - eta2 + eta2 * eta2 / 2.0f - eta2 * eta2 * eta2 / 6.0f + eta2 * eta2 * eta2 * eta2 / 24.0f; + tantheta2 = 2.0f * expTmp / (1.0f - expTmp * expTmp); + } + + float e1squ = m0_1 * m0_1 + pt1 * pt1 * (1.0f + 1.0f / tantheta1 / tantheta1); + float e2squ = m0_2 * m0_2 + pt2 * pt2 * (1.0f + 1.0f / tantheta2 / tantheta2); + + // fold onto 0...pi + float deltaPhi = std::fabs(phi1 - phi2); + while (deltaPhi > TwoPI) { + deltaPhi -= TwoPI; + } + if (deltaPhi > PI) { + deltaPhi = TwoPI - deltaPhi; + } + + float cosDeltaPhi = 0; + if (deltaPhi < PI / 3.0f) { + cosDeltaPhi = 1.0 - deltaPhi * deltaPhi / 2 + deltaPhi * deltaPhi * deltaPhi * deltaPhi / 24; + } else if (deltaPhi < 2.0f * PI / 3.0f) { + cosDeltaPhi = -(deltaPhi - PI / 2) + 1.0 / 6 * std::pow((deltaPhi - PI / 2), 3); + } else { + cosDeltaPhi = -1.0f + 1.0f / 2.0f * (deltaPhi - PI) * (deltaPhi - PI) - 1.0f / 24.0f * std::pow(deltaPhi - PI, 4.0f); + } + + double mass2 = m0_1 * m0_1 + m0_2 * m0_2 + 2.0f * (std::sqrt(e1squ * e2squ) - (pt1 * pt2 * (cosDeltaPhi + 1.0f / tantheta1 / tantheta2))); + + // LOGF(debug, "%f %f %f %f %f %f %f %f %f", pt1, eta1, phi1, pt2, eta2, phi2, m0_1, m0_2, mass2); + + return mass2; +} + +template +float UPCPairCuts::getDPhiStar(T const& track1, T const& track2, float radius, int magField) +{ + // + // calculates dphistar + // + + auto phi1 = phi(track1.px(), track1.py()); + auto pt1 = track1.pt(); + auto charge1 = track1.sign(); + + auto phi2 = phi(track2.px(), track2.py()); + auto pt2 = track2.pt(); + auto charge2 = track2.sign(); + + float dphistar = phi1 - phi2 - charge1 * std::asin(0.015 * magField * radius / pt1) + charge2 * std::asin(0.015 * magField * radius / pt2); + + if (dphistar > PI) { + dphistar = TwoPI - dphistar; + } + if (dphistar < -PI) { + dphistar = -TwoPI - dphistar; + } + if (dphistar > PI) { // might look funny but is needed + dphistar = TwoPI - dphistar; + } + + return dphistar; +} + +#endif // PWGUD_CORE_UPCPAIRCUTS_H_ diff --git a/PWGUD/Tasks/CMakeLists.txt b/PWGUD/Tasks/CMakeLists.txt index 2f78f0629b4..a193e46587e 100644 --- a/PWGUD/Tasks/CMakeLists.txt +++ b/PWGUD/Tasks/CMakeLists.txt @@ -146,7 +146,7 @@ o2physics_add_dpl_workflow(exclusive-phi o2physics_add_dpl_workflow(upc-photonuclear-jmg SOURCES upcPhotonuclearAnalysisJMG.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::ReconstructionDataFormats O2::DetectorsBase O2::DetectorsCommonDataFormats + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore O2::ReconstructionDataFormats O2::DetectorsBase O2::DetectorsCommonDataFormats COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(exclusive-two-protons diff --git a/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx b/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx index 81834492eca..995e04a8335 100644 --- a/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx +++ b/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx @@ -11,10 +11,17 @@ /// /// \brief /// \author Josué Martínez García, josuem@cern.ch +/// \file upcPhotonuclearAnalysisJMG.cxx + +#include #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "CCDB/BasicCCDBManager.h" +#include "Framework/StepTHn.h" +#include "CommonConstants/MathConstants.h" +#include #include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/TrackSelection.h" @@ -22,38 +29,66 @@ #include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "PWGCF/Core/CorrelationContainer.h" +#include "DataFormatsParameters/GRPObject.h" #include "PWGUD/DataModel/UDTables.h" +#include "PWGUD/Core/UPCPairCuts.h" #include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace constants::math; +namespace o2::aod +{ +namespace tree +{ +DECLARE_SOA_COLUMN(PtSideA, ptSideA, std::vector); +DECLARE_SOA_COLUMN(RapSideA, rapSideA, std::vector); +DECLARE_SOA_COLUMN(PhiSideA, phiSideA, std::vector); +DECLARE_SOA_COLUMN(PtSideC, ptSideC, std::vector); +DECLARE_SOA_COLUMN(RapSideC, rapSideC, std::vector); +DECLARE_SOA_COLUMN(PhiSideC, phiSideC, std::vector); +DECLARE_SOA_COLUMN(NchSideA, nchSideA, int); +DECLARE_SOA_COLUMN(MultiplicitySideA, multiplicitySideA, int); +DECLARE_SOA_COLUMN(NchSideC, nchSideC, int); +DECLARE_SOA_COLUMN(MultiplicitySideC, multiplicitySideC, int); +} // namespace tree +DECLARE_SOA_TABLE(TREE, "AOD", "Tree", + tree::PtSideA, + tree::RapSideA, + tree::PhiSideA, + tree::PtSideC, + tree::RapSideC, + tree::PhiSideC, + tree::NchSideA, + tree::MultiplicitySideA, + tree::NchSideC, + tree::MultiplicitySideC); +} // namespace o2::aod + +static constexpr float CFGPairCutDefaults[1][5] = {{-1, -1, -1, -1, -1}}; struct upcPhotonuclearAnalysisJMG { + Produces tree; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; // Declare configurables on events/collisions - Configurable cutMyPosZMin{"cutMyPosZMin", -10., {"My collision cut"}}; - Configurable cutMyPosZMax{"cutMyPosZMax", 10., {"My collision cut"}}; - Configurable cutMyTimeZNA{"cutMyTimeZNA", 2., {"My collision cut"}}; - Configurable cutMyTimeZNC{"cutMyTimeZNC", 2., {"My collision cut"}}; + Configurable myZVtxCut{"myZVtxCut", 10., {"My collision cut"}}; + Configurable myTimeZNACut{"myTimeZNACut", 2., {"My collision cut"}}; + Configurable myTimeZNCCut{"myTimeZNCCut", 2., {"My collision cut"}}; // Declare configurables on side A gap Configurable cutAGapMyEnergyZNAMax{"cutAGapMyEnergyZNAMax", 0., {"My collision cut. A Gap"}}; - Configurable cutAGapMyAmplitudeFT0AMax{"cutAGapMyAmplitudeFT0AMax", 200., {"My collision cut. A Gap"}}; + // Configurable cutAGapMyAmplitudeFT0AMax{"cutAGapMyAmplitudeFT0AMax", 200., {"My collision cut. A Gap"}}; Configurable cutAGapMyEnergyZNCMin{"cutAGapMyEnergyZNCMin", 1., {"My collision cut. A Gap"}}; - Configurable cutAGapMyAmplitudeFT0CMin{"cutAGapMyAmplitudeFT0CMin", 0., {"My collision cut. A Gap"}}; + // Configurable cutAGapMyAmplitudeFT0CMin{"cutAGapMyAmplitudeFT0CMin", 0., {"My collision cut. A Gap"}}; // Declare configurables on side C gap Configurable cutCGapMyEnergyZNAMin{"cutCGapMyEnergyZNAMin", 1., {"My collision cut. C Gap"}}; - Configurable cutCGapMyAmplitudeFT0AMin{"cutCGapMyAmplitudeFT0AMin", 0., {"My collision cut. A Gap"}}; + // Configurable cutCGapMyAmplitudeFT0AMin{"cutCGapMyAmplitudeFT0AMin", 0., {"My collision cut. A Gap"}}; Configurable cutCGapMyEnergyZNCMax{"cutCGapMyEnergyZNCMax", 0., {"My collision cut. C Gap"}}; - Configurable cutCGapMyAmplitudeFT0CMax{"cutCGapMyAmplitudeFT0CMax", 200., {"My collision cut. A Gap"}}; - // Declare configurables on both side gap - Configurable cutBothGapMyEnergyZNAMax{"cutBothGapMyEnergyZNAMax", 0., {"My collision cut. Both Gap"}}; - Configurable cutBothGapMyAmplitudeFT0AMax{"cutBothGapMyAmplitudeFT0AMax", 200., {"My collision cut. A Gap"}}; - Configurable cutBothGapMyEnergyZNCMax{"cutBothGapMyEnergyZNCMax", 0., {"My collision cut. Both Gap"}}; - Configurable cutBothGapMyAmplitudeFT0CMax{"cutBothGapMyAmplitudeFT0CMax", 200., {"My collision cut. A Gap"}}; + // Configurable cutCGapMyAmplitudeFT0CMax{"cutCGapMyAmplitudeFT0CMax", 200., {"My collision cut. A Gap"}}; // Declare configurables on tracks Configurable cutMyptMin{"cutMyptMin", 0.15, {"My Track cut"}}; Configurable cutMyptMax{"cutMyptMax", 10., {"My Track cut"}}; @@ -72,10 +107,35 @@ struct upcPhotonuclearAnalysisJMG { Configurable cutMyTPCNClsCrossedRowsOverNClsFindableMin{"cutMyTPCNClsCrossedRowsOverNClsFindableMin", 0.8f, {"My Track cut"}}; Configurable cutMyTPCNClsOverFindableNClsMin{"cutMyTPCNClsOverFindableNClsMin", 0.5f, {"My Track cut"}}; Configurable cutMyTPCChi2NclMax{"cutMyTPCChi2NclMax", 4.f, {"My Track cut"}}; + Configurable> cfgPairCut{"cfgPairCut", + {CFGPairCutDefaults[0], + 5, + {"Photon", "K0", "Lambda", "Phi", "Rho"}}, + "Pair cuts on various particles"}; + Configurable cfgTwoTrackCut{"cfgTwoTrackCut", -1, {"Two track cut"}}; + ConfigurableAxis axisVertex{"axisVertex", {10, -10, 10}, "vertex axis for histograms"}; + ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {72, -constants::math::PIHalf, constants::math::PIHalf * 3}, "delta phi axis for histograms"}; + ConfigurableAxis axisDeltaEta{"axisDeltaEta", {40, -2, 2}, "delta eta axis for histograms"}; + ConfigurableAxis axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt trigger axis for histograms"}; + ConfigurableAxis axisPtAssoc{"axisPtAssoc", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0}, "pt associated axis for histograms"}; + ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110.1}, "multiplicity / multiplicity axis for histograms"}; + ConfigurableAxis axisVertexEfficiency{"axisVertexEfficiency", {10, -10, 10}, "vertex axis for efficiency histograms"}; + ConfigurableAxis axisEtaEfficiency{"axisEtaEfficiency", {20, -1.0, 1.0}, "eta axis for efficiency histograms"}; + ConfigurableAxis axisPtEfficiency{"axisPtEfficiency", {VARIABLE_WIDTH, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0}, "pt axis for efficiency histograms"}; + + Filter collisionZVtxFilter = nabs(aod::collision::posZ) < myZVtxCut; + Filter collisionZNTimeFilter = nabs(aod::udzdc::timeZNA) < myTimeZNACut && nabs(aod::udzdc::timeZNC) < myTimeZNCCut; - using FullSGUDCollision = soa::Join::iterator; + using FullSGUDCollision = soa::Filtered>; using FullUDTracks = soa::Join; + // Output definitions + OutputObj same{"sameEvent"}; + OutputObj mixed{"mixedEvent"}; + + UPCPairCuts mPairCuts; + bool doPairCuts = false; + void init(InitContext const&) { const AxisSpec axisCollision{4, -0.5, 3.5}; @@ -83,9 +143,9 @@ struct upcPhotonuclearAnalysisJMG { const AxisSpec axisPt{402, -0.05, 20.05}; const AxisSpec axisP{402, -10.05, 10.05}; const AxisSpec axisTPCSignal{802, -0.05, 400.05}; - const AxisSpec axisPhi{64, -2 * o2::constants::math::PI, 2 * o2::constants::math::PI}; + const AxisSpec axisPhi{64, -2 * PI, 2 * PI}; const AxisSpec axisEta{50, -1.2, 1.2}; - const AxisSpec axisNch{101, -0.5, 100.5}; + const AxisSpec axisNch{201, -0.5, 200.5}; const AxisSpec axisZNEnergy{1002, -0.5, 500.5}; const AxisSpec axisZNTime{21, -10.5, 10.5}; const AxisSpec axisFT0Amplitud{201, -0.5, 200.5}; @@ -93,6 +153,21 @@ struct upcPhotonuclearAnalysisJMG { const AxisSpec axisChi2NCls{100, 0, 50}; const AxisSpec axisTPCNClsCrossedRowsMin{100, -0.05, 2.05}; + histos.add("yields", "multiplicity vs pT vs eta", {HistType::kTH3F, {{100, 0, 100, "multiplicity"}, {40, 0, 20, "p_{T}"}, {100, -2, 2, "#eta"}}}); + histos.add("etaphi", "multiplicity vs eta vs phi", {HistType::kTH3F, {{100, 0, 100, "multiplicity"}, {100, -2, 2, "#eta"}, {200, 0, 2 * PI, "#varphi"}}}); + + const int maxMixBin = axisMultiplicity->size() * axisVertex->size(); + histos.add("eventcount", "bin", {HistType::kTH1F, {{maxMixBin + 2, -2.5, -0.5 + maxMixBin, "bin"}}}); + mPairCuts.setHistogramRegistry(&histos); + if (cfgPairCut->get("Photon") > 0 || cfgPairCut->get("K0") > 0 || cfgPairCut->get("Lambda") > 0 || + cfgPairCut->get("Phi") > 0 || cfgPairCut->get("Rho") > 0) { + mPairCuts.setPairCut(UPCPairCuts::Photon, cfgPairCut->get("Photon")); + mPairCuts.setPairCut(UPCPairCuts::K0, cfgPairCut->get("K0")); + mPairCuts.setPairCut(UPCPairCuts::Lambda, cfgPairCut->get("Lambda")); + mPairCuts.setPairCut(UPCPairCuts::Phi, cfgPairCut->get("Phi")); + mPairCuts.setPairCut(UPCPairCuts::Rho, cfgPairCut->get("Rho")); + doPairCuts = true; + } histos.add("Events/hCountCollisions", "0 total - 1 side A - 2 side C - 3 both side; Number of analysed collision; counts", kTH1F, {axisCollision}); // histos to selection gap in side A @@ -112,8 +187,9 @@ struct upcPhotonuclearAnalysisJMG { histos.add("Tracks/SGsideA/hTrackTPCChi2NCls", "#it{N Clusters Chi2 TPC} distribution; #it{N Clusters Chi2 TPC}; counts", kTH1F, {axisChi2NCls}); histos.add("Tracks/SGsideA/hTrackITSNClsTPCCls", "#it{ITS Clusters vs TPC Clusters}; #it{TPC Clusters}; #it{ITS Clusters}", kTH2F, {axisNCls, axisNCls}); - histos.add("Events/SGsideA/hTrackZVtx", "vertex in z; z (cm); counts", kTH1F, {axisZvtx}); + histos.add("Events/SGsideA/hZVtx", "vertex in z; z (cm); counts", kTH1F, {axisZvtx}); histos.add("Events/SGsideA/hNch", "#it{Charged Tracks Multiplicity} distribution; #it{Charged Tracks Multiplicity}; counts", kTH1F, {axisNch}); + histos.add("Events/SGsideA/hMultiplicity", "#it{Multiplicity} distribution; #it{Multiplicity}; counts", kTH1F, {axisNch}); histos.add("Events/SGsideA/hPtVSNch", "#it{ #LT p_{T} #GT } vs #it{Charged Tracks Multiplicity}; #it{Charged Tracks Multiplicity}; #it{ #LT p_{T} #GT }", kTH2F, {axisNch, axisPt}); histos.add("Events/SGsideA/hEnergyZNA", "Energy in side A distribution; Energy in side A; counts", kTH1F, {axisZNEnergy}); histos.add("Events/SGsideA/hEnergyZNC", "Energy in side C distribution; Energy in side C; counts", kTH1F, {axisZNEnergy}); @@ -141,8 +217,9 @@ struct upcPhotonuclearAnalysisJMG { histos.add("Tracks/SGsideC/hTrackTPCChi2NCls", "#it{N Clusters Chi2 TPC} distribution; #it{N Clusters Chi2 TPC}; counts", kTH1F, {axisChi2NCls}); histos.add("Tracks/SGsideC/hTrackITSNClsTPCCls", "#it{ITS Clusters vs TPC Clusters}; #it{TPC Clusters}; #it{ITS Clusters}", kTH2F, {axisNCls, axisNCls}); - histos.add("Events/SGsideC/hTrackZVtx", "vertex in z; z (cm); counts", kTH1F, {axisZvtx}); + histos.add("Events/SGsideC/hZVtx", "vertex in z; z (cm); counts", kTH1F, {axisZvtx}); histos.add("Events/SGsideC/hNch", "#it{Charged Tracks Multiplicity} distribution; #it{Charged Tracks Multiplicity}; counts", kTH1F, {axisNch}); + histos.add("Events/SGsideC/hMultiplicity", "#it{Multiplicity} distribution; #it{Multiplicity}; counts", kTH1F, {axisNch}); histos.add("Events/SGsideC/hPtVSNch", "#it{ #LT p_{T} #GT } vs #it{Charged Tracks Multiplicity}; #it{Charged Tracks Multiplicity}; #it{ #LT p_{T} #GT }", kTH2F, {axisNch, axisPt}); histos.add("Events/SGsideC/hEnergyZNA", "Energy in side A distribution; Energy in side A; counts", kTH1F, {axisZNEnergy}); histos.add("Events/SGsideC/hEnergyZNC", "Energy in side C distribution; Energy in side C; counts", kTH1F, {axisZNEnergy}); @@ -153,43 +230,35 @@ struct upcPhotonuclearAnalysisJMG { histos.add("Events/SGsideC/hAmplitudFT0A", "Amplitud in side A distribution; Amplitud in side A; counts", kTH1F, {axisFT0Amplitud}); histos.add("Events/SGsideC/hAmplitudFT0C", "Amplitud in side C distribution; Amplitud in side C; counts", kTH1F, {axisFT0Amplitud}); - // histos to selection gap in both sides - histos.add("Tracks/SGsideBoth/hTrackPt", "#it{p_{T}} distribution; #it{p_{T}}; counts", kTH1F, {axisPt}); - histos.add("Tracks/SGsideBoth/hTrackPhi", "#it{#phi} distribution; #it{#phi}; counts", kTH1F, {axisPhi}); - histos.add("Tracks/SGsideBoth/hTrackEta", "#it{#eta} distribution; #it{#eta}; counts", kTH1F, {axisEta}); - histos.add("Tracks/SGsideBoth/hTrackTPCSignnalP", "#it{TPC dE/dx vs p}; #it{p*charge}; #it{TPC dE/dx}", kTH2F, {axisP, axisTPCSignal}); - histos.add("Tracks/SGsideBoth/hTrackITSNCls", "#it{N Clusters ITS} distribution; #it{N Clusters ITS}; counts", kTH1F, {axisNCls}); - histos.add("Tracks/SGsideBoth/hTrackITSChi2NCls", "#it{N Clusters Chi2 ITS} distribution; #it{N Clusters Chi2 ITS}; counts", kTH1F, {axisChi2NCls}); - histos.add("Tracks/SGsideBoth/hTrackNClsCrossedRowsOverNCls", "#it{NClsCrossedRows/FindableNCls} distribution in TPC; #it{NClsCrossedRows/FindableNCls}; counts", kTH1F, {axisTPCNClsCrossedRowsMin}); - histos.add("Tracks/SGsideBoth/hTrackTPCNClsCrossedRows", "#it{Number of crossed TPC Rows} distribution; #it{Number of crossed TPC Rows}; counts", kTH1F, {axisNCls}); - histos.add("Tracks/SGsideBoth/hTrackTPCNClsFindable", "#it{Findable TPC clusters for this track} distribution; #it{Findable TPC clusters for this track}; counts", kTH1F, {axisNCls}); - histos.add("Tracks/SGsideBoth/hTrackTPCChi2NCls", "#it{N Clusters Chi2 TPC} distribution; #it{N Clusters Chi2 TPC}; counts", kTH1F, {axisChi2NCls}); - histos.add("Tracks/SGsideBoth/hTrackITSNClsTPCCls", "#it{ITS Clusters vs TPC Clusters}; #it{TPC Clusters}; #it{ITS Clusters}", kTH2F, {axisNCls, axisNCls}); - - histos.add("Events/SGsideBoth/hTrackZVtx", "vertex in z; z (cm); counts", kTH1F, {axisZvtx}); - histos.add("Events/SGsideBoth/hNch", "#it{Charged Tracks Multiplicity} distribution; #it{Charged Tracks Multiplicity}; counts", kTH1F, {axisNch}); - histos.add("Events/SGsideBoth/hPtVSNch", "#it{ #LT p_{T} #GT } vs #it{Charged Tracks Multiplicity}; #it{Charged Tracks Multiplicity}; #it{ #LT p_{T} #GT }", kTH2F, {axisNch, axisPt}); - histos.add("Events/SGsideBoth/hEnergyZNA", "Energy in side A distribution; Energy in side A; counts", kTH1F, {axisZNEnergy}); - histos.add("Events/SGsideBoth/hEnergyZNC", "Energy in side C distribution; Energy in side C; counts", kTH1F, {axisZNEnergy}); - histos.add("Events/SGsideBoth/hEnergyRelationSides", "Energy in side A vs energy in side C; Energy in side A; Energy in side C", kTH2F, {axisZNEnergy, axisZNEnergy}); - histos.add("Events/SGsideBoth/hTimeZNA", "Time in side A distribution; Time in side A; counts", kTH1F, {axisZNTime}); - histos.add("Events/SGsideBoth/hTimeZNC", "Time in side C distribution; Time in side C; counts", kTH1F, {axisZNTime}); - histos.add("Events/SGsideBoth/hTimeRelationSides", "Time in side A vs time in side C; Time in side A; Time in side C", kTH2F, {axisZNTime, axisZNTime}); - histos.add("Events/SGsideBoth/hAmplitudFT0A", "Amplitud in side A distribution; Amplitud in side A; counts", kTH1F, {axisFT0Amplitud}); - histos.add("Events/SGsideBoth/hAmplitudFT0C", "Amplitud in side C distribution; Amplitud in side C; counts", kTH1F, {axisFT0Amplitud}); + std::vector corrAxis = {{axisDeltaEta, "#Delta#eta"}, + {axisPtAssoc, "p_{T} (GeV/c)"}, + {axisPtTrigger, "p_{T} (GeV/c)"}, + {axisMultiplicity, "multiplicity / multiplicity"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisVertex, "z-vtx (cm)"}}; + std::vector effAxis = {{axisEtaEfficiency, "#eta"}, + {axisEtaEfficiency, "#eta"}, + {axisPtEfficiency, "p_{T} (GeV/c)"}, + {axisVertexEfficiency, "z-vtx (cm)"}}; + same.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); + mixed.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); } - template - bool isGlobalCollisionCut(C const& collision) - { - if (collision.posZ() < cutMyPosZMin || cutMyPosZMax < collision.posZ()) { - return false; - } - if ((std::abs(collision.timeZNA()) < cutMyTimeZNA && std::abs(collision.timeZNC()) < cutMyTimeZNC) == false) { - return false; - } - return true; - } + std::vector vtxBinsEdges{VARIABLE_WIDTH, -10.0f, -7.0f, -5.0f, -2.0f, 0.0f, 2.0f, 5.0f, 7.0f, 10.0f}; + std::vector multBinsEdges{VARIABLE_WIDTH, 0.0f, 50.0f, 400.0f}; + SliceCache cache; + + // Binning only on PosZ without multiplicity + using BinningType = ColumnBinningPolicy; + BinningType bindingOnVtx{{vtxBinsEdges}, true}; + SameKindPair pairs{bindingOnVtx, 5, -1, &cache}; + + // ColumnBinningPolicy bindingOnVtx{{vtxBinsEdges, multBinsEdges}, true}; + + // SameKindPair, + // FullUDTracks, + // ColumnBinningPolicy> + // pair{bindingOnVtx, 5, -1, &cache}; template bool isCollisionCutSG(CSG const& collision, int SideGap) @@ -199,25 +268,17 @@ struct upcPhotonuclearAnalysisJMG { if ((collision.energyCommonZNA() < cutAGapMyEnergyZNAMax && collision.energyCommonZNC() >= cutAGapMyEnergyZNCMin) == false) { // 0n - A side && Xn - C Side return false; } - if ((collision.totalFT0AmplitudeA() < cutAGapMyAmplitudeFT0AMax && collision.totalFT0AmplitudeC() >= cutAGapMyAmplitudeFT0CMin) == false) { - return false; - } + // if ((collision.totalFT0AmplitudeA() < cutAGapMyAmplitudeFT0AMax && collision.totalFT0AmplitudeC() >= cutAGapMyAmplitudeFT0CMin) == false) { + // return false; + // } break; case 1: // Gap in C side if ((collision.energyCommonZNA() >= cutCGapMyEnergyZNAMin && collision.energyCommonZNC() < cutCGapMyEnergyZNCMax) == false) { // Xn - A side && 0n - C Side return false; } - if ((collision.totalFT0AmplitudeA() >= cutCGapMyAmplitudeFT0AMin && collision.totalFT0AmplitudeC() < cutCGapMyAmplitudeFT0CMax) == false) { - return false; - } - break; - case 2: // Gap in Both Sides - if ((collision.energyCommonZNA() < cutBothGapMyEnergyZNAMax && collision.energyCommonZNC() < cutBothGapMyEnergyZNCMax) == false) { // 0n - A side && 0n - C Side - return false; - } - if ((collision.totalFT0AmplitudeA() < cutBothGapMyAmplitudeFT0AMax && collision.totalFT0AmplitudeC() < cutBothGapMyAmplitudeFT0CMax) == false) { - return false; - } + // if ((collision.totalFT0AmplitudeA() >= cutCGapMyAmplitudeFT0AMin && collision.totalFT0AmplitudeC() < cutCGapMyAmplitudeFT0CMax) == false) { + // return false; + // } break; } return true; @@ -281,19 +342,67 @@ struct upcPhotonuclearAnalysisJMG { return true; } - void processSG(FullSGUDCollision const& reconstructedCollision, FullUDTracks const& reconstructedTracks) + template + void fillQAUD(const TTracks tracks) + { + for (auto& track : tracks) { + histos.fill(HIST("yields"), tracks.size(), track.pt(), eta(track.px(), track.py(), track.pz())); + histos.fill(HIST("etaphi"), tracks.size(), eta(track.px(), track.py(), track.pz()), phi(track.px(), track.py())); + } + } + + template + bool fillCollisionUD(TTarget target, float multiplicity) + { + target->fillEvent(multiplicity, CorrelationContainer::kCFStepAll); + target->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + return true; + } + + template + void fillCorrelationsUD(TTarget target, const TTracks tracks1, const TTracks tracks2, float multiplicity, float posZ) + { + multiplicity = tracks1.size(); + for (auto& track1 : tracks1) { + if (isTrackCut(track1) == false) { + continue; + } + target->getTriggerHist()->Fill(CorrelationContainer::kCFStepReconstructed, track1.pt(), multiplicity, posZ, 1.0); + for (auto& track2 : tracks2) { + if (track1 == track2) { + continue; + } + if (isTrackCut(track2) == false) { + continue; + } + if (doPairCuts && mPairCuts.conversionCuts(track1, track2)) { + continue; + } + float deltaPhi = phi(track1.px(), track1.py()) - phi(track2.px(), track2.py()); + if (deltaPhi > 1.5f * PI) { + deltaPhi -= TwoPI; + } + if (deltaPhi < -PIHalf) { + deltaPhi += TwoPI; + } + target->getPairHist()->Fill(CorrelationContainer::kCFStepReconstructed, eta(track1.px(), track1.py(), track1.pz()) - eta(track2.px(), track2.py(), track2.pz()), track2.pt(), track1.pt(), multiplicity, deltaPhi, posZ, 1.0); + } + } + } + + void processSG(FullSGUDCollision::iterator const& reconstructedCollision, FullUDTracks const& reconstructedTracks) { histos.fill(HIST("Events/hCountCollisions"), 0); - int SGside = reconstructedCollision.gapSide(); + int sgSide = reconstructedCollision.gapSide(); int nTracksCharged = 0; float sumPt = 0; + std::vector vTrackPtSideA, vTrackEtaSideA, vTrackPhiSideA; + std::vector vTrackPtSideC, vTrackEtaSideC, vTrackPhiSideC; + int nTracksChargedSideA(-222), nTracksChargedSideC(-222); + int multiplicitySideA(-222), multiplicitySideC(-222); - if (isGlobalCollisionCut(reconstructedCollision) == false) { - return; - } - - switch (SGside) { - case 0: // for side A + switch (sgSide) { + case 0: // gap for side A if (isCollisionCutSG(reconstructedCollision, 0) == false) { return; } @@ -304,7 +413,7 @@ struct upcPhotonuclearAnalysisJMG { histos.fill(HIST("Events/SGsideA/hTimeZNA"), reconstructedCollision.timeZNA()); histos.fill(HIST("Events/SGsideA/hTimeZNC"), reconstructedCollision.timeZNC()); histos.fill(HIST("Events/SGsideA/hTimeRelationSides"), reconstructedCollision.timeZNA(), reconstructedCollision.timeZNC()); - histos.fill(HIST("Events/SGsideA/hTrackZVtx"), reconstructedCollision.posZ()); + histos.fill(HIST("Events/SGsideA/hZVtx"), reconstructedCollision.posZ()); histos.fill(HIST("Events/SGsideA/hAmplitudFT0A"), reconstructedCollision.totalFT0AmplitudeA()); histos.fill(HIST("Events/SGsideA/hAmplitudFT0C"), reconstructedCollision.totalFT0AmplitudeC()); for (auto& track : reconstructedTracks) { @@ -318,6 +427,9 @@ struct upcPhotonuclearAnalysisJMG { histos.fill(HIST("Tracks/SGsideA/hTrackPhi"), phi(track.px(), track.py())); histos.fill(HIST("Tracks/SGsideA/hTrackEta"), eta(track.px(), track.py(), track.pz())); histos.fill(HIST("Tracks/SGsideA/hTrackTPCSignnalP"), momentum(track.px(), track.py(), track.pz()) * track.sign(), track.tpcSignal()); + vTrackPtSideA.push_back(track.pt()); + vTrackEtaSideA.push_back(eta(track.px(), track.py(), track.pz())); + vTrackPhiSideA.push_back(phi(track.px(), track.py())); histos.fill(HIST("Tracks/SGsideA/hTrackITSNCls"), track.itsNCls()); histos.fill(HIST("Tracks/SGsideA/hTrackITSChi2NCls"), track.itsChi2NCl()); @@ -333,10 +445,13 @@ struct upcPhotonuclearAnalysisJMG { } } histos.fill(HIST("Events/SGsideA/hNch"), nTracksCharged); + histos.fill(HIST("Events/SGsideA/hMultiplicity"), reconstructedTracks.size()); histos.fill(HIST("Events/SGsideA/hPtVSNch"), nTracksCharged, (sumPt / nTracksCharged)); + nTracksChargedSideA = nTracksCharged; + multiplicitySideA = reconstructedTracks.size(); nTracksCharged = sumPt = 0; break; - case 1: // for side C + case 1: // gap for side C if (isCollisionCutSG(reconstructedCollision, 1) == false) { return; } @@ -347,7 +462,7 @@ struct upcPhotonuclearAnalysisJMG { histos.fill(HIST("Events/SGsideC/hTimeZNA"), reconstructedCollision.timeZNA()); histos.fill(HIST("Events/SGsideC/hTimeZNC"), reconstructedCollision.timeZNC()); histos.fill(HIST("Events/SGsideC/hTimeRelationSides"), reconstructedCollision.timeZNA(), reconstructedCollision.timeZNC()); - histos.fill(HIST("Events/SGsideC/hTrackZVtx"), reconstructedCollision.posZ()); + histos.fill(HIST("Events/SGsideC/hZVtx"), reconstructedCollision.posZ()); histos.fill(HIST("Events/SGsideC/hAmplitudFT0A"), reconstructedCollision.totalFT0AmplitudeA()); histos.fill(HIST("Events/SGsideC/hAmplitudFT0C"), reconstructedCollision.totalFT0AmplitudeC()); for (auto& track : reconstructedTracks) { @@ -361,6 +476,9 @@ struct upcPhotonuclearAnalysisJMG { histos.fill(HIST("Tracks/SGsideC/hTrackPhi"), phi(track.px(), track.py())); histos.fill(HIST("Tracks/SGsideC/hTrackEta"), eta(track.px(), track.py(), track.pz())); histos.fill(HIST("Tracks/SGsideC/hTrackTPCSignnalP"), momentum(track.px(), track.py(), track.pz()) * track.sign(), track.tpcSignal()); + vTrackPtSideC.push_back(track.pt()); + vTrackEtaSideC.push_back(eta(track.px(), track.py(), track.pz())); + vTrackPhiSideC.push_back(phi(track.px(), track.py())); histos.fill(HIST("Tracks/SGsideC/hTrackITSNCls"), track.itsNCls()); histos.fill(HIST("Tracks/SGsideC/hTrackITSChi2NCls"), track.itsChi2NCl()); @@ -376,54 +494,90 @@ struct upcPhotonuclearAnalysisJMG { } } histos.fill(HIST("Events/SGsideC/hNch"), nTracksCharged); + histos.fill(HIST("Events/SGsideC/hMultiplicity"), reconstructedTracks.size()); histos.fill(HIST("Events/SGsideC/hPtVSNch"), nTracksCharged, (sumPt / nTracksCharged)); + nTracksChargedSideC = nTracksCharged; + multiplicitySideC = reconstructedTracks.size(); nTracksCharged = sumPt = 0; break; - case 2: // for both sides - if (isCollisionCutSG(reconstructedCollision, 2) == false) { + default: + return; + break; + } + tree(vTrackPtSideA, vTrackEtaSideA, vTrackPhiSideA, vTrackPtSideC, vTrackEtaSideC, vTrackPhiSideC, nTracksChargedSideA, multiplicitySideA, nTracksChargedSideC, multiplicitySideC); + // nTracksChargedSideA = nTracksChargedSideC = multiplicitySideA = multiplicitySideC = 0; + } + PROCESS_SWITCH(upcPhotonuclearAnalysisJMG, processSG, "Process in UD tables", true); + + void processSame(FullSGUDCollision::iterator const& reconstructedCollision, FullUDTracks const& reconstructedTracks) + { + int sgSide = reconstructedCollision.gapSide(); + + float multiplicity = reconstructedTracks.size(); + switch (sgSide) { + case 0: // gap for side A + if (isCollisionCutSG(reconstructedCollision, 0) == false) { return; } - histos.fill(HIST("Events/hCountCollisions"), 3); - histos.fill(HIST("Events/SGsideBoth/hEnergyZNA"), reconstructedCollision.energyCommonZNA()); - histos.fill(HIST("Events/SGsideBoth/hEnergyZNC"), reconstructedCollision.energyCommonZNC()); - histos.fill(HIST("Events/SGsideBoth/hEnergyRelationSides"), reconstructedCollision.energyCommonZNA(), reconstructedCollision.energyCommonZNC()); - histos.fill(HIST("Events/SGsideBoth/hTimeZNA"), reconstructedCollision.timeZNA()); - histos.fill(HIST("Events/SGsideBoth/hTimeZNC"), reconstructedCollision.timeZNC()); - histos.fill(HIST("Events/SGsideBoth/hTimeRelationSides"), reconstructedCollision.timeZNA(), reconstructedCollision.timeZNC()); - histos.fill(HIST("Events/SGsideBoth/hTrackZVtx"), reconstructedCollision.posZ()); - histos.fill(HIST("Events/SGsideBoth/hAmplitudFT0A"), reconstructedCollision.totalFT0AmplitudeA()); - histos.fill(HIST("Events/SGsideBoth/hAmplitudFT0C"), reconstructedCollision.totalFT0AmplitudeC()); - for (auto& track : reconstructedTracks) { - if (track.sign() == 1 || track.sign() == -1) { - if (isTrackCut(track) == false) { - continue; - } - nTracksCharged++; - sumPt += track.pt(); - histos.fill(HIST("Tracks/SGsideBoth/hTrackPt"), track.pt()); - histos.fill(HIST("Tracks/SGsideBoth/hTrackPhi"), phi(track.px(), track.py())); - histos.fill(HIST("Tracks/SGsideBoth/hTrackEta"), eta(track.px(), track.py(), track.pz())); - histos.fill(HIST("Tracks/SGsideBoth/hTrackTPCSignnalP"), momentum(track.px(), track.py(), track.pz()) * track.sign(), track.tpcSignal()); - - histos.fill(HIST("Tracks/SGsideBoth/hTrackITSNCls"), track.itsNCls()); - histos.fill(HIST("Tracks/SGsideBoth/hTrackITSChi2NCls"), track.itsChi2NCl()); - histos.fill(HIST("Tracks/SGsideBoth/hTrackNClsCrossedRowsOverNCls"), (static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable()))); - histos.fill(HIST("Tracks/SGsideBoth/hTrackTPCNClsCrossedRows"), track.tpcNClsCrossedRows()); - histos.fill(HIST("Tracks/SGsideBoth/hTrackTPCNClsFindable"), track.tpcNClsFindable()); - histos.fill(HIST("Tracks/SGsideBoth/hTrackTPCChi2NCls"), track.tpcChi2NCl()); - histos.fill(HIST("Tracks/SGsideBoth/hTrackITSNClsTPCCls"), track.tpcNClsFindable() - track.tpcNClsFindableMinusFound(), track.itsNCls()); - } + if (fillCollisionUD(same, multiplicity) == false) { + return; } - histos.fill(HIST("Events/SGsideBoth/hNch"), nTracksCharged); - histos.fill(HIST("Events/SGsideBoth/hPtVSNch"), nTracksCharged, (sumPt / nTracksCharged)); - nTracksCharged = sumPt = 0; + LOGF(info, "Filling same events"); + histos.fill(HIST("eventcount"), -2); + fillQAUD(reconstructedTracks); + fillCorrelationsUD(same, reconstructedTracks, reconstructedTracks, multiplicity, reconstructedCollision.posZ()); + break; + case 1: // gap for side C + // if (isCollisionCutSG(reconstructedCollision, 1) == false) { + // return; + // } break; default: return; break; } } - PROCESS_SWITCH(upcPhotonuclearAnalysisJMG, processSG, "Process in UD tables", true); + + PROCESS_SWITCH(upcPhotonuclearAnalysisJMG, processSame, "Process same event", true); + + void processMixed(FullSGUDCollision::iterator const& reconstructedCollision) + { + int sgSide = reconstructedCollision.gapSide(); + // int sgSide = 0; + + for (auto& [collision1, tracks1, collision2, tracks2] : pairs) { + if (collision1.size() == 0 || collision2.size() == 0) { + LOGF(info, "One or both collisions are empty."); + continue; + } + float multiplicity = tracks1.size(); + LOGF(info, "Filling mixed events"); + switch (sgSide) { + case 0: // gap for side A + if (isCollisionCutSG(reconstructedCollision, 0) == false) { + return; + } + if (fillCollisionUD(mixed, multiplicity) == false) { + return; + } + // LOGF(info, ">>> Bin of collision: ", bindingOnVtx.getBin({collision1.posZ()})); + // histos.fill(HIST("eventcount"), bindingOnVtx.getBin({collision1.posZ(), collision1.totalFT0AmplitudeC()})); + histos.fill(HIST("eventcount"), bindingOnVtx.getBin({collision1.posZ()})); + fillCorrelationsUD(mixed, tracks1, tracks2, multiplicity, collision1.posZ()); + break; + case 1: // gap for side C + // if (isCollisionCutSG(reconstructedCollision, 1) == false) { + // return; + // } + break; + default: + return; + break; + } + } + } + + PROCESS_SWITCH(upcPhotonuclearAnalysisJMG, processMixed, "Process mixed events", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)