diff --git a/ALICE3/DataModel/OTFStrangeness.h b/ALICE3/DataModel/OTFStrangeness.h index 03f180bb0ff..2c985873bac 100644 --- a/ALICE3/DataModel/OTFStrangeness.h +++ b/ALICE3/DataModel/OTFStrangeness.h @@ -27,6 +27,12 @@ #include #include +namespace o2::upgrade::pid +{ +static constexpr float NoPidSignal = -999.f; +static constexpr float NoPidSignalThreshold = -990.f; +} // namespace o2::upgrade::pid + namespace o2::aod { namespace otfcascade @@ -75,6 +81,221 @@ using UpgradeCascade = UpgradeCascades::iterator; DECLARE_SOA_TABLE(A3CascadeMcLabels, "AOD", "A3CASCADEMCLABELS", o2::soa::Index<>, otfcascade::McParticleId); +namespace casc_pid +{ + +// Xi +DECLARE_SOA_COLUMN(NSigmaInnerTofXiBachPi, nSigmaInnerTofXiBachPi, float); +DECLARE_SOA_COLUMN(NSigmaInnerTofXiPosPr, nSigmaInnerTofXiPosPr, float); +DECLARE_SOA_COLUMN(NSigmaInnerTofXiPosPi, nSigmaInnerTofXiPosPi, float); +DECLARE_SOA_COLUMN(NSigmaInnerTofXiNegPr, nSigmaInnerTofXiNegPr, float); +DECLARE_SOA_COLUMN(NSigmaInnerTofXiNegPi, nSigmaInnerTofXiNegPi, float); +DECLARE_SOA_DYNAMIC_COLUMN(HasInnerTofXiBachPi, hasInnerTofXiBachPi, + [](float nSigma) -> bool { return (nSigma > o2::upgrade::pid::NoPidSignalThreshold); }); +DECLARE_SOA_DYNAMIC_COLUMN(HasInnerTofXiPosPr, hasInnerTofXiPosPr, + [](float nSigma) -> bool { return (nSigma > o2::upgrade::pid::NoPidSignalThreshold); }); +DECLARE_SOA_DYNAMIC_COLUMN(HasInnerTofXiPosPi, hasInnerTofXiPosPi, + [](float nSigma) -> bool { return (nSigma > o2::upgrade::pid::NoPidSignalThreshold); }); +DECLARE_SOA_DYNAMIC_COLUMN(HasInnerTofXiNegPr, hasInnerTofXiNegPr, + [](float nSigma) -> bool { return (nSigma > o2::upgrade::pid::NoPidSignalThreshold); }); +DECLARE_SOA_DYNAMIC_COLUMN(HasInnerTofXiNegPi, hasInnerTofXiNegPi, + [](float nSigma) -> bool { return (nSigma > o2::upgrade::pid::NoPidSignalThreshold); }); + +DECLARE_SOA_COLUMN(NSigmaOuterTofXiBachPi, nSigmaOuterTofXiBachPi, float); +DECLARE_SOA_COLUMN(NSigmaOuterTofXiPosPr, nSigmaOuterTofXiPosPr, float); +DECLARE_SOA_COLUMN(NSigmaOuterTofXiPosPi, nSigmaOuterTofXiPosPi, float); +DECLARE_SOA_COLUMN(NSigmaOuterTofXiNegPr, nSigmaOuterTofXiNegPr, float); +DECLARE_SOA_COLUMN(NSigmaOuterTofXiNegPi, nSigmaOuterTofXiNegPi, float); +DECLARE_SOA_DYNAMIC_COLUMN(HasOuterTofXiBachPi, hasOuterTofXiBachPi, + [](float nSigma) -> bool { return (nSigma > o2::upgrade::pid::NoPidSignalThreshold); }); +DECLARE_SOA_DYNAMIC_COLUMN(HasOuterTofXiPosPr, hasOuterTofXiPosPr, + [](float nSigma) -> bool { return (nSigma > o2::upgrade::pid::NoPidSignalThreshold); }); +DECLARE_SOA_DYNAMIC_COLUMN(HasOuterTofXiPosPi, hasOuterTofXiPosPi, + [](float nSigma) -> bool { return (nSigma > o2::upgrade::pid::NoPidSignalThreshold); }); +DECLARE_SOA_DYNAMIC_COLUMN(HasOuterTofXiNegPr, hasOuterTofXiNegPr, + [](float nSigma) -> bool { return (nSigma > o2::upgrade::pid::NoPidSignalThreshold); }); +DECLARE_SOA_DYNAMIC_COLUMN(HasOuterTofXiNegPi, hasOuterTofXiNegPi, + [](float nSigma) -> bool { return (nSigma > o2::upgrade::pid::NoPidSignalThreshold); }); + +DECLARE_SOA_COLUMN(ExpectedInnerTofXiBachPi, expectedInnerTofXiBachPi, float); +DECLARE_SOA_COLUMN(ExpectedInnerTofXiPosPr, expectedInnerTofXiPosPr, float); +DECLARE_SOA_COLUMN(ExpectedInnerTofXiPosPi, expectedInnerTofXiPosPi, float); +DECLARE_SOA_COLUMN(ExpectedInnerTofXiNegPr, expectedInnerTofXiNegPr, float); +DECLARE_SOA_COLUMN(ExpectedInnerTofXiNegPi, expectedInnerTofXiNegPi, float); + +DECLARE_SOA_COLUMN(ExpectedOuterTofXiBachPi, expectedOuterTofXiBachPi, float); +DECLARE_SOA_COLUMN(ExpectedOuterTofXiPosPr, expectedOuterTofXiPosPr, float); +DECLARE_SOA_COLUMN(ExpectedOuterTofXiPosPi, expectedOuterTofXiPosPi, float); +DECLARE_SOA_COLUMN(ExpectedOuterTofXiNegPr, expectedOuterTofXiNegPr, float); +DECLARE_SOA_COLUMN(ExpectedOuterTofXiNegPi, expectedOuterTofXiNegPi, float); + +DECLARE_SOA_COLUMN(MeasuredInnerTofXiBachPi, measuredInnerTofXiBachPi, float); +DECLARE_SOA_COLUMN(MeasuredInnerTofXiPosPr, measuredInnerTofXiPosPr, float); +DECLARE_SOA_COLUMN(MeasuredInnerTofXiPosPi, measuredInnerTofXiPosPi, float); +DECLARE_SOA_COLUMN(MeasuredInnerTofXiNegPr, measuredInnerTofXiNegPr, float); +DECLARE_SOA_COLUMN(MeasuredInnerTofXiNegPi, measuredInnerTofXiNegPi, float); + +DECLARE_SOA_COLUMN(MeasuredOuterTofXiBachPi, measuredOuterTofXiBachPi, float); +DECLARE_SOA_COLUMN(MeasuredOuterTofXiPosPr, measuredOuterTofXiPosPr, float); +DECLARE_SOA_COLUMN(MeasuredOuterTofXiPosPi, measuredOuterTofXiPosPi, float); +DECLARE_SOA_COLUMN(MeasuredOuterTofXiNegPr, measuredOuterTofXiNegPr, float); +DECLARE_SOA_COLUMN(MeasuredOuterTofXiNegPi, measuredOuterTofXiNegPi, float); + +// Omega +DECLARE_SOA_COLUMN(NSigmaInnerTofOmegaBachKa, nSigmaInnerTofOmegaBachKa, float); +DECLARE_SOA_COLUMN(NSigmaInnerTofOmegaPosPr, nSigmaInnerTofOmegaPosPr, float); +DECLARE_SOA_COLUMN(NSigmaInnerTofOmegaPosPi, nSigmaInnerTofOmegaPosPi, float); +DECLARE_SOA_COLUMN(NSigmaInnerTofOmegaNegPr, nSigmaInnerTofOmegaNegPr, float); +DECLARE_SOA_COLUMN(NSigmaInnerTofOmegaNegPi, nSigmaInnerTofOmegaNegPi, float); +DECLARE_SOA_DYNAMIC_COLUMN(HasInnerTofOmegaBachKa, hasInnerTofOmegaBachKa, + [](float nSigma) -> bool { return (nSigma > o2::upgrade::pid::NoPidSignalThreshold); }); +DECLARE_SOA_DYNAMIC_COLUMN(HasInnerTofOmegaPosPr, hasInnerTofOmegaPosPr, + [](float nSigma) -> bool { return (nSigma > o2::upgrade::pid::NoPidSignalThreshold); }); +DECLARE_SOA_DYNAMIC_COLUMN(HasInnerTofOmegaPosPi, hasInnerTofOmegaPosPi, + [](float nSigma) -> bool { return (nSigma > o2::upgrade::pid::NoPidSignalThreshold); }); +DECLARE_SOA_DYNAMIC_COLUMN(HasInnerTofOmegaNegPr, hasInnerTofOmegaNegPr, + [](float nSigma) -> bool { return (nSigma > o2::upgrade::pid::NoPidSignalThreshold); }); +DECLARE_SOA_DYNAMIC_COLUMN(HasInnerTofOmegaNegPi, hasInnerTofOmegaNegPi, + [](float nSigma) -> bool { return (nSigma > o2::upgrade::pid::NoPidSignalThreshold); }); + +DECLARE_SOA_COLUMN(NSigmaOuterTofOmegaBachKa, nSigmaOuterTofOmegaBachKa, float); +DECLARE_SOA_COLUMN(NSigmaOuterTofOmegaPosPr, nSigmaOuterTofOmegaPosPr, float); +DECLARE_SOA_COLUMN(NSigmaOuterTofOmegaPosPi, nSigmaOuterTofOmegaPosPi, float); +DECLARE_SOA_COLUMN(NSigmaOuterTofOmegaNegPr, nSigmaOuterTofOmegaNegPr, float); +DECLARE_SOA_COLUMN(NSigmaOuterTofOmegaNegPi, nSigmaOuterTofOmegaNegPi, float); +DECLARE_SOA_DYNAMIC_COLUMN(HasOuterTofOmegaBachKa, hasOuterTofOmegaBachKa, + [](float nSigma) -> bool { return (nSigma > o2::upgrade::pid::NoPidSignalThreshold); }); +DECLARE_SOA_DYNAMIC_COLUMN(HasOuterTofOmegaPosPr, hasOuterTofOmegaPosPr, + [](float nSigma) -> bool { return (nSigma > o2::upgrade::pid::NoPidSignalThreshold); }); +DECLARE_SOA_DYNAMIC_COLUMN(HasOuterTofOmegaPosPi, hasOuterTofOmegaPosPi, + [](float nSigma) -> bool { return (nSigma > o2::upgrade::pid::NoPidSignalThreshold); }); +DECLARE_SOA_DYNAMIC_COLUMN(HasOuterTofOmegaNegPr, hasOuterTofOmegaNegPr, + [](float nSigma) -> bool { return (nSigma > o2::upgrade::pid::NoPidSignalThreshold); }); +DECLARE_SOA_DYNAMIC_COLUMN(HasOuterTofOmegaNegPi, hasOuterTofOmegaNegPi, + [](float nSigma) -> bool { return (nSigma > o2::upgrade::pid::NoPidSignalThreshold); }); + +DECLARE_SOA_COLUMN(ExpectedInnerTofOmegaBachKa, expectedInnerTofOmegaBachKa, float); +DECLARE_SOA_COLUMN(ExpectedInnerTofOmegaPosPr, expectedInnerTofOmegaPosPr, float); +DECLARE_SOA_COLUMN(ExpectedInnerTofOmegaPosPi, expectedInnerTofOmegaPosPi, float); +DECLARE_SOA_COLUMN(ExpectedInnerTofOmegaNegPr, expectedInnerTofOmegaNegPr, float); +DECLARE_SOA_COLUMN(ExpectedInnerTofOmegaNegPi, expectedInnerTofOmegaNegPi, float); + +DECLARE_SOA_COLUMN(ExpectedOuterTofOmegaBachKa, expectedOuterTofOmegaBachKa, float); +DECLARE_SOA_COLUMN(ExpectedOuterTofOmegaPosPr, expectedOuterTofOmegaPosPr, float); +DECLARE_SOA_COLUMN(ExpectedOuterTofOmegaPosPi, expectedOuterTofOmegaPosPi, float); +DECLARE_SOA_COLUMN(ExpectedOuterTofOmegaNegPr, expectedOuterTofOmegaNegPr, float); +DECLARE_SOA_COLUMN(ExpectedOuterTofOmegaNegPi, expectedOuterTofOmegaNegPi, float); + +DECLARE_SOA_COLUMN(MeasuredInnerTofOmegaBachKa, measuredInnerTofOmegaBachKa, float); +DECLARE_SOA_COLUMN(MeasuredInnerTofOmegaPosPr, measuredInnerTofOmegaPosPr, float); +DECLARE_SOA_COLUMN(MeasuredInnerTofOmegaPosPi, measuredInnerTofOmegaPosPi, float); +DECLARE_SOA_COLUMN(MeasuredInnerTofOmegaNegPr, measuredInnerTofOmegaNegPr, float); +DECLARE_SOA_COLUMN(MeasuredInnerTofOmegaNegPi, measuredInnerTofOmegaNegPi, float); + +DECLARE_SOA_COLUMN(MeasuredOuterTofOmegaBachKa, measuredOuterTofOmegaBachKa, float); +DECLARE_SOA_COLUMN(MeasuredOuterTofOmegaPosPr, measuredOuterTofOmegaPosPr, float); +DECLARE_SOA_COLUMN(MeasuredOuterTofOmegaPosPi, measuredOuterTofOmegaPosPi, float); +DECLARE_SOA_COLUMN(MeasuredOuterTofOmegaNegPr, measuredOuterTofOmegaNegPr, float); +DECLARE_SOA_COLUMN(MeasuredOuterTofOmegaNegPi, measuredOuterTofOmegaNegPi, float); + +} // namespace casc_pid + +DECLARE_SOA_TABLE(A3XiInnerTofPid, "AOD", "A3XIITOFPID", + casc_pid::NSigmaInnerTofXiBachPi, + casc_pid::NSigmaInnerTofXiPosPr, + casc_pid::NSigmaInnerTofXiPosPi, + casc_pid::NSigmaInnerTofXiNegPr, + casc_pid::NSigmaInnerTofXiNegPi, + casc_pid::HasInnerTofXiBachPi, + casc_pid::HasInnerTofXiPosPr, + casc_pid::HasInnerTofXiPosPi, + casc_pid::HasInnerTofXiNegPr, + casc_pid::HasInnerTofXiNegPi); + +DECLARE_SOA_TABLE(A3XiOuterTofPid, "AOD", "A3XIOTOFPID", + casc_pid::NSigmaOuterTofXiBachPi, + casc_pid::NSigmaOuterTofXiPosPr, + casc_pid::NSigmaOuterTofXiPosPi, + casc_pid::NSigmaOuterTofXiNegPr, + casc_pid::NSigmaOuterTofXiNegPi, + casc_pid::HasOuterTofXiBachPi, + casc_pid::HasOuterTofXiPosPr, + casc_pid::HasOuterTofXiPosPi, + casc_pid::HasOuterTofXiNegPr, + casc_pid::HasOuterTofXiNegPi); + +DECLARE_SOA_TABLE(A3OmegaInnerTofPid, "AOD", "A3OMITOFPID", + casc_pid::NSigmaInnerTofOmegaBachKa, + casc_pid::NSigmaInnerTofOmegaPosPr, + casc_pid::NSigmaInnerTofOmegaPosPi, + casc_pid::NSigmaInnerTofOmegaNegPr, + casc_pid::NSigmaInnerTofOmegaNegPi, + casc_pid::HasInnerTofOmegaBachKa, + casc_pid::HasInnerTofOmegaPosPr, + casc_pid::HasInnerTofOmegaPosPi, + casc_pid::HasInnerTofOmegaNegPr, + casc_pid::HasInnerTofOmegaNegPi); + +DECLARE_SOA_TABLE(A3OmegaOuterTofPid, "AOD", "A3OMOTOFPID", + casc_pid::NSigmaOuterTofOmegaBachKa, + casc_pid::NSigmaOuterTofOmegaPosPr, + casc_pid::NSigmaOuterTofOmegaPosPi, + casc_pid::NSigmaOuterTofOmegaNegPr, + casc_pid::NSigmaOuterTofOmegaNegPi, + casc_pid::HasOuterTofOmegaBachKa, + casc_pid::HasOuterTofOmegaPosPr, + casc_pid::HasOuterTofOmegaPosPi, + casc_pid::HasOuterTofOmegaNegPr, + casc_pid::HasOuterTofOmegaNegPi); + +DECLARE_SOA_TABLE(A3XiExpectedInnerTimes, "AOD", "A3XIITIMES", + casc_pid::ExpectedInnerTofXiBachPi, + casc_pid::ExpectedInnerTofXiPosPr, + casc_pid::ExpectedInnerTofXiPosPi, + casc_pid::ExpectedInnerTofXiNegPr, + casc_pid::ExpectedInnerTofXiNegPi, + casc_pid::MeasuredInnerTofXiBachPi, + casc_pid::MeasuredInnerTofXiPosPr, + casc_pid::MeasuredInnerTofXiPosPi, + casc_pid::MeasuredInnerTofXiNegPr, + casc_pid::MeasuredInnerTofXiNegPi); + +DECLARE_SOA_TABLE(A3XiExpectedOuterTimes, "AOD", "A3XIOTIMES", + casc_pid::ExpectedOuterTofXiBachPi, + casc_pid::ExpectedOuterTofXiPosPr, + casc_pid::ExpectedOuterTofXiPosPi, + casc_pid::ExpectedOuterTofXiNegPr, + casc_pid::ExpectedOuterTofXiNegPi, + casc_pid::MeasuredOuterTofXiBachPi, + casc_pid::MeasuredOuterTofXiPosPr, + casc_pid::MeasuredOuterTofXiPosPi, + casc_pid::MeasuredOuterTofXiNegPr, + casc_pid::MeasuredOuterTofXiNegPi); + +DECLARE_SOA_TABLE(A3OmegaExpectedInnerTimes, "AOD", "A3OMITIMES", + casc_pid::ExpectedInnerTofOmegaBachKa, + casc_pid::ExpectedInnerTofOmegaPosPr, + casc_pid::ExpectedInnerTofOmegaPosPi, + casc_pid::ExpectedInnerTofOmegaNegPr, + casc_pid::ExpectedInnerTofOmegaNegPi, + casc_pid::MeasuredInnerTofOmegaBachKa, + casc_pid::MeasuredInnerTofOmegaPosPr, + casc_pid::MeasuredInnerTofOmegaPosPi, + casc_pid::MeasuredInnerTofOmegaNegPr, + casc_pid::MeasuredInnerTofOmegaNegPi); + +DECLARE_SOA_TABLE(A3OmegaExpectedOuterTimes, "AOD", "A3OMOTIMES", + casc_pid::ExpectedOuterTofOmegaBachKa, + casc_pid::ExpectedOuterTofOmegaPosPr, + casc_pid::ExpectedOuterTofOmegaPosPi, + casc_pid::ExpectedOuterTofOmegaNegPr, + casc_pid::ExpectedOuterTofOmegaNegPi, + casc_pid::MeasuredOuterTofOmegaBachKa, + casc_pid::MeasuredOuterTofOmegaPosPr, + casc_pid::MeasuredOuterTofOmegaPosPi, + casc_pid::MeasuredOuterTofOmegaNegPr, + casc_pid::MeasuredOuterTofOmegaNegPi); + namespace otfv0 { DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! diff --git a/ALICE3/TableProducer/CMakeLists.txt b/ALICE3/TableProducer/CMakeLists.txt index 233088b6d5e..0d8a80520a8 100644 --- a/ALICE3/TableProducer/CMakeLists.txt +++ b/ALICE3/TableProducer/CMakeLists.txt @@ -70,3 +70,8 @@ o2physics_add_dpl_workflow(alice3strangenessfinder SOURCES alice3strangenessFinder.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::ALICE3Core COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(alice3-strangeness-tof-pid + SOURCES alice3StrangenessTofPid.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::ALICE3Core + COMPONENT_NAME Analysis) diff --git a/ALICE3/TableProducer/alice3StrangenessTofPid.cxx b/ALICE3/TableProducer/alice3StrangenessTofPid.cxx new file mode 100644 index 00000000000..3d48351bee5 --- /dev/null +++ b/ALICE3/TableProducer/alice3StrangenessTofPid.cxx @@ -0,0 +1,579 @@ +// 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 alice3StrangenessTofPid.cxx +/// \brief This task produces tof strangeness pid tables +/// \author Jesper Karlsson Gumprecht +/// + +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "ALICE3/DataModel/OTFStrangeness.h" +#include "ALICE3/DataModel/tracksAlice3.h" +#include "ALICE3/Utils/a3StrangenessTofPidHelper.h" +#include "Common/Core/trackUtilities.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::upgrade::stratofpid; + +using CascTofResults = StrangenessTofResults; +using Alice3Tracks = soa::Join; +using FullCascadeCandidates = soa::Join; +using Alice3Collision = soa::Join::iterator; + +struct Alice3StrangenessTofPid { + Produces tableA3XiInnerTofPid; // contains xi strangeness iTOF nsigma + Produces tableA3XiOuterTofPid; // contains xi strangeness oTOF nsigma + Produces tableA3OmegaInnerTofPid; // contains omega strangeness iTOF nsigma + Produces tableA3OmegaOuterTofPid; // contains omega strangeness oTOF nsigma + Produces tableA3XiExpectedInnerTimes; // contains xi strangeness iTOF info + Produces tableA3XiExpectedOuterTimes; // contains xi strangeness oTOF info + Produces tableA3OmegaExpectedInnerTimes; // contains omega strangeness iTOF info + Produces tableA3OmegaExpectedOuterTimes; // contains omega strangeness oTOF info + + struct : ConfigurableGroup { + ConfigurableAxis axisNSigma{"axisNSigma", {200, -10, 10}, "N sigma axis"}; + ConfigurableAxis axisCollisionTime{"axisCollisionTime", {200, -1e-3, 1e-3}, "Time delta axis"}; + ConfigurableAxis axisTimeDelta{"axisTimeDelta", {300, -1500, 1500}, "Time delta axis"}; + ConfigurableAxis axisTime{"axisTime", {1000, 0, 10000}, "Time axis"}; + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "pt axis for QA histograms"}; + } axes; + + struct : ConfigurableGroup { + std::string prefix = "cfgTof"; + + // Time Of Flight + Configurable innerRadius{"innerRadius", 21., "Radius of iTOF (cm)"}; + Configurable innerResolution{"innerResolution", 20., "Timing resolution of iTOF (ps)"}; + Configurable outerRadius{"outerRadius", 92., "Radius of oTOF (cm)"}; + Configurable outerResolution{"outerResolution", 20., "Timing resolution of oTOF (ps)"}; + } cfgTof; + + struct : ConfigurableGroup { + std::string prefix = "produce"; + + // Tables + Configurable tableInnerNSigmaXi{"tableInnerNSigmaXi", true, "Produce NSigma tables for xi candidate"}; + Configurable tableOuterNSigmaXi{"tableOuterNSigmaXi", true, "Produce NSigma tables for xi candidate"}; + Configurable tableInnerExpectedTimesXi{"tableInnerExpectedTimesXi", false, "Produce expected and measured times tables for xi candidate"}; + Configurable tableOuterExpectedTimesXi{"tableOuterExpectedTimesXi", false, "Produce expected and measured times tables for xi candidate"}; + Configurable tableInnerNSigmaOmega{"tableInnerNSigmaOmega", true, "Produce NSigma tables for omega candidate"}; + Configurable tableOuterNSigmaOmega{"tableOuterNSigmaOmega", true, "Produce NSigma tables for omega candidate"}; + Configurable tableInnerExpectedTimesOmega{"tableInnerExpectedTimesOmega", false, "Produce expected and measured times tables for omega candidate"}; + Configurable tableOuterExpectedTimesOmega{"tableOuterExpectedTimesOmega", false, "Produce expected and measured times tables for omega candidate"}; + + // Histograms + Configurable histosXi{"histosXi", true, "Produce histograms for xi candidates"}; + Configurable histosAntiXi{"histosAntiXi", true, "Produce histograms for anti xi candidates"}; + Configurable histosOmega{"histosOmega", true, "Produce histograms for omega candidates"}; + Configurable histosAntiOmega{"histosAntiOmega", true, "Produce histograms for anti omega candidates"}; + + } produce; + + Configurable magneticField{"magneticField", 20.0f, "Magnetic field (in kilogauss)"}; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + StrangenessTofPid tofPidCasc; + Service pdgDB{}; + static constexpr float NanoToPico = 1e+3; + static constexpr std::array ParentTrackCovMatrix{}; + + void init(InitContext&) + { + // Todo: First try and get from tofpid task + tofPidCasc.setResolution(cfgTof.innerResolution, cfgTof.outerResolution); + tofPidCasc.setRadius(cfgTof.innerRadius, cfgTof.innerResolution); + tofPidCasc.setMagneticField(magneticField); + + if (doprocessCascades) { + if (produce.histosXi) { + histos.add("Xi/hInnerArrivalTimeDeltaNeg", "hInnerArrivalTimeDeltaNeg", kTH1D, {{axes.axisTimeDelta}}); + histos.add("Xi/hInnerArrivalTimeDeltaPos", "hInnerArrivalTimeDeltaPos", kTH1D, {{axes.axisTimeDelta}}); + histos.add("Xi/hInnerArrivalTimeDeltaBach", "hInnerArrivalTimeDeltaBach", kTH1D, {{axes.axisTimeDelta}}); + histos.add("Xi/hOuterArrivalTimeDeltaNeg", "hOuterArrivalTimeDeltaNeg", kTH1D, {{axes.axisTimeDelta}}); + histos.add("Xi/hOuterArrivalTimeDeltaPos", "hOuterArrivalTimeDeltaPos", kTH1D, {{axes.axisTimeDelta}}); + histos.add("Xi/hOuterArrivalTimeDeltaBach", "hOuterArrivalTimeDeltaBach", kTH1D, {{axes.axisTimeDelta}}); + + histos.add("Xi/hInnerNSigmaNeg", "hInnerNSigmaNeg", kTH1D, {{axes.axisNSigma}}); + histos.add("Xi/hInnerNSigmaPos", "hInnerNSigmaPos", kTH1D, {{axes.axisNSigma}}); + histos.add("Xi/hInnerNSigmaBach", "hInnerNSigmaBach", kTH1D, {{axes.axisNSigma}}); + histos.add("Xi/hOuterNSigmaNeg", "hOuterNSigmaNeg", kTH1D, {{axes.axisNSigma}}); + histos.add("Xi/hOuterNSigmaPos", "hOuterNSigmaPos", kTH1D, {{axes.axisNSigma}}); + histos.add("Xi/hOuterNSigmaBach", "hOuterNSigmaBach", kTH1D, {{axes.axisNSigma}}); + + histos.add("Xi/hInnerExpectedArrivalTimeNeg", "hInnerExpectedArrivalTimeNeg", kTH1D, {{axes.axisTime}}); + histos.add("Xi/hInnerExpectedArrivalTimePos", "hInnerExpectedArrivalTimePos", kTH1D, {{axes.axisTime}}); + histos.add("Xi/hInnerExpectedArrivalTimeBach", "hInnerExpectedArrivalTimeBach", kTH1D, {{axes.axisTime}}); + histos.add("Xi/hOuterExpectedArrivalTimeNeg", "hOuterExpectedArrivalTimeNeg", kTH1D, {{axes.axisTime}}); + histos.add("Xi/hOuterExpectedArrivalTimePos", "hOuterExpectedArrivalTimePos", kTH1D, {{axes.axisTime}}); + histos.add("Xi/hOuterExpectedArrivalTimeBach", "hOuterExpectedArrivalTimeBach", kTH1D, {{axes.axisTime}}); + + histos.add("Xi/hInnerMeasuredArrivalTimeNeg", "hInnerMeasuredArrivalTimeNeg", kTH1D, {{axes.axisTime}}); + histos.add("Xi/hInnerMeasuredArrivalTimePos", "hInnerMeasuredArrivalTimePos", kTH1D, {{axes.axisTime}}); + histos.add("Xi/hInnerMeasuredArrivalTimeBach", "hInnerMeasuredArrivalTimeBach", kTH1D, {{axes.axisTime}}); + histos.add("Xi/hOuterMeasuredArrivalTimeNeg", "hOuterMeasuredArrivalTimeNeg", kTH1D, {{axes.axisTime}}); + histos.add("Xi/hOuterMeasuredArrivalTimePos", "hOuterMeasuredArrivalTimePos", kTH1D, {{axes.axisTime}}); + histos.add("Xi/hOuterMeasuredArrivalTimeBach", "hOuterMeasuredArrivalTimeBach", kTH1D, {{axes.axisTime}}); + + histos.add("Xi/hInnerMeasuredVsExpectedArrivalTimeNeg", "hInnerMeasuredVsExpectedArrivalTimeNeg;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + histos.add("Xi/hInnerMeasuredVsExpectedArrivalTimePos", "hInnerMeasuredVsExpectedArrivalTimePos;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + histos.add("Xi/hInnerMeasuredVsExpectedArrivalTimeBach", "hInnerMeasuredVsExpectedArrivalTimeBach;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + histos.add("Xi/hOuterMeasuredVsExpectedArrivalTimeNeg", "hOuterMeasuredVsExpectedArrivalTimeNeg;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + histos.add("Xi/hOuterMeasuredVsExpectedArrivalTimePos", "hOuterMeasuredVsExpectedArrivalTimePos;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + histos.add("Xi/hOuterMeasuredVsExpectedArrivalTimeBach", "hOuterMeasuredVsExpectedArrivalTimeBach;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + } + + if (produce.histosAntiXi) { + histos.add("AntiXi/hInnerArrivalTimeDeltaNeg", "hInnerArrivalTimeDeltaNeg", kTH1D, {{axes.axisTimeDelta}}); + histos.add("AntiXi/hInnerArrivalTimeDeltaPos", "hInnerArrivalTimeDeltaPos", kTH1D, {{axes.axisTimeDelta}}); + histos.add("AntiXi/hInnerArrivalTimeDeltaBach", "hInnerArrivalTimeDeltaBach", kTH1D, {{axes.axisTimeDelta}}); + histos.add("AntiXi/hOuterArrivalTimeDeltaNeg", "hOuterArrivalTimeDeltaNeg", kTH1D, {{axes.axisTimeDelta}}); + histos.add("AntiXi/hOuterArrivalTimeDeltaPos", "hOuterArrivalTimeDeltaPos", kTH1D, {{axes.axisTimeDelta}}); + histos.add("AntiXi/hOuterArrivalTimeDeltaBach", "hOuterArrivalTimeDeltaBach", kTH1D, {{axes.axisTimeDelta}}); + + histos.add("AntiXi/hInnerNSigmaNeg", "hInnerNSigmaNeg", kTH1D, {{axes.axisNSigma}}); + histos.add("AntiXi/hInnerNSigmaPos", "hInnerNSigmaPos", kTH1D, {{axes.axisNSigma}}); + histos.add("AntiXi/hInnerNSigmaBach", "hInnerNSigmaBach", kTH1D, {{axes.axisNSigma}}); + histos.add("AntiXi/hOuterNSigmaNeg", "hOuterNSigmaNeg", kTH1D, {{axes.axisNSigma}}); + histos.add("AntiXi/hOuterNSigmaPos", "hOuterNSigmaPos", kTH1D, {{axes.axisNSigma}}); + histos.add("AntiXi/hOuterNSigmaBach", "hOuterNSigmaBach", kTH1D, {{axes.axisNSigma}}); + + histos.add("AntiXi/hInnerExpectedArrivalTimeNeg", "hInnerExpectedArrivalTimeNeg", kTH1D, {{axes.axisTime}}); + histos.add("AntiXi/hInnerExpectedArrivalTimePos", "hInnerExpectedArrivalTimePos", kTH1D, {{axes.axisTime}}); + histos.add("AntiXi/hInnerExpectedArrivalTimeBach", "hInnerExpectedArrivalTimeBach", kTH1D, {{axes.axisTime}}); + histos.add("AntiXi/hOuterExpectedArrivalTimeNeg", "hOuterExpectedArrivalTimeNeg", kTH1D, {{axes.axisTime}}); + histos.add("AntiXi/hOuterExpectedArrivalTimePos", "hOuterExpectedArrivalTimePos", kTH1D, {{axes.axisTime}}); + histos.add("AntiXi/hOuterExpectedArrivalTimeBach", "hOuterExpectedArrivalTimeBach", kTH1D, {{axes.axisTime}}); + + histos.add("AntiXi/hInnerMeasuredArrivalTimeNeg", "hInnerMeasuredArrivalTimeNeg", kTH1D, {{axes.axisTime}}); + histos.add("AntiXi/hInnerMeasuredArrivalTimePos", "hInnerMeasuredArrivalTimePos", kTH1D, {{axes.axisTime}}); + histos.add("AntiXi/hInnerMeasuredArrivalTimeBach", "hInnerMeasuredArrivalTimeBach", kTH1D, {{axes.axisTime}}); + histos.add("AntiXi/hOuterMeasuredArrivalTimeNeg", "hOuterMeasuredArrivalTimeNeg", kTH1D, {{axes.axisTime}}); + histos.add("AntiXi/hOuterMeasuredArrivalTimePos", "hOuterMeasuredArrivalTimePos", kTH1D, {{axes.axisTime}}); + histos.add("AntiXi/hOuterMeasuredArrivalTimeBach", "hOuterMeasuredArrivalTimeBach", kTH1D, {{axes.axisTime}}); + + histos.add("AntiXi/hInnerMeasuredVsExpectedArrivalTimeNeg", "hInnerMeasuredVsExpectedArrivalTimeNeg;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + histos.add("AntiXi/hInnerMeasuredVsExpectedArrivalTimePos", "hInnerMeasuredVsExpectedArrivalTimePos;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + histos.add("AntiXi/hInnerMeasuredVsExpectedArrivalTimeBach", "hInnerMeasuredVsExpectedArrivalTimeBach;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + histos.add("AntiXi/hOuterMeasuredVsExpectedArrivalTimeNeg", "hOuterMeasuredVsExpectedArrivalTimeNeg;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + histos.add("AntiXi/hOuterMeasuredVsExpectedArrivalTimePos", "hOuterMeasuredVsExpectedArrivalTimePos;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + histos.add("AntiXi/hOuterMeasuredVsExpectedArrivalTimeBach", "hOuterMeasuredVsExpectedArrivalTimeBach;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + } + + if (produce.histosOmega) { + histos.add("Omega/hInnerArrivalTimeDeltaNeg", "hInnerArrivalTimeDeltaNeg", kTH1D, {{axes.axisTimeDelta}}); + histos.add("Omega/hInnerArrivalTimeDeltaPos", "hInnerArrivalTimeDeltaPos", kTH1D, {{axes.axisTimeDelta}}); + histos.add("Omega/hInnerArrivalTimeDeltaBach", "hInnerArrivalTimeDeltaBach", kTH1D, {{axes.axisTimeDelta}}); + histos.add("Omega/hOuterArrivalTimeDeltaNeg", "hOuterArrivalTimeDeltaNeg", kTH1D, {{axes.axisTimeDelta}}); + histos.add("Omega/hOuterArrivalTimeDeltaPos", "hOuterArrivalTimeDeltaPos", kTH1D, {{axes.axisTimeDelta}}); + histos.add("Omega/hOuterArrivalTimeDeltaBach", "hOuterArrivalTimeDeltaBach", kTH1D, {{axes.axisTimeDelta}}); + + histos.add("Omega/hInnerNSigmaNeg", "hInnerNSigmaNeg", kTH1D, {{axes.axisNSigma}}); + histos.add("Omega/hInnerNSigmaPos", "hInnerNSigmaPos", kTH1D, {{axes.axisNSigma}}); + histos.add("Omega/hInnerNSigmaBach", "hInnerNSigmaBach", kTH1D, {{axes.axisNSigma}}); + histos.add("Omega/hOuterNSigmaNeg", "hOuterNSigmaNeg", kTH1D, {{axes.axisNSigma}}); + histos.add("Omega/hOuterNSigmaPos", "hOuterNSigmaPos", kTH1D, {{axes.axisNSigma}}); + histos.add("Omega/hOuterNSigmaBach", "hOuterNSigmaBach", kTH1D, {{axes.axisNSigma}}); + + histos.add("Omega/hInnerExpectedArrivalTimeNeg", "hInnerExpectedArrivalTimeNeg", kTH1D, {{axes.axisTime}}); + histos.add("Omega/hInnerExpectedArrivalTimePos", "hInnerExpectedArrivalTimePos", kTH1D, {{axes.axisTime}}); + histos.add("Omega/hInnerExpectedArrivalTimeBach", "hInnerExpectedArrivalTimeBach", kTH1D, {{axes.axisTime}}); + histos.add("Omega/hOuterExpectedArrivalTimeNeg", "hOuterExpectedArrivalTimeNeg", kTH1D, {{axes.axisTime}}); + histos.add("Omega/hOuterExpectedArrivalTimePos", "hOuterExpectedArrivalTimePos", kTH1D, {{axes.axisTime}}); + histos.add("Omega/hOuterExpectedArrivalTimeBach", "hOuterExpectedArrivalTimeBach", kTH1D, {{axes.axisTime}}); + + histos.add("Omega/hInnerMeasuredArrivalTimeNeg", "hInnerMeasuredArrivalTimeNeg", kTH1D, {{axes.axisTime}}); + histos.add("Omega/hInnerMeasuredArrivalTimePos", "hInnerMeasuredArrivalTimePos", kTH1D, {{axes.axisTime}}); + histos.add("Omega/hInnerMeasuredArrivalTimeBach", "hInnerMeasuredArrivalTimeBach", kTH1D, {{axes.axisTime}}); + histos.add("Omega/hOuterMeasuredArrivalTimeNeg", "hOuterMeasuredArrivalTimeNeg", kTH1D, {{axes.axisTime}}); + histos.add("Omega/hOuterMeasuredArrivalTimePos", "hOuterMeasuredArrivalTimePos", kTH1D, {{axes.axisTime}}); + histos.add("Omega/hOuterMeasuredArrivalTimeBach", "hOuterMeasuredArrivalTimeBach", kTH1D, {{axes.axisTime}}); + + histos.add("Omega/hInnerMeasuredVsExpectedArrivalTimeNeg", "hInnerMeasuredVsExpectedArrivalTimeNeg;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + histos.add("Omega/hInnerMeasuredVsExpectedArrivalTimePos", "hInnerMeasuredVsExpectedArrivalTimePos;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + histos.add("Omega/hInnerMeasuredVsExpectedArrivalTimeBach", "hInnerMeasuredVsExpectedArrivalTimeBach;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + histos.add("Omega/hOuterMeasuredVsExpectedArrivalTimeNeg", "hOuterMeasuredVsExpectedArrivalTimeNeg;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + histos.add("Omega/hOuterMeasuredVsExpectedArrivalTimePos", "hOuterMeasuredVsExpectedArrivalTimePos;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + histos.add("Omega/hOuterMeasuredVsExpectedArrivalTimeBach", "hOuterMeasuredVsExpectedArrivalTimeBach;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + } + + if (produce.histosAntiOmega) { + histos.add("AntiOmega/hInnerArrivalTimeDeltaNeg", "hInnerArrivalTimeDeltaNeg", kTH1D, {{axes.axisTimeDelta}}); + histos.add("AntiOmega/hInnerArrivalTimeDeltaPos", "hInnerArrivalTimeDeltaPos", kTH1D, {{axes.axisTimeDelta}}); + histos.add("AntiOmega/hInnerArrivalTimeDeltaBach", "hInnerArrivalTimeDeltaBach", kTH1D, {{axes.axisTimeDelta}}); + histos.add("AntiOmega/hOuterArrivalTimeDeltaNeg", "hOuterArrivalTimeDeltaNeg", kTH1D, {{axes.axisTimeDelta}}); + histos.add("AntiOmega/hOuterArrivalTimeDeltaPos", "hOuterArrivalTimeDeltaPos", kTH1D, {{axes.axisTimeDelta}}); + histos.add("AntiOmega/hOuterArrivalTimeDeltaBach", "hOuterArrivalTimeDeltaBach", kTH1D, {{axes.axisTimeDelta}}); + + histos.add("AntiOmega/hInnerNSigmaNeg", "hInnerNSigmaNeg", kTH1D, {{axes.axisNSigma}}); + histos.add("AntiOmega/hInnerNSigmaPos", "hInnerNSigmaPos", kTH1D, {{axes.axisNSigma}}); + histos.add("AntiOmega/hInnerNSigmaBach", "hInnerNSigmaBach", kTH1D, {{axes.axisNSigma}}); + histos.add("AntiOmega/hOuterNSigmaNeg", "hOuterNSigmaNeg", kTH1D, {{axes.axisNSigma}}); + histos.add("AntiOmega/hOuterNSigmaPos", "hOuterNSigmaPos", kTH1D, {{axes.axisNSigma}}); + histos.add("AntiOmega/hOuterNSigmaBach", "hOuterNSigmaBach", kTH1D, {{axes.axisNSigma}}); + + histos.add("AntiOmega/hInnerExpectedArrivalTimeNeg", "hInnerExpectedArrivalTimeNeg", kTH1D, {{axes.axisTime}}); + histos.add("AntiOmega/hInnerExpectedArrivalTimePos", "hInnerExpectedArrivalTimePos", kTH1D, {{axes.axisTime}}); + histos.add("AntiOmega/hInnerExpectedArrivalTimeBach", "hInnerExpectedArrivalTimeBach", kTH1D, {{axes.axisTime}}); + histos.add("AntiOmega/hOuterExpectedArrivalTimeNeg", "hOuterExpectedArrivalTimeNeg", kTH1D, {{axes.axisTime}}); + histos.add("AntiOmega/hOuterExpectedArrivalTimePos", "hOuterExpectedArrivalTimePos", kTH1D, {{axes.axisTime}}); + histos.add("AntiOmega/hOuterExpectedArrivalTimeBach", "hOuterExpectedArrivalTimeBach", kTH1D, {{axes.axisTime}}); + + histos.add("AntiOmega/hInnerMeasuredArrivalTimeNeg", "hInnerMeasuredArrivalTimeNeg", kTH1D, {{axes.axisTime}}); + histos.add("AntiOmega/hInnerMeasuredArrivalTimePos", "hInnerMeasuredArrivalTimePos", kTH1D, {{axes.axisTime}}); + histos.add("AntiOmega/hInnerMeasuredArrivalTimeBach", "hInnerMeasuredArrivalTimeBach", kTH1D, {{axes.axisTime}}); + histos.add("AntiOmega/hOuterMeasuredArrivalTimeNeg", "hOuterMeasuredArrivalTimeNeg", kTH1D, {{axes.axisTime}}); + histos.add("AntiOmega/hOuterMeasuredArrivalTimePos", "hOuterMeasuredArrivalTimePos", kTH1D, {{axes.axisTime}}); + histos.add("AntiOmega/hOuterMeasuredArrivalTimeBach", "hOuterMeasuredArrivalTimeBach", kTH1D, {{axes.axisTime}}); + + histos.add("AntiOmega/hInnerMeasuredVsExpectedArrivalTimeNeg", "hInnerMeasuredVsExpectedArrivalTimeNeg;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + histos.add("AntiOmega/hInnerMeasuredVsExpectedArrivalTimePos", "hInnerMeasuredVsExpectedArrivalTimePos;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + histos.add("AntiOmega/hInnerMeasuredVsExpectedArrivalTimeBach", "hInnerMeasuredVsExpectedArrivalTimeBach;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + histos.add("AntiOmega/hOuterMeasuredVsExpectedArrivalTimeNeg", "hOuterMeasuredVsExpectedArrivalTimeNeg;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + histos.add("AntiOmega/hOuterMeasuredVsExpectedArrivalTimePos", "hOuterMeasuredVsExpectedArrivalTimePos;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + histos.add("AntiOmega/hOuterMeasuredVsExpectedArrivalTimeBach", "hOuterMeasuredVsExpectedArrivalTimeBach;Measured time (ps);Expected time (ps)", kTH2D, {{axes.axisTime}, {axes.axisTime}}); + } + } + histos.print(); + } + + void processCascades(Alice3Collision const& collision, FullCascadeCandidates const& cascadeCandidates, Alice3Tracks const&, aod::McParticles const&, aod::McCollisions const&) + { + const std::array vtx = {collision.posX(), collision.posY(), collision.posZ()}; + const auto mcCollision = collision.template mcCollision_as(); + for (const auto& casc : cascadeCandidates) { + const std::array cascSV = {casc.x(), casc.y(), casc.z()}; + const std::array cascP = {casc.px(), casc.py(), casc.pz()}; + const int chargeCascade = (casc.sign() > 0) ? 1 : -1; + o2::track::TrackParCov cascade(cascSV, cascP, ParentTrackCovMatrix, chargeCascade); + + const std::array v0SV = {casc.xlambda(), casc.ylambda(), casc.zlambda()}; + const std::array v0P = {casc.pxpos() + casc.pxneg(), casc.pypos() + casc.pyneg(), casc.pzpos() + casc.pzneg()}; + static constexpr int ChargeV0 = 0; + o2::track::TrackParCov v0(v0SV, v0P, ParentTrackCovMatrix, ChargeV0); + + const auto bachTrack = casc.template bachelor_as(); + const auto bachParticle = bachTrack.template mcParticle_as(); + o2::track::TrackParCov bachelor = getTrackParCov(bachTrack); + + const auto posTrack = casc.template posTrack_as(); + const auto posParticle = posTrack.template mcParticle_as(); + o2::track::TrackParCov positive = getTrackParCov(posTrack); + + const auto negTrack = casc.template negTrack_as(); + const auto negParticle = negTrack.template mcParticle_as(); + o2::track::TrackParCov negative = getTrackParCov(negTrack); + + tofPidCasc.reset(); + tofPidCasc.setTrack(TrackType::Positive, positive, mcCollision.t() + posParticle.vt(), pdgDB->Mass(posParticle.pdgCode())); + tofPidCasc.setTrack(TrackType::Negative, negative, mcCollision.t() + negParticle.vt(), pdgDB->Mass(negParticle.pdgCode())); + tofPidCasc.setTrack(TrackType::Bachelor, bachelor, mcCollision.t() + bachParticle.vt(), pdgDB->Mass(bachParticle.pdgCode())); + tofPidCasc.setTrack(TrackType::V0, v0); // no track time + tofPidCasc.setTrack(TrackType::Cascade, cascade); // no track time + + CascTofResults straTofResultsXi{}, straTofResultsAntiXi{}, straTofResultsOmega{}, straTofResultsAntiOmega{}; + straTofResultsXi = tofPidCasc.findNSigmas(vtx, cascSV, v0SV); + straTofResultsAntiXi = tofPidCasc.findNSigmas(vtx, cascSV, v0SV); + straTofResultsOmega = tofPidCasc.findNSigmas(vtx, cascSV, v0SV); + straTofResultsAntiOmega = tofPidCasc.findNSigmas(vtx, cascSV, v0SV); + + if (produce.histosXi) { + if (straTofResultsXi.pos.hasInnerTof) { + histos.fill(HIST("Xi/hInnerArrivalTimeDeltaPos"), (straTofResultsXi.pos.measuredTimeInner - straTofResultsXi.pos.expectedTimeInner) * NanoToPico); + histos.fill(HIST("Xi/hInnerNSigmaPos"), straTofResultsXi.pos.nSigmaInner); + histos.fill(HIST("Xi/hInnerExpectedArrivalTimePos"), straTofResultsXi.pos.expectedTimeInner * NanoToPico); + histos.fill(HIST("Xi/hInnerMeasuredArrivalTimePos"), straTofResultsXi.pos.measuredTimeInner * NanoToPico); + histos.fill(HIST("Xi/hInnerMeasuredVsExpectedArrivalTimePos"), straTofResultsXi.pos.measuredTimeInner * NanoToPico, straTofResultsXi.pos.expectedTimeInner * NanoToPico); + } + if (straTofResultsXi.neg.hasInnerTof) { + histos.fill(HIST("Xi/hInnerArrivalTimeDeltaNeg"), (straTofResultsXi.neg.measuredTimeInner - straTofResultsXi.neg.expectedTimeInner) * NanoToPico); + histos.fill(HIST("Xi/hInnerNSigmaNeg"), straTofResultsXi.neg.nSigmaInner); + histos.fill(HIST("Xi/hInnerExpectedArrivalTimeNeg"), straTofResultsXi.neg.expectedTimeInner * NanoToPico); + histos.fill(HIST("Xi/hInnerMeasuredArrivalTimeNeg"), straTofResultsXi.neg.measuredTimeInner * NanoToPico); + histos.fill(HIST("Xi/hInnerMeasuredVsExpectedArrivalTimeNeg"), straTofResultsXi.neg.measuredTimeInner * NanoToPico, straTofResultsXi.neg.expectedTimeInner * NanoToPico); + } + if (straTofResultsXi.bach.hasInnerTof) { + histos.fill(HIST("Xi/hInnerArrivalTimeDeltaBach"), (straTofResultsXi.bach.measuredTimeInner - straTofResultsXi.bach.expectedTimeInner) * NanoToPico); + histos.fill(HIST("Xi/hInnerNSigmaBach"), straTofResultsXi.bach.nSigmaInner); + histos.fill(HIST("Xi/hInnerExpectedArrivalTimeBach"), straTofResultsXi.bach.expectedTimeInner * NanoToPico); + histos.fill(HIST("Xi/hInnerMeasuredArrivalTimeBach"), straTofResultsXi.bach.measuredTimeInner * NanoToPico); + histos.fill(HIST("Xi/hInnerMeasuredVsExpectedArrivalTimeBach"), straTofResultsXi.bach.measuredTimeInner * NanoToPico, straTofResultsXi.bach.expectedTimeInner * NanoToPico); + } + if (straTofResultsXi.pos.hasOuterTof) { + histos.fill(HIST("Xi/hOuterArrivalTimeDeltaPos"), (straTofResultsXi.pos.measuredTimeOuter - straTofResultsXi.pos.expectedTimeOuter) * NanoToPico); + histos.fill(HIST("Xi/hOuterNSigmaPos"), straTofResultsXi.pos.nSigmaOuter); + histos.fill(HIST("Xi/hOuterExpectedArrivalTimePos"), straTofResultsXi.pos.expectedTimeOuter * NanoToPico); + histos.fill(HIST("Xi/hOuterMeasuredArrivalTimePos"), straTofResultsXi.pos.measuredTimeOuter * NanoToPico); + histos.fill(HIST("Xi/hOuterMeasuredVsExpectedArrivalTimePos"), straTofResultsXi.pos.measuredTimeOuter * NanoToPico, straTofResultsXi.pos.expectedTimeOuter * NanoToPico); + } + if (straTofResultsXi.neg.hasOuterTof) { + histos.fill(HIST("Xi/hOuterArrivalTimeDeltaNeg"), (straTofResultsXi.neg.measuredTimeOuter - straTofResultsXi.neg.expectedTimeOuter) * NanoToPico); + histos.fill(HIST("Xi/hOuterNSigmaNeg"), straTofResultsXi.neg.nSigmaOuter); + histos.fill(HIST("Xi/hOuterExpectedArrivalTimeNeg"), straTofResultsXi.neg.expectedTimeOuter * NanoToPico); + histos.fill(HIST("Xi/hOuterMeasuredArrivalTimeNeg"), straTofResultsXi.neg.measuredTimeOuter * NanoToPico); + histos.fill(HIST("Xi/hOuterMeasuredVsExpectedArrivalTimeNeg"), straTofResultsXi.neg.measuredTimeOuter * NanoToPico, straTofResultsXi.neg.expectedTimeOuter * NanoToPico); + } + if (straTofResultsXi.bach.hasOuterTof) { + histos.fill(HIST("Xi/hOuterArrivalTimeDeltaBach"), (straTofResultsXi.bach.measuredTimeOuter - straTofResultsXi.bach.expectedTimeOuter) * NanoToPico); + histos.fill(HIST("Xi/hOuterNSigmaBach"), straTofResultsXi.bach.nSigmaOuter); + histos.fill(HIST("Xi/hOuterExpectedArrivalTimeBach"), straTofResultsXi.bach.expectedTimeOuter * NanoToPico); + histos.fill(HIST("Xi/hOuterMeasuredArrivalTimeBach"), straTofResultsXi.bach.measuredTimeOuter * NanoToPico); + histos.fill(HIST("Xi/hOuterMeasuredVsExpectedArrivalTimeBach"), straTofResultsXi.bach.measuredTimeOuter * NanoToPico, straTofResultsXi.bach.expectedTimeOuter * NanoToPico); + } + } + if (produce.histosAntiXi) { + if (straTofResultsAntiXi.pos.hasInnerTof) { + histos.fill(HIST("AntiXi/hInnerArrivalTimeDeltaPos"), (straTofResultsAntiXi.pos.measuredTimeInner - straTofResultsAntiXi.pos.expectedTimeInner) * NanoToPico); + histos.fill(HIST("AntiXi/hInnerNSigmaPos"), straTofResultsAntiXi.pos.nSigmaInner); + histos.fill(HIST("AntiXi/hInnerExpectedArrivalTimePos"), straTofResultsAntiXi.pos.expectedTimeInner * NanoToPico); + histos.fill(HIST("AntiXi/hInnerMeasuredArrivalTimePos"), straTofResultsAntiXi.pos.measuredTimeInner * NanoToPico); + histos.fill(HIST("AntiXi/hInnerMeasuredVsExpectedArrivalTimePos"), straTofResultsAntiXi.pos.measuredTimeInner * NanoToPico, straTofResultsAntiXi.pos.expectedTimeInner * NanoToPico); + } + if (straTofResultsAntiXi.neg.hasInnerTof) { + histos.fill(HIST("AntiXi/hInnerArrivalTimeDeltaNeg"), (straTofResultsAntiXi.neg.measuredTimeInner - straTofResultsAntiXi.neg.expectedTimeInner) * NanoToPico); + histos.fill(HIST("AntiXi/hInnerNSigmaNeg"), straTofResultsAntiXi.neg.nSigmaInner); + histos.fill(HIST("AntiXi/hInnerExpectedArrivalTimeNeg"), straTofResultsAntiXi.neg.expectedTimeInner * NanoToPico); + histos.fill(HIST("AntiXi/hInnerMeasuredArrivalTimeNeg"), straTofResultsAntiXi.neg.measuredTimeInner * NanoToPico); + histos.fill(HIST("AntiXi/hInnerMeasuredVsExpectedArrivalTimeNeg"), straTofResultsAntiXi.neg.measuredTimeInner * NanoToPico, straTofResultsAntiXi.neg.expectedTimeInner * NanoToPico); + } + if (straTofResultsAntiXi.bach.hasInnerTof) { + histos.fill(HIST("AntiXi/hInnerArrivalTimeDeltaBach"), (straTofResultsAntiXi.bach.measuredTimeInner - straTofResultsAntiXi.bach.expectedTimeInner) * NanoToPico); + histos.fill(HIST("AntiXi/hInnerNSigmaBach"), straTofResultsAntiXi.bach.nSigmaInner); + histos.fill(HIST("AntiXi/hInnerExpectedArrivalTimeBach"), straTofResultsAntiXi.bach.expectedTimeInner * NanoToPico); + histos.fill(HIST("AntiXi/hInnerMeasuredArrivalTimeBach"), straTofResultsAntiXi.bach.measuredTimeInner * NanoToPico); + histos.fill(HIST("AntiXi/hInnerMeasuredVsExpectedArrivalTimeBach"), straTofResultsAntiXi.bach.measuredTimeInner * NanoToPico, straTofResultsAntiXi.bach.expectedTimeInner * NanoToPico); + } + if (straTofResultsAntiXi.pos.hasOuterTof) { + histos.fill(HIST("AntiXi/hOuterArrivalTimeDeltaPos"), (straTofResultsAntiXi.pos.measuredTimeOuter - straTofResultsAntiXi.pos.expectedTimeOuter) * NanoToPico); + histos.fill(HIST("AntiXi/hOuterNSigmaPos"), straTofResultsAntiXi.pos.nSigmaOuter); + histos.fill(HIST("AntiXi/hOuterExpectedArrivalTimePos"), straTofResultsAntiXi.pos.expectedTimeOuter * NanoToPico); + histos.fill(HIST("AntiXi/hOuterMeasuredArrivalTimePos"), straTofResultsAntiXi.pos.measuredTimeOuter * NanoToPico); + histos.fill(HIST("AntiXi/hOuterMeasuredVsExpectedArrivalTimePos"), straTofResultsAntiXi.pos.measuredTimeOuter * NanoToPico, straTofResultsAntiXi.pos.expectedTimeOuter * NanoToPico); + } + if (straTofResultsAntiXi.neg.hasOuterTof) { + histos.fill(HIST("AntiXi/hOuterArrivalTimeDeltaNeg"), (straTofResultsAntiXi.neg.measuredTimeOuter - straTofResultsAntiXi.neg.expectedTimeOuter) * NanoToPico); + histos.fill(HIST("AntiXi/hOuterNSigmaNeg"), straTofResultsAntiXi.neg.nSigmaOuter); + histos.fill(HIST("AntiXi/hOuterExpectedArrivalTimeNeg"), straTofResultsAntiXi.neg.expectedTimeOuter * NanoToPico); + histos.fill(HIST("AntiXi/hOuterMeasuredArrivalTimeNeg"), straTofResultsAntiXi.neg.measuredTimeOuter * NanoToPico); + histos.fill(HIST("AntiXi/hOuterMeasuredVsExpectedArrivalTimeNeg"), straTofResultsAntiXi.neg.measuredTimeOuter * NanoToPico, straTofResultsAntiXi.neg.expectedTimeOuter * NanoToPico); + } + if (straTofResultsAntiXi.bach.hasOuterTof) { + histos.fill(HIST("AntiXi/hOuterArrivalTimeDeltaBach"), (straTofResultsAntiXi.bach.measuredTimeOuter - straTofResultsAntiXi.bach.expectedTimeOuter) * NanoToPico); + histos.fill(HIST("AntiXi/hOuterNSigmaBach"), straTofResultsAntiXi.bach.nSigmaOuter); + histos.fill(HIST("AntiXi/hOuterExpectedArrivalTimeBach"), straTofResultsAntiXi.bach.expectedTimeOuter * NanoToPico); + histos.fill(HIST("AntiXi/hOuterMeasuredArrivalTimeBach"), straTofResultsAntiXi.bach.measuredTimeOuter * NanoToPico); + histos.fill(HIST("AntiXi/hOuterMeasuredVsExpectedArrivalTimeBach"), straTofResultsAntiXi.bach.measuredTimeOuter * NanoToPico, straTofResultsAntiXi.bach.expectedTimeOuter * NanoToPico); + } + } + if (produce.histosOmega) { + if (straTofResultsOmega.pos.hasInnerTof) { + histos.fill(HIST("Omega/hInnerArrivalTimeDeltaPos"), (straTofResultsOmega.pos.measuredTimeInner - straTofResultsOmega.pos.expectedTimeInner) * NanoToPico); + histos.fill(HIST("Omega/hInnerNSigmaPos"), straTofResultsOmega.pos.nSigmaInner); + histos.fill(HIST("Omega/hInnerExpectedArrivalTimePos"), straTofResultsOmega.pos.expectedTimeInner * NanoToPico); + histos.fill(HIST("Omega/hInnerMeasuredArrivalTimePos"), straTofResultsOmega.pos.measuredTimeInner * NanoToPico); + histos.fill(HIST("Omega/hInnerMeasuredVsExpectedArrivalTimePos"), straTofResultsOmega.pos.measuredTimeInner * NanoToPico, straTofResultsOmega.pos.expectedTimeInner * NanoToPico); + } + if (straTofResultsOmega.neg.hasInnerTof) { + histos.fill(HIST("Omega/hInnerArrivalTimeDeltaNeg"), (straTofResultsOmega.neg.measuredTimeInner - straTofResultsOmega.neg.expectedTimeInner) * NanoToPico); + histos.fill(HIST("Omega/hInnerNSigmaNeg"), straTofResultsOmega.neg.nSigmaInner); + histos.fill(HIST("Omega/hInnerExpectedArrivalTimeNeg"), straTofResultsOmega.neg.expectedTimeInner * NanoToPico); + histos.fill(HIST("Omega/hInnerMeasuredArrivalTimeNeg"), straTofResultsOmega.neg.measuredTimeInner * NanoToPico); + histos.fill(HIST("Omega/hInnerMeasuredVsExpectedArrivalTimeNeg"), straTofResultsOmega.neg.measuredTimeInner * NanoToPico, straTofResultsOmega.neg.expectedTimeInner * NanoToPico); + } + if (straTofResultsOmega.bach.hasInnerTof) { + histos.fill(HIST("Omega/hInnerArrivalTimeDeltaBach"), (straTofResultsOmega.bach.measuredTimeInner - straTofResultsOmega.bach.expectedTimeInner) * NanoToPico); + histos.fill(HIST("Omega/hInnerNSigmaBach"), straTofResultsOmega.bach.nSigmaInner); + histos.fill(HIST("Omega/hInnerExpectedArrivalTimeBach"), straTofResultsOmega.bach.expectedTimeInner * NanoToPico); + histos.fill(HIST("Omega/hInnerMeasuredArrivalTimeBach"), straTofResultsOmega.bach.measuredTimeInner * NanoToPico); + histos.fill(HIST("Omega/hInnerMeasuredVsExpectedArrivalTimeBach"), straTofResultsOmega.bach.measuredTimeInner * NanoToPico, straTofResultsOmega.bach.expectedTimeInner * NanoToPico); + } + if (straTofResultsOmega.pos.hasOuterTof) { + histos.fill(HIST("Omega/hOuterArrivalTimeDeltaPos"), (straTofResultsOmega.pos.measuredTimeOuter - straTofResultsOmega.pos.expectedTimeOuter) * NanoToPico); + histos.fill(HIST("Omega/hOuterNSigmaPos"), straTofResultsOmega.pos.nSigmaOuter); + histos.fill(HIST("Omega/hOuterExpectedArrivalTimePos"), straTofResultsOmega.pos.expectedTimeOuter * NanoToPico); + histos.fill(HIST("Omega/hOuterMeasuredArrivalTimePos"), straTofResultsOmega.pos.measuredTimeOuter * NanoToPico); + histos.fill(HIST("Omega/hOuterMeasuredVsExpectedArrivalTimePos"), straTofResultsOmega.pos.measuredTimeOuter * NanoToPico, straTofResultsOmega.pos.expectedTimeOuter * NanoToPico); + } + if (straTofResultsOmega.neg.hasOuterTof) { + histos.fill(HIST("Omega/hOuterArrivalTimeDeltaNeg"), (straTofResultsOmega.neg.measuredTimeOuter - straTofResultsOmega.neg.expectedTimeOuter) * NanoToPico); + histos.fill(HIST("Omega/hOuterNSigmaNeg"), straTofResultsOmega.neg.nSigmaOuter); + histos.fill(HIST("Omega/hOuterExpectedArrivalTimeNeg"), straTofResultsOmega.neg.expectedTimeOuter * NanoToPico); + histos.fill(HIST("Omega/hOuterMeasuredArrivalTimeNeg"), straTofResultsOmega.neg.measuredTimeOuter * NanoToPico); + histos.fill(HIST("Omega/hOuterMeasuredVsExpectedArrivalTimeNeg"), straTofResultsOmega.neg.measuredTimeOuter * NanoToPico, straTofResultsOmega.neg.expectedTimeOuter * NanoToPico); + } + if (straTofResultsOmega.bach.hasOuterTof) { + histos.fill(HIST("Omega/hOuterArrivalTimeDeltaBach"), (straTofResultsOmega.bach.measuredTimeOuter - straTofResultsOmega.bach.expectedTimeOuter) * NanoToPico); + histos.fill(HIST("Omega/hOuterNSigmaBach"), straTofResultsOmega.bach.nSigmaOuter); + histos.fill(HIST("Omega/hOuterExpectedArrivalTimeBach"), straTofResultsOmega.bach.expectedTimeOuter * NanoToPico); + histos.fill(HIST("Omega/hOuterMeasuredArrivalTimeBach"), straTofResultsOmega.bach.measuredTimeOuter * NanoToPico); + histos.fill(HIST("Omega/hOuterMeasuredVsExpectedArrivalTimeBach"), straTofResultsOmega.bach.measuredTimeOuter * NanoToPico, straTofResultsOmega.bach.expectedTimeOuter * NanoToPico); + } + } + + if (produce.histosAntiOmega) { + if (straTofResultsAntiOmega.pos.hasInnerTof) { + histos.fill(HIST("AntiOmega/hInnerArrivalTimeDeltaPos"), (straTofResultsAntiOmega.pos.measuredTimeInner - straTofResultsAntiOmega.pos.expectedTimeInner) * NanoToPico); + histos.fill(HIST("AntiOmega/hInnerNSigmaPos"), straTofResultsAntiOmega.pos.nSigmaInner); + histos.fill(HIST("AntiOmega/hInnerExpectedArrivalTimePos"), straTofResultsAntiOmega.pos.expectedTimeInner * NanoToPico); + histos.fill(HIST("AntiOmega/hInnerMeasuredArrivalTimePos"), straTofResultsAntiOmega.pos.measuredTimeInner * NanoToPico); + histos.fill(HIST("AntiOmega/hInnerMeasuredVsExpectedArrivalTimePos"), straTofResultsAntiOmega.pos.measuredTimeInner * NanoToPico, straTofResultsAntiOmega.pos.expectedTimeInner * NanoToPico); + } + if (straTofResultsAntiOmega.neg.hasInnerTof) { + histos.fill(HIST("AntiOmega/hInnerArrivalTimeDeltaNeg"), (straTofResultsAntiOmega.neg.measuredTimeInner - straTofResultsAntiOmega.neg.expectedTimeInner) * NanoToPico); + histos.fill(HIST("AntiOmega/hInnerNSigmaNeg"), straTofResultsAntiOmega.neg.nSigmaInner); + histos.fill(HIST("AntiOmega/hInnerExpectedArrivalTimeNeg"), straTofResultsAntiOmega.neg.expectedTimeInner * NanoToPico); + histos.fill(HIST("AntiOmega/hInnerMeasuredArrivalTimeNeg"), straTofResultsAntiOmega.neg.measuredTimeInner * NanoToPico); + histos.fill(HIST("AntiOmega/hInnerMeasuredVsExpectedArrivalTimeNeg"), straTofResultsAntiOmega.neg.measuredTimeInner * NanoToPico, straTofResultsAntiOmega.neg.expectedTimeInner * NanoToPico); + } + if (straTofResultsAntiOmega.bach.hasInnerTof) { + histos.fill(HIST("AntiOmega/hInnerArrivalTimeDeltaBach"), (straTofResultsAntiOmega.bach.measuredTimeInner - straTofResultsAntiOmega.bach.expectedTimeInner) * NanoToPico); + histos.fill(HIST("AntiOmega/hInnerNSigmaBach"), straTofResultsAntiOmega.bach.nSigmaInner); + histos.fill(HIST("AntiOmega/hInnerExpectedArrivalTimeBach"), straTofResultsAntiOmega.bach.expectedTimeInner * NanoToPico); + histos.fill(HIST("AntiOmega/hInnerMeasuredArrivalTimeBach"), straTofResultsAntiOmega.bach.measuredTimeInner * NanoToPico); + histos.fill(HIST("AntiOmega/hInnerMeasuredVsExpectedArrivalTimeBach"), straTofResultsAntiOmega.bach.measuredTimeInner * NanoToPico, straTofResultsAntiOmega.bach.expectedTimeInner * NanoToPico); + } + if (straTofResultsAntiOmega.pos.hasOuterTof) { + histos.fill(HIST("AntiOmega/hOuterArrivalTimeDeltaPos"), (straTofResultsAntiOmega.pos.measuredTimeOuter - straTofResultsAntiOmega.pos.expectedTimeOuter) * NanoToPico); + histos.fill(HIST("AntiOmega/hOuterNSigmaPos"), straTofResultsAntiOmega.pos.nSigmaOuter); + histos.fill(HIST("AntiOmega/hOuterExpectedArrivalTimePos"), straTofResultsAntiOmega.pos.expectedTimeOuter * NanoToPico); + histos.fill(HIST("AntiOmega/hOuterMeasuredArrivalTimePos"), straTofResultsAntiOmega.pos.measuredTimeOuter * NanoToPico); + histos.fill(HIST("AntiOmega/hOuterMeasuredVsExpectedArrivalTimePos"), straTofResultsAntiOmega.pos.measuredTimeOuter * NanoToPico, straTofResultsAntiOmega.pos.expectedTimeOuter * NanoToPico); + } + if (straTofResultsAntiOmega.neg.hasOuterTof) { + histos.fill(HIST("AntiOmega/hOuterArrivalTimeDeltaNeg"), (straTofResultsAntiOmega.neg.measuredTimeOuter - straTofResultsAntiOmega.neg.expectedTimeOuter) * NanoToPico); + histos.fill(HIST("AntiOmega/hOuterNSigmaNeg"), straTofResultsAntiOmega.neg.nSigmaOuter); + histos.fill(HIST("AntiOmega/hOuterExpectedArrivalTimeNeg"), straTofResultsAntiOmega.neg.expectedTimeOuter * NanoToPico); + histos.fill(HIST("AntiOmega/hOuterMeasuredArrivalTimeNeg"), straTofResultsAntiOmega.neg.measuredTimeOuter * NanoToPico); + histos.fill(HIST("AntiOmega/hOuterMeasuredVsExpectedArrivalTimeNeg"), straTofResultsAntiOmega.neg.measuredTimeOuter * NanoToPico, straTofResultsAntiOmega.neg.expectedTimeOuter * NanoToPico); + } + if (straTofResultsAntiOmega.bach.hasOuterTof) { + histos.fill(HIST("AntiOmega/hOuterArrivalTimeDeltaBach"), (straTofResultsAntiOmega.bach.measuredTimeOuter - straTofResultsAntiOmega.bach.expectedTimeOuter) * NanoToPico); + histos.fill(HIST("AntiOmega/hOuterNSigmaBach"), straTofResultsAntiOmega.bach.nSigmaOuter); + histos.fill(HIST("AntiOmega/hOuterExpectedArrivalTimeBach"), straTofResultsAntiOmega.bach.expectedTimeOuter * NanoToPico); + histos.fill(HIST("AntiOmega/hOuterMeasuredArrivalTimeBach"), straTofResultsAntiOmega.bach.measuredTimeOuter * NanoToPico); + histos.fill(HIST("AntiOmega/hOuterMeasuredVsExpectedArrivalTimeBach"), straTofResultsAntiOmega.bach.measuredTimeOuter * NanoToPico, straTofResultsAntiOmega.bach.expectedTimeOuter * NanoToPico); + } + } + + if (produce.tableInnerNSigmaXi) { + tableA3XiInnerTofPid( + (straTofResultsXi.bach.hasInnerTof) ? straTofResultsXi.bach.nSigmaInner : o2::upgrade::pid::NoPidSignal, + (straTofResultsXi.pos.hasInnerTof) ? straTofResultsXi.bach.nSigmaInner : o2::upgrade::pid::NoPidSignal, + (straTofResultsAntiXi.pos.hasInnerTof) ? straTofResultsAntiXi.bach.nSigmaInner : o2::upgrade::pid::NoPidSignal, + (straTofResultsAntiXi.neg.hasInnerTof) ? straTofResultsAntiXi.bach.nSigmaInner : o2::upgrade::pid::NoPidSignal, + (straTofResultsXi.neg.hasInnerTof) ? straTofResultsXi.bach.nSigmaInner : o2::upgrade::pid::NoPidSignal); + } + if (produce.tableOuterNSigmaXi) { + tableA3XiOuterTofPid( + (straTofResultsXi.bach.hasOuterTof) ? straTofResultsXi.bach.nSigmaOuter : o2::upgrade::pid::NoPidSignal, + (straTofResultsXi.pos.hasOuterTof) ? straTofResultsXi.bach.nSigmaOuter : o2::upgrade::pid::NoPidSignal, + (straTofResultsAntiXi.pos.hasOuterTof) ? straTofResultsAntiXi.bach.nSigmaOuter : o2::upgrade::pid::NoPidSignal, + (straTofResultsAntiXi.neg.hasOuterTof) ? straTofResultsAntiXi.bach.nSigmaOuter : o2::upgrade::pid::NoPidSignal, + (straTofResultsXi.neg.hasOuterTof) ? straTofResultsXi.bach.nSigmaOuter : o2::upgrade::pid::NoPidSignal); + } + if (produce.tableInnerNSigmaOmega) { + tableA3OmegaInnerTofPid( + (straTofResultsOmega.bach.hasInnerTof) ? straTofResultsOmega.bach.nSigmaInner : o2::upgrade::pid::NoPidSignal, + (straTofResultsOmega.pos.hasInnerTof) ? straTofResultsOmega.bach.nSigmaInner : o2::upgrade::pid::NoPidSignal, + (straTofResultsAntiOmega.pos.hasInnerTof) ? straTofResultsAntiOmega.bach.nSigmaInner : o2::upgrade::pid::NoPidSignal, + (straTofResultsAntiOmega.neg.hasInnerTof) ? straTofResultsAntiOmega.bach.nSigmaInner : o2::upgrade::pid::NoPidSignal, + (straTofResultsOmega.neg.hasInnerTof) ? straTofResultsOmega.bach.nSigmaInner : o2::upgrade::pid::NoPidSignal); + } + if (produce.tableOuterNSigmaOmega) { + tableA3OmegaOuterTofPid( + (straTofResultsOmega.bach.hasOuterTof) ? straTofResultsOmega.bach.nSigmaOuter : o2::upgrade::pid::NoPidSignal, + (straTofResultsOmega.pos.hasOuterTof) ? straTofResultsOmega.bach.nSigmaOuter : o2::upgrade::pid::NoPidSignal, + (straTofResultsAntiOmega.pos.hasOuterTof) ? straTofResultsAntiOmega.bach.nSigmaOuter : o2::upgrade::pid::NoPidSignal, + (straTofResultsAntiOmega.neg.hasOuterTof) ? straTofResultsAntiOmega.bach.nSigmaOuter : o2::upgrade::pid::NoPidSignal, + (straTofResultsOmega.neg.hasOuterTof) ? straTofResultsOmega.bach.nSigmaOuter : o2::upgrade::pid::NoPidSignal); + } + + if (produce.tableInnerExpectedTimesXi) { + tableA3XiExpectedInnerTimes( + straTofResultsXi.bach.expectedTimeInner, + straTofResultsXi.pos.expectedTimeInner, + straTofResultsAntiXi.pos.expectedTimeInner, + straTofResultsAntiXi.neg.expectedTimeInner, + straTofResultsXi.neg.expectedTimeInner, + straTofResultsXi.bach.measuredTimeInner, + straTofResultsXi.pos.measuredTimeInner, + straTofResultsAntiXi.pos.measuredTimeInner, + straTofResultsAntiXi.neg.measuredTimeInner, + straTofResultsXi.neg.measuredTimeInner); + } + if (produce.tableOuterExpectedTimesXi) { + tableA3XiExpectedOuterTimes( + straTofResultsXi.bach.expectedTimeOuter, + straTofResultsXi.pos.expectedTimeOuter, + straTofResultsAntiXi.pos.expectedTimeOuter, + straTofResultsAntiXi.neg.expectedTimeOuter, + straTofResultsXi.neg.expectedTimeOuter, + straTofResultsXi.bach.measuredTimeOuter, + straTofResultsXi.pos.measuredTimeOuter, + straTofResultsAntiXi.pos.measuredTimeOuter, + straTofResultsAntiXi.neg.measuredTimeOuter, + straTofResultsXi.neg.measuredTimeOuter); + } + if (produce.tableInnerExpectedTimesOmega) { + tableA3OmegaExpectedInnerTimes( + straTofResultsOmega.bach.expectedTimeInner, + straTofResultsOmega.pos.expectedTimeInner, + straTofResultsAntiOmega.pos.expectedTimeInner, + straTofResultsAntiOmega.neg.expectedTimeInner, + straTofResultsOmega.neg.expectedTimeInner, + straTofResultsOmega.bach.measuredTimeInner, + straTofResultsOmega.pos.measuredTimeInner, + straTofResultsAntiOmega.pos.measuredTimeInner, + straTofResultsAntiOmega.neg.measuredTimeInner, + straTofResultsOmega.neg.measuredTimeInner); + } + if (produce.tableOuterExpectedTimesOmega) { + tableA3OmegaExpectedOuterTimes( + straTofResultsOmega.bach.expectedTimeOuter, + straTofResultsOmega.pos.expectedTimeOuter, + straTofResultsAntiOmega.pos.expectedTimeOuter, + straTofResultsAntiOmega.neg.expectedTimeOuter, + straTofResultsOmega.neg.expectedTimeOuter, + straTofResultsOmega.bach.measuredTimeOuter, + straTofResultsOmega.pos.measuredTimeOuter, + straTofResultsAntiOmega.pos.measuredTimeOuter, + straTofResultsAntiOmega.neg.measuredTimeOuter, + straTofResultsOmega.neg.measuredTimeOuter); + } + } + } + + PROCESS_SWITCH(Alice3StrangenessTofPid, processCascades, "", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/ALICE3/Tasks/alice3Strangeness.cxx b/ALICE3/Tasks/alice3Strangeness.cxx index 3b54dcb6945..0a70dd2c410 100644 --- a/ALICE3/Tasks/alice3Strangeness.cxx +++ b/ALICE3/Tasks/alice3Strangeness.cxx @@ -54,7 +54,7 @@ using namespace o2::constants::math; using Alice3Tracks = soa::Join; using FullV0Candidates = soa::Join; -using FullCascadeCandidates = soa::Join; +using FullCascadeCandidates = soa::Join; using FullCollisions = soa::Join; struct Alice3Strangeness { @@ -117,14 +117,17 @@ struct Alice3Strangeness { Configurable posMinPtDepDCAxy{"posMinPtDepDCAxy", 0.f, "[1] in |DCAxy| > [0]+[1]/pT"}; Configurable posMinConstDCAz{"posMinConstDCAz", -1.f, "[1] in |DCAz| > [0]+[1]/pT"}; Configurable posMinPtDepDCAz{"posMinPtDepDCAz", 0.f, "[0] in |DCAz| > [0]+[1]/pT"}; + Configurable posMaxNSigma{"posMaxNSigma", 5.f, "Max NSigma from strangeness tof pid"}; Configurable negMinConstDCAxy{"negMinConstDCAxy", 0.5f, "[0] in |DCAxy| > [0]+[1]/pT"}; Configurable negMinPtDepDCAxy{"negMinPtDepDCAxy", 0.f, "[1] in |DCAxy| > [0]+[1]/pT"}; Configurable negMinConstDCAz{"negMinConstDCAz", -1.f, "[1] in |DCAz| > [0]+[1]/pT"}; Configurable negMinPtDepDCAz{"negMinPtDepDCAz", 0.f, "[0] in |DCAz| > [0]+[1]/pT"}; + Configurable negMaxNSigma{"negMaxNSigma", 5.f, "Max NSigma from strangeness tof pid"}; Configurable bachMinConstDCAxy{"bachMinConstDCAxy", 0.5f, "[0] in |DCAxy| > [0]+[1]/pT"}; Configurable bachMinPtDepDCAxy{"bachMinPtDepDCAxy", 0.f, "[1] in |DCAxy| > [0]+[1]/pT"}; Configurable bachMinConstDCAz{"bachMinConstDCAz", -1.f, "[1] in |DCAz| > [0]+[1]/pT"}; Configurable bachMinPtDepDCAz{"bachMinPtDepDCAz", 0.f, "[0] in |DCAz| > [0]+[1]/pT"}; + Configurable bachMaxNSigma{"bachMaxNSigma", 5.f, "Max NSigma from strangeness tof pid"}; Configurable laMaxDauDCA{"laMaxDauDCA", 0.5f, "DCA (cm) between lambda daughters"}; Configurable laMinDecayRadius{"laMinDecayRadius", 0.5f, "Minimum lambda radius"}; Configurable laMassWindow{"laMassWindow", 0.5f, "accepted la mass window around PDG mass"}; @@ -156,6 +159,10 @@ struct Alice3Strangeness { Configurable cascMaxNormalizedDecayLength{"cascMaxNormalizedDecayLength", true, "enable cascMaxNormalizedDecayLength selection"}; Configurable cascMinCosPA{"cascMinCosPA", true, "enable cascMinCosPA selection"}; Configurable competingMassRejection{"competingMassRejection", false, "enable competingMassRejection selection"}; + Configurable rejectNoInnerTofSignal{"rejectNoInnerTofSignal", false, "reject candidate if track has no signal in tof"}; + Configurable rejectNoOuterTofSignal{"rejectNoOuterTofSignal", false, "reject candidate if track has no signal in tof"}; + Configurable tofInner{"tofInner", true, "enable particle identification selection"}; + Configurable tofOuter{"tofOuter", false, "enable particle identification selection"}; } cascadeFlags; uint16_t appliedSelectionCheckMask; @@ -167,6 +174,10 @@ struct Alice3Strangeness { static constexpr float ToMicrons = 1e+4f; static constexpr float CtauXi = 4.91f; static constexpr float CtauOmega = 2.461f; + float nSigmaBachInnerTof{}, nSigmaPosInnerTof{}, nSigmaNegInnerTof{}; + float nSigmaBachOuterTof{}, nSigmaPosOuterTof{}, nSigmaNegOuterTof{}; + bool hasBachInnerTof{}, hasPosInnerTof{}, hasNegInnerTof{}; + bool hasBachOuterTof{}, hasPosOuterTof{}, hasNegOuterTof{}; struct Cascade { enum Type { Xi = 0, @@ -199,6 +210,75 @@ struct Alice3Strangeness { } } analysedCascade; + template + void configureNSigmas(const TCascade& cascade) + { + const Cascade::Type analysedCascadeType = static_cast(cascadeFlags.analyseCascade.value); + switch (analysedCascadeType) { + case Cascade::Xi: + nSigmaBachInnerTof = cascade.nSigmaInnerTofXiBachPi(); + nSigmaBachOuterTof = cascade.nSigmaOuterTofXiBachPi(); + nSigmaPosInnerTof = cascade.nSigmaInnerTofXiPosPr(); + nSigmaPosOuterTof = cascade.nSigmaOuterTofXiPosPr(); + nSigmaNegInnerTof = cascade.nSigmaInnerTofXiNegPi(); + nSigmaNegOuterTof = cascade.nSigmaOuterTofXiNegPi(); + hasBachInnerTof = cascade.hasInnerTofXiBachPi(); + hasPosInnerTof = cascade.hasOuterTofXiBachPi(); + hasNegInnerTof = cascade.hasInnerTofXiPosPr(); + hasBachOuterTof = cascade.hasOuterTofXiPosPr(); + hasPosOuterTof = cascade.hasInnerTofXiNegPi(); + hasNegOuterTof = cascade.hasOuterTofXiNegPi(); + + break; + case Cascade::AntiXi: + nSigmaBachInnerTof = cascade.nSigmaInnerTofXiBachPi(); + nSigmaBachOuterTof = cascade.nSigmaOuterTofXiBachPi(); + nSigmaPosInnerTof = cascade.nSigmaInnerTofXiPosPi(); + nSigmaPosOuterTof = cascade.nSigmaOuterTofXiPosPi(); + nSigmaNegInnerTof = cascade.nSigmaInnerTofXiNegPr(); + nSigmaNegOuterTof = cascade.nSigmaOuterTofXiNegPr(); + hasBachInnerTof = cascade.hasInnerTofXiBachPi(); + hasPosInnerTof = cascade.hasOuterTofXiBachPi(); + hasNegInnerTof = cascade.hasInnerTofXiPosPi(); + hasBachOuterTof = cascade.hasOuterTofXiPosPi(); + hasPosOuterTof = cascade.hasInnerTofXiNegPr(); + hasNegOuterTof = cascade.hasOuterTofXiNegPr(); + + break; + case Cascade::Omega: + nSigmaBachInnerTof = cascade.nSigmaInnerTofOmegaBachKa(); + nSigmaBachOuterTof = cascade.nSigmaOuterTofOmegaBachKa(); + nSigmaPosInnerTof = cascade.nSigmaInnerTofOmegaPosPr(); + nSigmaPosOuterTof = cascade.nSigmaOuterTofOmegaPosPr(); + nSigmaNegInnerTof = cascade.nSigmaInnerTofOmegaNegPi(); + nSigmaNegOuterTof = cascade.nSigmaOuterTofOmegaNegPi(); + hasBachInnerTof = cascade.hasInnerTofOmegaBachKa(); + hasPosInnerTof = cascade.hasOuterTofOmegaBachKa(); + hasNegInnerTof = cascade.hasInnerTofOmegaPosPr(); + hasBachOuterTof = cascade.hasOuterTofOmegaPosPr(); + hasPosOuterTof = cascade.hasInnerTofOmegaNegPi(); + hasNegOuterTof = cascade.hasOuterTofOmegaNegPi(); + break; + case Cascade::AntiOmega: + nSigmaBachInnerTof = cascade.nSigmaInnerTofOmegaBachKa(); + nSigmaBachOuterTof = cascade.nSigmaOuterTofOmegaBachKa(); + nSigmaPosInnerTof = cascade.nSigmaInnerTofOmegaPosPi(); + nSigmaPosOuterTof = cascade.nSigmaOuterTofOmegaPosPi(); + nSigmaNegInnerTof = cascade.nSigmaInnerTofOmegaNegPr(); + nSigmaNegOuterTof = cascade.nSigmaOuterTofOmegaNegPr(); + hasBachInnerTof = cascade.hasInnerTofOmegaBachKa(); + hasPosInnerTof = cascade.hasOuterTofOmegaBachKa(); + hasNegInnerTof = cascade.hasInnerTofOmegaPosPi(); + hasBachOuterTof = cascade.hasOuterTofOmegaPosPi(); + hasPosOuterTof = cascade.hasInnerTofOmegaNegPr(); + hasNegOuterTof = cascade.hasOuterTofOmegaNegPr(); + break; + + default: + break; + } + } + void init(InitContext&) { histos.add("K0/hMassAllCandidates", "", kTH2D, {histAxes.axisK0Mass, histAxes.axisPt}); @@ -236,7 +316,7 @@ struct Alice3Strangeness { histos.add("reconstructedCandidates/Cascade/h3dOmegaCandidates", "h3dOmegaCandidates", kTH3D, {histAxes.axisPt, histAxes.axisEta, histAxes.axisOmegaMass}); histos.add("reconstructedCandidates/Cascade/h3dAntiOmegaCandidates", "h3dAntiOmegaCandidates", kTH3D, {histAxes.axisPt, histAxes.axisEta, histAxes.axisOmegaMass}); - histos.add("reconstructedCandidates/Cascade/hSelectionQa", "hSelectionQa", kTH1D, {{20, 0.5, 20.5}}); + histos.add("reconstructedCandidates/Cascade/hSelectionQa", "hSelectionQa", kTH1D, {{25, 0.5, 25.5}}); histos.get(HIST("reconstructedCandidates/Cascade/hSelectionQa"))->GetXaxis()->SetBinLabel(1, "all candidates"); histos.get(HIST("reconstructedCandidates/Cascade/hSelectionQa"))->GetXaxis()->SetBinLabel(2, "pos dcaXY"); histos.get(HIST("reconstructedCandidates/Cascade/hSelectionQa"))->GetXaxis()->SetBinLabel(3, "neg dcaXY"); @@ -253,6 +333,12 @@ struct Alice3Strangeness { histos.get(HIST("reconstructedCandidates/Cascade/hSelectionQa"))->GetXaxis()->SetBinLabel(14, "casc decay radius"); histos.get(HIST("reconstructedCandidates/Cascade/hSelectionQa"))->GetXaxis()->SetBinLabel(15, "casc cosPA"); histos.get(HIST("reconstructedCandidates/Cascade/hSelectionQa"))->GetXaxis()->SetBinLabel(16, "competing mass"); + histos.get(HIST("reconstructedCandidates/Cascade/hSelectionQa"))->GetXaxis()->SetBinLabel(17, "itof nsigma bach"); + histos.get(HIST("reconstructedCandidates/Cascade/hSelectionQa"))->GetXaxis()->SetBinLabel(18, "itof nsigma pos"); + histos.get(HIST("reconstructedCandidates/Cascade/hSelectionQa"))->GetXaxis()->SetBinLabel(19, "itof nsigma neg"); + histos.get(HIST("reconstructedCandidates/Cascade/hSelectionQa"))->GetXaxis()->SetBinLabel(20, "otof nsigma bach"); + histos.get(HIST("reconstructedCandidates/Cascade/hSelectionQa"))->GetXaxis()->SetBinLabel(21, "otof nsigma pos"); + histos.get(HIST("reconstructedCandidates/Cascade/hSelectionQa"))->GetXaxis()->SetBinLabel(22, "otof nsigma neg"); histos.add("reconstructedCandidates/Cascade/BeforeSelection/hPosDCAxy", "hPosDCAxy", kTH1D, {histAxes.axisDCA}); histos.add("reconstructedCandidates/Cascade/BeforeSelection/hNegDCAxy", "hNegDCAxy", kTH1D, {histAxes.axisDCA}); @@ -620,7 +706,58 @@ struct Alice3Strangeness { continue; } + if (cascadeFlags.tofInner || cascadeFlags.tofOuter) { + configureNSigmas(cascade); + } + histos.fill(HIST("reconstructedCandidates/Cascade/hSelectionQa"), 16 /* Pass casc competing mass rej*/); + if (cascadeFlags.tofInner) { + const bool applyNSigmaCut = cascadeFlags.rejectNoInnerTofSignal || hasBachInnerTof; + if (applyNSigmaCut && nSigmaBachInnerTof > cascadeSelectionValues.bachMaxNSigma) { + continue; // reject: nSigma cut applies (either TOF signal present, or no-signal tracks are required to pass it too) + } + } + histos.fill(HIST("reconstructedCandidates/Cascade/hSelectionQa"), 17 /* Pass bach itof nsigma*/); + + if (cascadeFlags.tofInner) { + const bool applyNSigmaCut = cascadeFlags.rejectNoInnerTofSignal || hasPosInnerTof; + if (applyNSigmaCut && nSigmaPosInnerTof > cascadeSelectionValues.posMaxNSigma) { + continue; + } + } + histos.fill(HIST("reconstructedCandidates/Cascade/hSelectionQa"), 18 /* Pass pos itof nsigma*/); + + if (cascadeFlags.tofInner) { + const bool applyNSigmaCut = cascadeFlags.rejectNoInnerTofSignal || hasNegInnerTof; + if (applyNSigmaCut && nSigmaNegInnerTof > cascadeSelectionValues.negMaxNSigma) { + continue; + } + } + histos.fill(HIST("reconstructedCandidates/Cascade/hSelectionQa"), 19 /* Pass neg itof nsigma*/); + + if (cascadeFlags.tofOuter) { + const bool applyNSigmaCut = cascadeFlags.rejectNoOuterTofSignal || hasBachOuterTof; + if (applyNSigmaCut && nSigmaBachOuterTof > cascadeSelectionValues.bachMaxNSigma) { + continue; + } + } + histos.fill(HIST("reconstructedCandidates/Cascade/hSelectionQa"), 20 /* Pass bach otof nsigma*/); + + if (cascadeFlags.tofOuter) { + const bool applyNSigmaCut = cascadeFlags.rejectNoOuterTofSignal || hasPosOuterTof; + if (applyNSigmaCut && nSigmaPosOuterTof > cascadeSelectionValues.posMaxNSigma) { + continue; + } + } + histos.fill(HIST("reconstructedCandidates/Cascade/hSelectionQa"), 21 /* Pass pos otof nsigma*/); + + if (cascadeFlags.tofOuter) { + const bool applyNSigmaCut = cascadeFlags.rejectNoOuterTofSignal || hasNegOuterTof; + if (applyNSigmaCut && nSigmaNegOuterTof > cascadeSelectionValues.negMaxNSigma) { + continue; + } + } + histos.fill(HIST("reconstructedCandidates/Cascade/hSelectionQa"), 22 /* Pass neg otof nsigma*/); histos.fill(HIST("reconstructedCandidates/Cascade/AfterSelection/hPosDCAxy"), positive.dcaXY() * ToMicrons); histos.fill(HIST("reconstructedCandidates/Cascade/AfterSelection/hNegDCAxy"), negative.dcaXY() * ToMicrons); histos.fill(HIST("reconstructedCandidates/Cascade/AfterSelection/hBachDCAxy"), bachelor.dcaXY() * ToMicrons); diff --git a/ALICE3/Utils/a3StrangenessTofPidHelper.h b/ALICE3/Utils/a3StrangenessTofPidHelper.h new file mode 100644 index 00000000000..b39a3fe011e --- /dev/null +++ b/ALICE3/Utils/a3StrangenessTofPidHelper.h @@ -0,0 +1,386 @@ +// 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 a3StrangenessTofPidHelper.h +/// \brief Helper to calculate expected arrival time for decay products of weakly decaying particles +/// \author Jesper Karlsson Gumprecht +/// + +#ifndef ALICE3_UTILS_A3STRANGENESSTOFPIDHELPER_H_ +#define ALICE3_UTILS_A3STRANGENESSTOFPIDHELPER_H_ + +#include "ALICE3/Core/TrackUtilities.h" + +#include +#include + +#include + +#include +#include + +namespace o2::upgrade::stratofpid +{ + +enum class Topology { V0, + Cascade }; + +enum class TrackType { Positive, + Negative, + V0, + Bachelor, + Cascade }; + +enum class CandidateType { K0S, + Lambda, + AntiLambda, + Xi, + AntiXi, + Omega, + AntiOmega }; + +struct TrackTofResult { + bool hasInnerTof, hasOuterTof; + float nSigmaInner, nSigmaOuter; + float expectedTimeInner, expectedTimeOuter; + float measuredTimeInner, measuredTimeOuter; +}; + +template +struct StrangenessTofResults; + +template <> +struct StrangenessTofResults { + TrackTofResult pos; + TrackTofResult neg; +}; + +template <> +struct StrangenessTofResults { + TrackTofResult pos; + TrackTofResult neg; + TrackTofResult bach; +}; + +template +struct CandidateInfo; + +template <> +struct CandidateInfo { + static constexpr float V0Mass = o2::constants::physics::MassKaonNeutral; + static constexpr float PosMass = o2::constants::physics::MassPionCharged; + static constexpr float NegMass = o2::constants::physics::MassPionCharged; +}; +template <> +struct CandidateInfo { + static constexpr float V0Mass = o2::constants::physics::MassLambda0; + static constexpr float PosMass = o2::constants::physics::MassProton; + static constexpr float NegMass = o2::constants::physics::MassPionCharged; +}; +template <> +struct CandidateInfo { + static constexpr float V0Mass = o2::constants::physics::MassLambda0; + static constexpr float PosMass = o2::constants::physics::MassPionCharged; + static constexpr float NegMass = o2::constants::physics::MassProton; +}; +template <> +struct CandidateInfo { + static constexpr float V0Mass = o2::constants::physics::MassLambda0; + static constexpr float PosMass = o2::constants::physics::MassProton; + static constexpr float NegMass = o2::constants::physics::MassPionCharged; + static constexpr float BachMass = o2::constants::physics::MassPionCharged; + static constexpr float CascMass = o2::constants::physics::MassXiMinus; +}; +template <> +struct CandidateInfo { + static constexpr float V0Mass = o2::constants::physics::MassLambda0; + static constexpr float PosMass = o2::constants::physics::MassPionCharged; + static constexpr float NegMass = o2::constants::physics::MassProton; + static constexpr float BachMass = o2::constants::physics::MassPionCharged; + static constexpr float CascMass = o2::constants::physics::MassXiMinus; +}; +template <> +struct CandidateInfo { + static constexpr float V0Mass = o2::constants::physics::MassLambda0; + static constexpr float PosMass = o2::constants::physics::MassProton; + static constexpr float NegMass = o2::constants::physics::MassPionCharged; + static constexpr float BachMass = o2::constants::physics::MassKaonCharged; + static constexpr float CascMass = o2::constants::physics::MassOmegaMinus; +}; +template <> +struct CandidateInfo { + static constexpr float V0Mass = o2::constants::physics::MassLambda0; + static constexpr float PosMass = o2::constants::physics::MassPionCharged; + static constexpr float NegMass = o2::constants::physics::MassProton; + static constexpr float BachMass = o2::constants::physics::MassKaonCharged; + static constexpr float CascMass = o2::constants::physics::MassOmegaMinus; +}; + +class StrangenessTofPidBase +{ + public: + StrangenessTofPidBase() : mRand(0) {} + void setRandomSeed(const int seed) { mRand.SetSeed(seed); } + void setMagneticField(const float b) { mMagneticField = b; } + void setInnerResolution(const float res) { mInnerResolution = res; } + void setOuterResolution(const float res) { mOuterResolution = res; } + void setResolution(const float ires, const float ores) + { + setInnerResolution(ires); + setOuterResolution(ores); + } + void setResolution(const float res) + { + setInnerResolution(res); + setOuterResolution(res); + } + void setInnerRadius(const float radius) { mInnerRadius = radius; } + void setOuterRadius(const float radius) { mOuterRadius = radius; } + void setRadius(const float iradius, const float oradius) + { + setInnerRadius(iradius); + setOuterRadius(oradius); + } + void setTrack(const TrackType type, const o2::track::TrackParCov& track, const float vt = -1.f, const float mass = -1.f) + { + switch (type) { + case TrackType::Positive: + mPosTrack = track; + mPosTrackTime = vt * NanoToPico; + mTruePosCandMass = mass; + break; + case TrackType::Negative: + mNegTrack = track; + mNegTrackTime = vt * NanoToPico; + mTrueNegCandMass = mass; + break; + case TrackType::V0: + mV0Track = track; + break; + + default: + break; + } + } + + bool propagateTrackToOriginalRadius(o2::track::TrackParCov& track, const std::array originalVtx) const + { + static constexpr float Tolerance = 1e-2; + std::array trackXYZ{}; + track.getXYZGlo(trackXYZ); + + // Check if track is already in the right place + if (std::abs(std::hypot(trackXYZ[0], trackXYZ[1]) - std::hypot(originalVtx[0], originalVtx[1])) < Tolerance) { + return true; + } + + float targetX = 1e+3; + if (!track.getXatLabR(std::hypot(originalVtx[0], originalVtx[1]), targetX, mMagneticField)) { + return false; + } + + return track.propagateTo(targetX, mMagneticField); + } + + [[nodiscard]] float calculateArrivalTime(const o2::track::TrackParCov& track, const std::array vtx, const float radius, const float mass) const + { + o2::track::TrackParCov propagatedTrack(track); + if (!propagateTrackToOriginalRadius(propagatedTrack, vtx)) { + return FailedToPropagate; + } + + const float trackLength = o2::upgrade::computeTrackLength(propagatedTrack, radius, mMagneticField); + if (trackLength < 0) { + return FailedToPropagate; + } + + const float velocity = o2::upgrade::computeParticleVelocity(propagatedTrack.getP(), mass); + return trackLength / velocity; + } + + // Special case for V0s + [[nodiscard]] float calculateArrivalTimeV0(const o2::track::TrackParCov& track, const std::array pv, const std::array sv, const float mass) const + { + o2::track::TrackParCov propagatedTrack(track); + if (!propagateTrackToOriginalRadius(propagatedTrack, pv)) { + return FailedToPropagate; + } + + const float dx = pv[0] - sv[0]; + const float dy = pv[1] - sv[1]; + const float dz = pv[2] - sv[2]; + const float trackLength = std::hypot(dx, dy, dz); + const float velocity = o2::upgrade::computeParticleVelocity(propagatedTrack.getP(), mass); + return trackLength / velocity; + } + + float smear(const float time, const float sigma) + { + return mRand.Gaus(time, sigma); + } + + template + StrangenessTofResults findNSigmas(const std::array vtx, const std::array vtxV0, const float timeOffset = 0) + { + const float v0ExpectedTime = timeOffset + calculateArrivalTimeV0(mV0Track, vtx, vtxV0, CandidateInfo::V0Mass); + const float posExpectedTimeInner = v0ExpectedTime + calculateArrivalTime(mPosTrack, vtxV0, mInnerRadius, CandidateInfo::PosMass); + const float posExpectedTimeOuter = v0ExpectedTime + calculateArrivalTime(mPosTrack, vtxV0, mOuterRadius, CandidateInfo::PosMass); + const float negExpectedTimeInner = v0ExpectedTime + calculateArrivalTime(mNegTrack, vtxV0, mInnerRadius, CandidateInfo::NegMass); + const float negExpectedTimeOuter = v0ExpectedTime + calculateArrivalTime(mNegTrack, vtxV0, mOuterRadius, CandidateInfo::NegMass); + + if (!mMeasuredTimeSmeared) { + mPosMeasuredTimeInner = smear(mPosTrackTime + calculateArrivalTime(mPosTrack, vtxV0, mInnerRadius, mTruePosCandMass), mInnerResolution); + mPosMeasuredTimeOuter = smear(mPosTrackTime + calculateArrivalTime(mPosTrack, vtxV0, mOuterRadius, mTruePosCandMass), mOuterResolution); + mNegMeasuredTimeInner = smear(mNegTrackTime + calculateArrivalTime(mNegTrack, vtxV0, mInnerRadius, mTrueNegCandMass), mInnerResolution); + mNegMeasuredTimeOuter = smear(mNegTrackTime + calculateArrivalTime(mNegTrack, vtxV0, mOuterRadius, mTrueNegCandMass), mOuterResolution); + mMeasuredTimeSmeared = true; + } + + return StrangenessTofResults{ + .pos = { + .hasInnerTof = (mPosMeasuredTimeInner > 0 && posExpectedTimeInner > 0), + .hasOuterTof = (mPosMeasuredTimeOuter > 0 && posExpectedTimeOuter > 0), + .nSigmaInner = (mPosMeasuredTimeInner - posExpectedTimeInner) / mInnerResolution, + .nSigmaOuter = (mPosMeasuredTimeOuter - posExpectedTimeOuter) / mOuterResolution, + .expectedTimeInner = posExpectedTimeInner * PicoToNano, + .expectedTimeOuter = posExpectedTimeOuter * PicoToNano, + .measuredTimeInner = mPosMeasuredTimeInner * PicoToNano, + .measuredTimeOuter = mPosMeasuredTimeOuter * PicoToNano, + }, + .neg = { + .hasInnerTof = (mNegMeasuredTimeInner > 0 && negExpectedTimeInner > 0), + .hasOuterTof = (mNegMeasuredTimeOuter > 0 && negExpectedTimeOuter > 0), + .nSigmaInner = (mNegMeasuredTimeInner - negExpectedTimeInner) / mInnerResolution, + .nSigmaOuter = (mNegMeasuredTimeOuter - negExpectedTimeOuter) / mOuterResolution, + .expectedTimeInner = negExpectedTimeInner * PicoToNano, + .expectedTimeOuter = negExpectedTimeOuter * PicoToNano, + .measuredTimeInner = mNegMeasuredTimeInner * PicoToNano, + .measuredTimeOuter = mNegMeasuredTimeOuter * PicoToNano, + }}; + } + + void reset() + { + mMeasuredTimeSmeared = false; + mPosTrackTime = 0.f; + mNegTrackTime = 0.f; + mPosMeasuredTimeInner = 0.f; + mPosMeasuredTimeOuter = 0.f; + mNegMeasuredTimeInner = 0.f; + mNegMeasuredTimeOuter = 0.f; + mTruePosCandMass = 0.f; + mTrueNegCandMass = 0.f; + mPosTrack = o2::track::TrackParCov(); + mNegTrack = o2::track::TrackParCov(); + mV0Track = o2::track::TrackParCov(); + } + + protected: + static constexpr float NanoToPico = 1e+3; + static constexpr float PicoToNano = 1e-3; + static constexpr float FailedToPropagate = -1e+8; + + // Detector config + float mInnerResolution = 20.f; // ps + float mOuterResolution = 20.f; // ps + float mInnerRadius = 21.f; // cm + float mOuterRadius = 92.f; // cm + float mMagneticField = 20.f; // kG + + // Track properties + bool mMeasuredTimeSmeared = false; + float mPosTrackTime{}, mNegTrackTime{}; + float mPosMeasuredTimeInner{}, mPosMeasuredTimeOuter{}; + float mNegMeasuredTimeInner{}, mNegMeasuredTimeOuter{}; + float mTruePosCandMass{}, mTrueNegCandMass{}; + o2::track::TrackParCov mPosTrack, mNegTrack, mV0Track; + + // For smearing + TRandom3 mRand; +}; + +template +class StrangenessTofPid; + +template <> +class StrangenessTofPid : public StrangenessTofPidBase +{ +}; + +template <> +class StrangenessTofPid : public StrangenessTofPidBase +{ + public: + void setTrack(const TrackType type, const o2::track::TrackParCov& track, const float vt = -1.f, const float mass = -1.f) + { + switch (type) { + case TrackType::Bachelor: + mBachTrack = track; + mBachTrackTime = vt * NanoToPico; + mTrueBachCandMass = mass; + break; + case TrackType::Cascade: + mCascTrack = track; + break; + default: + StrangenessTofPidBase::setTrack(type, track, vt, mass); + break; + } + } + + template + StrangenessTofResults findNSigmas(const std::array vtx, const std::array vtxCascade, const std::array vtxV0) + { + const float cascExpectedTime = calculateArrivalTime(mCascTrack, vtx, std::hypot(vtxCascade[0], vtxCascade[1]), CandidateInfo::CascMass); + const float bachExpectedTimeInner = cascExpectedTime + calculateArrivalTime(mBachTrack, vtxCascade, mInnerRadius, CandidateInfo::BachMass); + const float bachExpectedTimeOuter = cascExpectedTime + calculateArrivalTime(mBachTrack, vtxCascade, mOuterRadius, CandidateInfo::BachMass); + + if (!mMeasuredTimeSmeared) { + mBachMeasuredTimeInner = smear(mBachTrackTime + calculateArrivalTime(mBachTrack, vtxCascade, mInnerRadius, mTrueBachCandMass), mInnerResolution); + mBachMeasuredTimeOuter = smear(mBachTrackTime + calculateArrivalTime(mBachTrack, vtxCascade, mOuterRadius, mTrueBachCandMass), mOuterResolution); + } + + const auto straTofResultsV0 = StrangenessTofPidBase::findNSigmas(vtxCascade, vtxV0, cascExpectedTime); + return StrangenessTofResults{ + .pos = straTofResultsV0.pos, + .neg = straTofResultsV0.neg, + .bach = { + .hasInnerTof = (mBachMeasuredTimeInner > 0 && bachExpectedTimeInner > 0), + .hasOuterTof = (mBachMeasuredTimeOuter > 0 && bachExpectedTimeOuter > 0), + .nSigmaInner = (mBachMeasuredTimeInner - bachExpectedTimeInner) / mInnerResolution, + .nSigmaOuter = (mBachMeasuredTimeOuter - bachExpectedTimeOuter) / mOuterResolution, + .expectedTimeInner = bachExpectedTimeInner * PicoToNano, + .expectedTimeOuter = bachExpectedTimeOuter * PicoToNano, + .measuredTimeInner = mBachMeasuredTimeInner * PicoToNano, + .measuredTimeOuter = mBachMeasuredTimeOuter * PicoToNano, + }}; + } + + void reset() + { + mBachTrackTime = 0.f; + mTrueBachCandMass = 0.f; + mBachMeasuredTimeInner = 0.f; + mBachMeasuredTimeOuter = 0.f; + mBachTrack = o2::track::TrackParCov(); + mCascTrack = o2::track::TrackParCov(); + StrangenessTofPidBase::reset(); + } + + protected: + // Track properties + float mBachTrackTime{}, mTrueBachCandMass{}; + float mBachMeasuredTimeInner{}, mBachMeasuredTimeOuter{}; + o2::track::TrackParCov mBachTrack, mCascTrack; +}; + +} // namespace o2::upgrade::stratofpid +#endif // ALICE3_UTILS_A3STRANGENESSTOFPIDHELPER_H_