diff --git a/Phys/FunctorCore/include/Functors/PID.h b/Phys/FunctorCore/include/Functors/PID.h new file mode 100644 index 0000000000000000000000000000000000000000..8c74eca3dcc94f17f632ee5e594280c3ae1c741a --- /dev/null +++ b/Phys/FunctorCore/include/Functors/PID.h @@ -0,0 +1,87 @@ +/*****************************************************************************\ +* (c) Copyright 2023 CERN for the benefit of the LHCb Collaboration * +* * +* This software is distributed under the terms of the GNU General Public * +* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". * +* * +* In applying this licence, 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. * +\*****************************************************************************/ +#pragma once +#include "Event/ProtoParticle.h" +#include "Functors/Function.h" +#include "Kernel/RichParticleIDType.h" + +namespace Functors::PID { + + namespace details { + + LHCb::RichPID const* getRichPID( LHCb::Particle const& p ) { + auto const* proto = p.proto(); + return proto ? proto->richPID() : nullptr; + } + + } // namespace details + + template <Rich::ParticleIDType pidtype, bool scaled = false> + struct RichDLL : public Function { + auto operator()( LHCb::Particle const& p ) const { + auto const* pid = details::getRichPID( p ); + if constexpr ( scaled ) { + return pid ? Functors::Optional{pid->scaledDLLForCombDLL( pidtype )} : std::nullopt; + } else { + return pid ? Functors::Optional{pid->particleDeltaLL( pidtype )} : std::nullopt; + } + } + + auto operator()( LHCb::Particle const* p ) const { return ( *this )( *p ); } + }; + + using RichDLLe = RichDLL<Rich::ParticleIDType::Electron>; + using RichDLLmu = RichDLL<Rich::ParticleIDType::Muon>; + using RichDLLp = RichDLL<Rich::ParticleIDType::Proton>; + using RichDLLk = RichDLL<Rich::ParticleIDType::Kaon>; + using RichDLLpi = RichDLL<Rich::ParticleIDType::Pion>; + using RichDLLd = RichDLL<Rich::ParticleIDType::Deuteron>; + using RichDLLbt = RichDLL<Rich::ParticleIDType::BelowThreshold>; + + using RichScaledDLLe = RichDLL<Rich::ParticleIDType::Electron, true>; + using RichScaledDLLmu = RichDLL<Rich::ParticleIDType::Muon, true>; + + struct Rich1GasUsed : public Predicate { + bool operator()( LHCb::Particle const& p ) const { + auto const* pid = details::getRichPID( p ); + return pid ? pid->usedRich1Gas() : false; + } + + auto operator()( LHCb::Particle const* p ) const { return ( *this )( *p ); } + }; + + struct Rich2GasUsed : public Predicate { + bool operator()( LHCb::Particle const& p ) const { + auto const* pid = details::getRichPID( p ); + return pid ? pid->usedRich2Gas() : false; + } + + auto operator()( LHCb::Particle const* p ) const { return ( *this )( *p ); } + }; + + template <Rich::ParticleIDType pidtype> + struct RichThreshold : public Predicate { + bool operator()( LHCb::Particle const& p ) const { + auto const* pid = details::getRichPID( p ); + return pid ? pid->isAboveThreshold( pidtype ) : false; + } + + auto operator()( LHCb::Particle const* p ) const { return ( *this )( *p ); } + }; + + using RichThresholdEl = RichThreshold<Rich::ParticleIDType::Electron>; + using RichThresholdKa = RichThreshold<Rich::ParticleIDType::Kaon>; + using RichThresholdMu = RichThreshold<Rich::ParticleIDType::Muon>; + using RichThresholdPi = RichThreshold<Rich::ParticleIDType::Pion>; + using RichThresholdPr = RichThreshold<Rich::ParticleIDType::Proton>; + using RichThresholdDe = RichThreshold<Rich::ParticleIDType::Deuteron>; + +} // namespace Functors::PID diff --git a/Phys/FunctorCore/include/Functors/Particle.h b/Phys/FunctorCore/include/Functors/Particle.h index 8713c88e97986a6738c8f0f1781602162e63a02b..2e93e529f4b47d56db9cb81ffb25a183d85c9875 100644 --- a/Phys/FunctorCore/include/Functors/Particle.h +++ b/Phys/FunctorCore/include/Functors/Particle.h @@ -195,9 +195,13 @@ namespace Functors::Particle { bool operator()( LHCb::ProtoParticle const* pp ) const { return pp && ( *this )( *pp ); } }; - using PPHasRich = PPHasInfo<LHCb::ProtoParticle::RichPIDStatus>; using PPHasMuonInfo = PPHasInfo<LHCb::ProtoParticle::InAccMuon>; + struct PPHasRich : Predicate { + bool operator()( LHCb::ProtoParticle const& pp ) const { return pp.richPID(); } + bool operator()( LHCb::ProtoParticle const* pp ) const { return pp && ( *this )( *pp ); } + }; + struct PPHasEcalInfo : public Predicate { bool operator()( LHCb::ProtoParticle const& pp ) const { constexpr auto ecal_info = std::array{ diff --git a/Phys/FunctorCore/include/Functors/TrackLike.h b/Phys/FunctorCore/include/Functors/TrackLike.h index ea3c1d59a938b377aafe70aba59a23e053c77861..d8c561db216ff81025e5d7771d8962a27a32bc25 100644 --- a/Phys/FunctorCore/include/Functors/TrackLike.h +++ b/Phys/FunctorCore/include/Functors/TrackLike.h @@ -407,16 +407,6 @@ namespace Functors::Track { return d.HcalPIDe(); case additInfo::HcalPIDmu: return d.HcalPIDmu(); - case additInfo::RichDLLp: - return d.RichDLLp(); - case additInfo::RichDLLk: - return d.RichDLLk(); - case additInfo::RichDLLpi: - return d.RichDLLpi(); - case additInfo::RichDLLd: - return d.RichDLLd(); - case additInfo::RichDLLbt: - return d.RichDLLbt(); case additInfo::CaloEoverP: return d.ElectronShowerEoP(); case additInfo::ElectronShowerDLL: @@ -450,13 +440,6 @@ namespace Functors::Track { using EcalPIDmu = NumAdditionalInfo<additInfo::EcalPIDmu>; using HcalPIDe = NumAdditionalInfo<additInfo::HcalPIDe>; using HcalPIDmu = NumAdditionalInfo<additInfo::HcalPIDmu>; - using RichDLLe = NumAdditionalInfo<additInfo::RichDLLe>; - using RichDLLmu = NumAdditionalInfo<additInfo::RichDLLmu>; - using RichDLLp = NumAdditionalInfo<additInfo::RichDLLp>; - using RichDLLk = NumAdditionalInfo<additInfo::RichDLLk>; - using RichDLLpi = NumAdditionalInfo<additInfo::RichDLLpi>; - using RichDLLd = NumAdditionalInfo<additInfo::RichDLLd>; - using RichDLLbt = NumAdditionalInfo<additInfo::RichDLLbt>; using ElectronShowerEoP = NumAdditionalInfo<additInfo::CaloEoverP>; using ElectronShowerDLL = NumAdditionalInfo<additInfo::ElectronShowerDLL>; using ClusterMatch = NumAdditionalInfo<additInfo::CaloTrMatch>; diff --git a/Phys/FunctorCore/python/Functors/__init__.py b/Phys/FunctorCore/python/Functors/__init__.py index ee5e0ec89a005afb98fa06f863849578bb89cf3f..eede027924abd875e39e366b43a03a71c54029f2 100644 --- a/Phys/FunctorCore/python/Functors/__init__.py +++ b/Phys/FunctorCore/python/Functors/__init__.py @@ -798,33 +798,80 @@ HCALPIDMU = Functor( Functor's call operator expects a track like object.""") RICH_DLL_E = Functor( - 'RICH_DLL_E', "Track::RichDLLe", """Rich-based DLL for electron-ID. + 'RICH_DLL_E', "PID::RichDLLe", """Rich-based DLL for electron-ID. Functor's call operator expects a track like object.""") RICH_DLL_MU = Functor( - 'RICH_DLL_MU', "Track::RichDLLmu", """Rich-based DLL for mu-ID. + 'RICH_DLL_MU', "PID::RichDLLmu", """Rich-based DLL for mu-ID. Functor's call operator expects a track like object.""") RICH_DLL_P = Functor( - 'RICH_DLL_P', "Track::RichDLLp", """Rich-based DLL for proton-ID. + 'RICH_DLL_P', "PID::RichDLLp", """Rich-based DLL for proton-ID. Functor's call operator expects a track like object.""") RICH_DLL_K = Functor( - 'RICH_DLL_K', "Track::RichDLLk", """Rich-based DLL for kaon-ID. + 'RICH_DLL_K', "PID::RichDLLk", """Rich-based DLL for kaon-ID. Functor's call operator expects a track like object.""") RICH_DLL_PI = Functor( - 'RICH_DLL_PI', "Track::RichDLLpi", """Rich-based DLL for pion-ID. + 'RICH_DLL_PI', "PID::RichDLLpi", """Rich-based DLL for pion-ID. Functor's call operator expects a track like object.""") RICH_DLL_D = Functor( - 'RICH_DLL_D', "Track::RichDLLd", """Rich-based DLL for deuteron-ID. + 'RICH_DLL_D', "PID::RichDLLd", """Rich-based DLL for deuteron-ID. Functor's call operator expects a track like object.""") RICH_DLL_BT = Functor( - 'RICH_DLL_BT', "Track::RichDLLbt", + 'RICH_DLL_BT', "PID::RichDLLbt", """Rich-based DLL for below threshold tracks. + Functor's call operator expects a track like object.""") +RICH_SCALED_DLL_E = Functor( + 'RICH_SCALED_DLL_E', "PID::RichScaledDLLe", + """Rich-based DLL for electron-ID. + Scaled with monotonic function to approximate true DLL. + For usage in combined DLLs (with other subdetectors). + + Functor's call operator expects a track like object.""") +RICH_SCALED_DLL_MU = Functor( + 'RICH_SCALED_DLL_MU', "PID::RichScaledDLLmu", """Rich-based DLL for mu-ID. + Scaled with monotonic function to approximate true DLL. + For usage in combined DLLs (with other subdetectors). + + Functor's call operator expects a track like object.""") +RICH1_GAS_USED = Functor( + 'RICH1_GAS_USED', "PID::Rich1GasUsed", """Rich 1 gas flag. + + Functor's call operator expects a track like object.""") +RICH2_GAS_USED = Functor( + 'RICH2_GAS_USED', "PID::Rich2GasUsed", """Rich 2 gas flag. + + Functor's call operator expects a track like object.""") +RICH_THRESHOLD_EL = Functor( + 'RICH_THRESHOLD_EL', "PID::RichThresholdEl", + """Rich threshold for electrons. + + Functor's call operator expects a track like object.""") +RICH_THRESHOLD_KA = Functor( + 'RICH_THRESHOLD_KA', "PID::RichThresholdKa", """Rich threshold for kaons. + + Functor's call operator expects a track like object.""") +RICH_THRESHOLD_MU = Functor( + 'RICH_THRESHOLD_MU', "PID::RichThresholdMu", """Rich threshold for muons. + + Functor's call operator expects a track like object.""") +RICH_THRESHOLD_PI = Functor( + 'RICH_THRESHOLD_PI', "PID::RichThresholdPi", """Rich threshold for pions. + + Functor's call operator expects a track like object.""") +RICH_THRESHOLD_PR = Functor( + 'RICH_THRESHOLD_PR', "PID::RichThresholdPr", """Rich threshold for protons. + + Functor's call operator expects a track like object.""") +RICH_THRESHOLD_DE = Functor( + 'RICH_THRESHOLD_DE', "PID::RichThresholdDe", + """Rich threshold for deuterons. + Functor's call operator expects a track like object.""") ELECTRONSHOWEREOP = Functor( 'ELECTRONSHOWEREOP', "Track::ElectronShowerEoP", diff --git a/Phys/FunctorCore/tests/options/test_functors_tested.py b/Phys/FunctorCore/tests/options/test_functors_tested.py index 8348dc2dbd572ad5ba6d94e0a5c1ed4d165b8534..3b15d3783429c9a60cfd3720cb81687b29a5abc3 100644 --- a/Phys/FunctorCore/tests/options/test_functors_tested.py +++ b/Phys/FunctorCore/tests/options/test_functors_tested.py @@ -80,7 +80,10 @@ exceptions = [ 'Functors::Particle::GetProtoParticle', 'Functors::Adapters::GenerationFromCompositeV1( /* The generation of the children. Generation 1 are direct children, Generation 2 are grandchildren and so on. */ std::integral_constant<int, 1>{}', 'Functors::Adapters::GenerationFromCompositeV1( /* The generation of the children. Generation 1 are direct children, Generation 2 are grandchildren and so on. */ std::integral_constant<int, 2>{}', - 'Functors::Particle::ParticlePropertyUser' + 'Functors::Particle::ParticlePropertyUser', + 'Functors::PID::RichThresholdDe', 'Functors::PID::RichThresholdKa', + 'Functors::PID::RichThresholdMu', 'Functors::PID::RichThresholdPi', + 'Functors::PID::RichThresholdPr' ] functor_cpp_names = [] diff --git a/Phys/FunctorCore/tests/src/TestFunctors.cpp b/Phys/FunctorCore/tests/src/TestFunctors.cpp index 2edcb7b3593d9a318563c3235877179ae979439d..0f0316f6f4bc08cb3be2156cc3d73cb036c58d50 100644 --- a/Phys/FunctorCore/tests/src/TestFunctors.cpp +++ b/Phys/FunctorCore/tests/src/TestFunctors.cpp @@ -33,6 +33,7 @@ #include "Functors/JIT_includes.h" #include "Functors/MVA.h" #include "Functors/NeutralLike.h" +#include "Functors/PID.h" #include "Functors/Particle.h" #include "Functors/Simulation.h" #include "Functors/TES.h" @@ -216,55 +217,40 @@ BOOST_AUTO_TEST_CASE( test_rich_dll ) { double true_val = 0.3; // get functors - auto const RICH_DLL_E = Functors::Track::RichDLLe{}; - auto const RICH_DLL_K = Functors::Track::RichDLLk{}; - auto const RICH_DLL_PI = Functors::Track::RichDLLpi{}; - auto const RICH_DLL_P = Functors::Track::RichDLLp{}; - auto const RICH_DLL_MU = Functors::Track::RichDLLmu{}; - auto const RICH_DLL_D = Functors::Track::RichDLLd{}; - auto const RICH_DLL_BT = Functors::Track::RichDLLbt{}; - - // define particles - auto e = LHCb::Particle( LHCb::ParticleID{11} ); - auto k = LHCb::Particle( LHCb::ParticleID{321} ); - auto pi = LHCb::Particle( LHCb::ParticleID{-211} ); - auto p = LHCb::Particle( LHCb::ParticleID{2212} ); - auto mu = LHCb::Particle( LHCb::ParticleID{-13} ); - auto d = LHCb::Particle( LHCb::ParticleID{1000010020} ); - - // define proto particles - auto e_proto = LHCb::ProtoParticle(); - auto k_proto = LHCb::ProtoParticle(); - auto pi_proto = LHCb::ProtoParticle(); - auto p_proto = LHCb::ProtoParticle(); - auto mu_proto = LHCb::ProtoParticle(); - auto d_proto = LHCb::ProtoParticle(); + auto const RICH_DLL_E = Functors::PID::RichDLLe{}; + auto const RICH_DLL_K = Functors::PID::RichDLLk{}; + auto const RICH_DLL_PI = Functors::PID::RichDLLpi{}; + auto const RICH_DLL_P = Functors::PID::RichDLLp{}; + auto const RICH_DLL_MU = Functors::PID::RichDLLmu{}; + auto const RICH_DLL_D = Functors::PID::RichDLLd{}; + auto const RICH_DLL_BT = Functors::PID::RichDLLbt{}; + + // define particle and protoparticle + auto part = LHCb::Particle( LHCb::ParticleID{11} ); + auto proto = LHCb::ProtoParticle(); // add DLL info - e_proto.addInfo( LHCb::ProtoParticle::additionalInfo::RichDLLe, true_val ); - k_proto.addInfo( LHCb::ProtoParticle::additionalInfo::RichDLLk, true_val ); - pi_proto.addInfo( LHCb::ProtoParticle::additionalInfo::RichDLLpi, true_val ); - p_proto.addInfo( LHCb::ProtoParticle::additionalInfo::RichDLLp, true_val ); - mu_proto.addInfo( LHCb::ProtoParticle::additionalInfo::RichDLLmu, true_val ); - d_proto.addInfo( LHCb::ProtoParticle::additionalInfo::RichDLLd, true_val ); - d_proto.addInfo( LHCb::ProtoParticle::additionalInfo::RichDLLbt, true_val ); - - // set proto in particles - e.setProto( &e_proto ); - k.setProto( &k_proto ); - pi.setProto( &pi_proto ); - p.setProto( &p_proto ); - mu.setProto( &mu_proto ); - d.setProto( &d_proto ); + auto pid = LHCb::RichPID(); + pid.setParticleDeltaLL( Rich::ParticleIDType::Electron, true_val ); + pid.setParticleDeltaLL( Rich::ParticleIDType::Muon, true_val ); + pid.setParticleDeltaLL( Rich::ParticleIDType::Pion, true_val ); + pid.setParticleDeltaLL( Rich::ParticleIDType::Kaon, true_val ); + pid.setParticleDeltaLL( Rich::ParticleIDType::Proton, true_val ); + pid.setParticleDeltaLL( Rich::ParticleIDType::Deuteron, true_val ); + pid.setParticleDeltaLL( Rich::ParticleIDType::BelowThreshold, true_val ); + + // add info + proto.setRichPID( &pid ); + part.setProto( &proto ); // do checks - BOOST_CHECK( RICH_DLL_E( e ).value_or( true_val + 1 ) - true_val < 1e-6 ); - BOOST_CHECK( RICH_DLL_K( k ).value_or( true_val + 1 ) - true_val < 1e-6 ); - BOOST_CHECK( RICH_DLL_PI( pi ).value_or( true_val + 1 ) - true_val < 1e-6 ); - BOOST_CHECK( RICH_DLL_P( p ).value_or( true_val + 1 ) - true_val < 1e-6 ); - BOOST_CHECK( RICH_DLL_MU( mu ).value_or( true_val + 1 ) - true_val < 1e-6 ); - BOOST_CHECK( RICH_DLL_D( d ).value_or( true_val + 1 ) - true_val < 1e-6 ); - BOOST_CHECK( RICH_DLL_BT( d ).value_or( true_val + 1 ) - true_val < 1e-6 ); + BOOST_CHECK( RICH_DLL_E( part ).value_or( true_val + 1 ) - true_val < 1e-6 ); + BOOST_CHECK( RICH_DLL_K( part ).value_or( true_val + 1 ) - true_val < 1e-6 ); + BOOST_CHECK( RICH_DLL_PI( part ).value_or( true_val + 1 ) - true_val < 1e-6 ); + BOOST_CHECK( RICH_DLL_P( part ).value_or( true_val + 1 ) - true_val < 1e-6 ); + BOOST_CHECK( RICH_DLL_MU( part ).value_or( true_val + 1 ) - true_val < 1e-6 ); + BOOST_CHECK( RICH_DLL_D( part ).value_or( true_val + 1 ) - true_val < 1e-6 ); + BOOST_CHECK( RICH_DLL_BT( part ).value_or( true_val + 1 ) - true_val < 1e-6 ); } // check we can apply an IsMuon cut to some tracks @@ -417,10 +403,13 @@ BOOST_AUTO_TEST_CASE( test_ai_functors ) { ( Functors::Track::ElectronEnergy{} > 0.f ) & ( Functors::Track::BremHypoEnergy{} > 0.f ) & ( Functors::Track::BremHypoDeltaX{} > 0.f ) & ( Functors::Track::BremHypoID{} > 0 ) & ( Functors::Track::BremTrackBasedEnergy{} > 0.f ) & ( Functors::Track::ElectronID{} > 0 ) & - ( Functors::Track::HcalEoP{} > 0.f ) & ( Functors::Track::RichDLLe{} > 0.f ) & - ( Functors::Track::RichDLLmu{} > 0.f ) & ( Functors::Track::RichDLLp{} > 0.f ) & - ( Functors::Track::RichDLLk{} > 0.f ) & ( Functors::Track::RichDLLpi{} > 0.f ) & - ( Functors::Track::RichDLLd{} > 0.f ) & ( Functors::Track::RichDLLbt{} > 0.f ) ); + ( Functors::Track::HcalEoP{} > 0.f ) & ( Functors::PID::RichDLLe{} > 0.f ) & + ( Functors::PID::RichDLLmu{} > 0.f ) & ( Functors::PID::RichDLLp{} > 0.f ) & + ( Functors::PID::RichDLLk{} > 0.f ) & ( Functors::PID::RichDLLpi{} > 0.f ) & + ( Functors::PID::RichDLLd{} > 0.f ) & ( Functors::PID::RichDLLbt{} > 0.f ) & + ( Functors::PID::RichScaledDLLe{} > 0.f ) & ( Functors::PID::RichScaledDLLmu{} > 0.f ) & + ( Functors::PID::RichThresholdEl{} ) & ( Functors::PID::Rich1GasUsed{} ) & + ( Functors::PID::Rich2GasUsed{} ) ); } BOOST_AUTO_TEST_CASE( test_1trackmva_functor ) { diff --git a/Phys/ProtoParticleFilter/src/ProtoParticleSelection.h b/Phys/ProtoParticleFilter/src/ProtoParticleSelection.h index 1c21927f227d87d1429c88ba32f4d3e87d611884..27b56b24142ab5be07713266b35bdd89055ddaf0 100644 --- a/Phys/ProtoParticleFilter/src/ProtoParticleSelection.h +++ b/Phys/ProtoParticleFilter/src/ProtoParticleSelection.h @@ -402,9 +402,7 @@ public: // Helper classes // Methods to test if a ProtoParticle has any sub-det DLL information /// Does this ProtoParticle have RICH DLL information - inline bool hasRichDLL( const LHCb::ProtoParticle* proto ) const { - return proto->hasInfo( LHCb::ProtoParticle::additionalInfo::RichPIDStatus ); - } + inline bool hasRichDLL( const LHCb::ProtoParticle* proto ) const { return proto->richPID(); } /// Does this ProtoParticle have MUON DLL information inline bool hasMuonDLL( const LHCb::ProtoParticle* proto ) const {