diff --git a/CaloFuture/CaloFuturePIDs/src/AcceptanceCaloAlgs.cpp b/CaloFuture/CaloFuturePIDs/src/AcceptanceCaloAlgs.cpp index 21a3cfbda5f244e8a7b3ec7c9447b4d71b36fe53..5f28dcf0d34b405ffe60e09616222595f93be2f9 100644 --- a/CaloFuture/CaloFuturePIDs/src/AcceptanceCaloAlgs.cpp +++ b/CaloFuture/CaloFuturePIDs/src/AcceptanceCaloAlgs.cpp @@ -72,22 +72,23 @@ namespace LHCb::Calo { // acceptance type to extrapolation state // also taking into account which type of tracks are allowed std::optional extrapolation_stateloc_acc( CaloAcceptance acceptance, Tracks const& tracks ) { - auto const trktype = tracks.type(); + if ( acceptance == CaloAcceptance::Unknown ) return std::nullopt; // type to state location (if not avaible, not valid type) - auto const acctotypemap = std::map>{ - {CaloAcceptance::Brem, - {{TT::Long, SL::ClosestToBeam}, - {TT::Downstream, SL::FirstMeasurement}, - {TT::Velo, SL::ClosestToBeam}, - {TT::Upstream, SL::ClosestToBeam}}}, - {CaloAcceptance::Ecal, - {{TT::Long, SL::EndRich2}, {TT::Downstream, SL::EndRich2}, {TT::Ttrack, SL::LastMeasurement}}}, - {CaloAcceptance::Hcal, - {{TT::Long, SL::EndRich2}, {TT::Downstream, SL::EndRich2}, {TT::Ttrack, SL::LastMeasurement}}}, - }; - // if not available, not valid acceptance + track type combination - auto trktypes = acctotypemap.at( acceptance ); - return ( trktypes.find( trktype ) != trktypes.end() ) ? std::optional{trktypes[trktype]} : std::nullopt; + switch ( tracks.type() ) { + case TT::Long: + return acceptance == CaloAcceptance::Brem ? SL::ClosestToBeam : SL::EndRich2; + case TT::Downstream: + return acceptance == CaloAcceptance::Brem ? SL::FirstMeasurement : SL::EndRich2; + case TT::Velo: + case TT::Upstream: + return acceptance == CaloAcceptance::Brem ? std::optional{SL::ClosestToBeam} : std::nullopt; + case TT::Ttrack: + return ( acceptance == CaloAcceptance::Ecal ) || ( acceptance == CaloAcceptance::Hcal ) + ? std::optional{SL::LastMeasurement} + : std::nullopt; + default: + return std::nullopt; + } } } // namespace diff --git a/Muon/MuonID/src/component/MuonIDHltAlg.cpp b/Muon/MuonID/src/component/MuonIDHltAlg.cpp index a547a28122757ee885c2a179d9a84762fb20b20d..3773d6c3029878630f4db1c3e16690894788333d 100644 --- a/Muon/MuonID/src/component/MuonIDHltAlg.cpp +++ b/Muon/MuonID/src/component/MuonIDHltAlg.cpp @@ -313,9 +313,9 @@ public: MuonTrackExtrapolation extrapolation; if constexpr ( std::is_same_v ) { - extrapolation = extrapolateTrack( track.StatePosDir( 1 ), cond ); + extrapolation = extrapolateTrack( track.StatePosDir( SL::EndT ), cond ); } else { - extrapolation = extrapolateTrack( track.positionDirection( SL::EndRich2 ), cond ); + extrapolation = extrapolateTrack( track.StatePosDir( SL::EndRich2 ), cond ); } const bool inAcc = inAcceptance( extrapolation, cond ); if ( !inAcc ) return muPid; @@ -444,12 +444,12 @@ private: // methods // Linear extrapolation equivalent to TrackLinearExtrapolator for ( unsigned station = 0; station != cond.m_stationsCount; ++station ) { // x(z') = x(z) + (dx/dz * (z' - z)) - extrapolation[station] = {LHCb::Utils::as_arithmetic( state( 0 ) ) + - LHCb::Utils::as_arithmetic( state( 3 ) ) * - ( cond.m_stationZ[station] - LHCb::Utils::as_arithmetic( state( 2 ) ) ), - LHCb::Utils::as_arithmetic( state( 1 ) ) + - LHCb::Utils::as_arithmetic( state( 4 ) ) * - ( cond.m_stationZ[station] - LHCb::Utils::as_arithmetic( state( 2 ) ) )}; + extrapolation[station] = {LHCb::Utils::as_arithmetic( state.x() ) + + LHCb::Utils::as_arithmetic( state.tx() ) * + ( cond.m_stationZ[station] - LHCb::Utils::as_arithmetic( state.z() ) ), + LHCb::Utils::as_arithmetic( state.y() ) + + LHCb::Utils::as_arithmetic( state.ty() ) * + ( cond.m_stationZ[station] - LHCb::Utils::as_arithmetic( state.z() ) )}; } return extrapolation; } diff --git a/Muon/MuonMatch/src/MuonMatchVeloUTSoA.cpp b/Muon/MuonMatch/src/MuonMatchVeloUTSoA.cpp index 47d5f1af9a5964ee8eebf5f1961912ea1a0c349c..bd680a8ad8e0a1bd8e18d61a7a1e011086ba2058 100644 --- a/Muon/MuonMatch/src/MuonMatchVeloUTSoA.cpp +++ b/Muon/MuonMatch/src/MuonMatchVeloUTSoA.cpp @@ -34,10 +34,10 @@ UTTracks MuonMatchVeloUTSoA::operator()( const EventContext& evtCtx, const UTTra UTTracks matched{seeds.getVeloAncestors(), Zipping::generateZipIdentifier(), memResource}; matched.reserve( seeds.size() ); - + const auto velozipped = seeds.getVeloAncestors()->scalar(); for ( auto const& seed : seeds.scalar() ) { auto const t = seed.offset(); - State state( seed ); + State state( seed, velozipped[seed.trackVP().cast()] ); auto mask = this->matchByTrackType( state, hit_cont, memResource, magnet ); matched.copy_back( seeds, t, mask ); diff --git a/Muon/MuonMatch/src/Utils.h b/Muon/MuonMatch/src/Utils.h index d80989ab5858c55f72f4be6e9f3cf25089c25f11..cb29ddce681d5f83fb3988509262a01365ba216f 100644 --- a/Muon/MuonMatch/src/Utils.h +++ b/Muon/MuonMatch/src/Utils.h @@ -14,6 +14,7 @@ #include // LHCb #include "Event/PrUpstreamTracks.h" +#include "Event/PrVeloTracks.h" #include "Event/State.h" // from MuonDAQ #include "MuonDAQ/CommonMuonHit.h" @@ -32,12 +33,16 @@ struct Candidate final { struct State { using Proxy = typename LHCb::Pr::Upstream::Tracks::template proxy_type< SIMDWrapper::Scalar, LHCb::Pr::ProxyBehaviour::Contiguous, LHCb::Pr::Upstream::Tracks const>; - State( const Proxy& track ) { - const auto pos = track.StatePos(); - const auto dir = track.StateDir(); + using VeloProxy = + typename LHCb::Pr::Velo::Tracks::template proxy_type; + State( const Proxy& track, const VeloProxy& velo ) { + + const auto pos = velo.StatePos( LHCb::Event::Enum::State::Location::EndVelo ); + const auto dir = velo.StateDir( LHCb::Event::Enum::State::Location::EndVelo ); qop = track.qOverP().cast(); - p = std::fabs( 1. / qop ); + p = std::abs( 1.f / qop ); x = pos.x().cast(); y = pos.y().cast(); diff --git a/Phys/FunctorCore/include/Functors/Common.h b/Phys/FunctorCore/include/Functors/Common.h index df0deb6d6d8de338165ce129c4309ddc77984385..2b6aaa0c85c06080e9d3342662cba46d4be365de 100644 --- a/Phys/FunctorCore/include/Functors/Common.h +++ b/Phys/FunctorCore/include/Functors/Common.h @@ -12,6 +12,7 @@ #include "Event/MCParticle.h" #include "Event/MCVertex.h" #include "Functors/Function.h" +#include "Functors/Utilities.h" #include "GaudiAlg/GaudiTupleAlg.h" #include "GaudiKernel/DataObjectHandle.h" #include "GaudiKernel/SerializeSTL.h" @@ -19,6 +20,9 @@ #include "Relations/RelationWeighted1D.h" #include "SelKernel/VertexRelation.h" +#include +#include + namespace Functors::Common { /** @@ -45,6 +49,7 @@ namespace Functors::Common { } } } // namespace details + /** * @brief Functor to forward input * @@ -101,6 +106,25 @@ namespace Functors::Common { } }; + /** + * @brief std::get value by Index + * + * @tparam Index + */ + template + struct Get final : Function { + + template + constexpr auto operator()( std::tuple&& tup ) const { + return std::get( std::forward>( tup ) ); + } + + template + constexpr auto operator()( Args&&... args ) const { + return ( *this )( ForwardArgs{}( args... ) ); + } + }; + /** * @brief Functor to return address of object */ diff --git a/Phys/FunctorCore/include/Functors/Functional.h b/Phys/FunctorCore/include/Functors/Functional.h index aaf5c67cd2d6ed54e30ef6d9a60281bde0ba6081..261380b9474692ae45ef4a61468cf68decdadfaa 100644 --- a/Phys/FunctorCore/include/Functors/Functional.h +++ b/Phys/FunctorCore/include/Functors/Functional.h @@ -162,6 +162,31 @@ namespace Functors::Functional { } }; + /* * + * @brief reduces range to minimum value that is not zero + * */ + struct MinElementNotZero final : public Function { + template + auto operator()( Data&& range ) const { + using data_t = std::remove_reference_t; + using Sel::Utils::select; + using std::abs; + using std::min; + // reduce to smallest value that is not zero + return std::accumulate( std::begin( range ), std::end( range ), std::numeric_limits::max(), + []( auto curr_min_value, auto value ) { + const auto zero = [&] { + if constexpr ( std::numeric_limits::is_exact ) { + return value == 0; + } else { + return abs( value ) <= std::numeric_limits::min(); + } + }(); + return select( !zero, min( curr_min_value, value ), curr_min_value ); + } ); + } + }; + /* * * @brief return max element of range * */ diff --git a/Phys/FunctorCore/include/Functors/JIT_includes.h b/Phys/FunctorCore/include/Functors/JIT_includes.h index 31e3cd239698524715a475522dab5503b5ae4390..7f4067a26e8272eba0675062a9899aaab7fea8ba 100644 --- a/Phys/FunctorCore/include/Functors/JIT_includes.h +++ b/Phys/FunctorCore/include/Functors/JIT_includes.h @@ -53,6 +53,8 @@ #include "Event/MCParticle.h" #include "Event/MCVertex.h" // TrackEvent +#include "Event/PrLongTracks.h" +#include "Event/PrUpstreamTracks.h" #include "Event/Track_v1.h" #include "Event/Track_v2.h" #include "Event/Track_v3.h" @@ -68,5 +70,7 @@ // PrKernel #include "PrKernel/PrSelection.h" // RelTables +#include "CaloFutureUtils/TrackUtils.h" +#include "Event/RelationTable.h" #include "Event/TableView.h" #include "Relations/Relation2D.h" diff --git a/Phys/FunctorCore/python/Functors/__init__.py b/Phys/FunctorCore/python/Functors/__init__.py index 6438f02cdd4e9409b86abd7536295bc41c992a43..2e5314cfba75a31b786dd83fffff2f286e9ef7e6 100644 --- a/Phys/FunctorCore/python/Functors/__init__.py +++ b/Phys/FunctorCore/python/Functors/__init__.py @@ -366,6 +366,22 @@ def CALL(Row: int, Col: int): return _CALL(Args=[Row, Col]) +_GET = Functor( + '_GET', + 'Common::Get', + 'std::get (tuple) and handles unpacked from tuple', + TemplateParams=[('Index', 'Integer index passed as template to std::get', + template_list_arg_formatter)]) + + +def GET(index: int): + """Get an element of statically indexed data. + Args: + index: index of dats + """ + return _GET(Index=[index]) + + TRACK_COVARIANCE = Functor( 'TRACK_COVARIANCE', 'Track::Covariance', @@ -2562,6 +2578,11 @@ BACK = Functor('BACK', "Functional::Back", "Back element of range") MIN_ELEMENT = Functor('MIN_ELEMENT', "Functional::Min", "Miniumum element of range") + +MIN_ELEMENT_NOTZERO = Functor('MIN_ELEMENT_NOTZERO', + "Functional::MinElementNotZero", + "Miniumum element of range that is not zero") + MAX_ELEMENT = Functor('MAX_ELEMENT', "Functional::Max", "Maximum element of range") diff --git a/Phys/FunctorCore/tests/src/TestFunctors.cpp b/Phys/FunctorCore/tests/src/TestFunctors.cpp index 0c7eb665efc3cec8ac20cec638eccb96247b7a57..6899a78f12cdea6a41ed520d7c8a861fc71d0d97 100644 --- a/Phys/FunctorCore/tests/src/TestFunctors.cpp +++ b/Phys/FunctorCore/tests/src/TestFunctors.cpp @@ -24,6 +24,7 @@ #include "Event/PrimaryVertices.h" #include "Event/Proxy.h" #include "Event/RecSummary.h" +#include "Event/RelationTable.h" #include "Event/TrackEnums.h" #include "Event/Track_v3.h" #include "Event/UniqueIDGenerator.h" @@ -40,6 +41,7 @@ #include "Kernel/ParticleID.h" #include "Kernel/Traits.h" #include "LHCbMath/MatVec.h" +#include "LHCbMath/SIMDWrapper.h" #include "PrKernel/PrSelection.h" #include "Relations/Relation1D.h" #include "Relations/RelationWeighted2D.h" @@ -2709,6 +2711,40 @@ BOOST_AUTO_TEST_CASE( test_get_track_functor ) { 1.e-6 * abs( trckv3_func_threemom.Y().cast() ) ); BOOST_CHECK( abs( trckv3_func_threemom.Z().cast() - truev3_threemom.Z().cast() ) < 1.e-6 * abs( trckv3_func_threemom.Z().cast() ) ); + + // the following tests accessing weights (ExtraTags) of RelationTable1D/2D using + // the Weight and Get functors. + auto WEIGHT = Functors::Common::Weight{}; + auto GET_0 = Functors::Common::Get<0>{}; + auto MIN = Functors::Functional::MinElementNotZero{}; + struct Val1 : LHCb::Event::int_field {}; + struct Val2 : LHCb::Event::float_field {}; + const auto reltracks = v3::generate_tracks( 2 * SIMDWrapper::best::types::size, unique_id_gen, 1, zn ); + const auto othertracks = v3::generate_tracks( 2 * SIMDWrapper::best::types::size + 1, unique_id_gen, 1, zn ); + LHCb::Event::RelationTable1D reltable{&reltracks}; + LHCb::Event::RelationTable2D reltable2{&reltracks, &othertracks}; + reltable.reserve( tracks.size() ); + for ( const auto& track : reltracks.scalar() ) { + reltable.add( track, 4 + track.offset(), 2.f ); + reltable2.add( track, othertracks.scalar()[track.offset()], 3.f ); + } + reltable2.add( reltracks.scalar()[0], othertracks.scalar()[reltracks.size()], 3.f ); + + auto view = reltable.buildView(); + auto zip = LHCb::Event::make_zip( *reltable.from(), view ); + for ( const auto& t : zip ) { + auto value = std::invoke( GET_0, std::invoke( WEIGHT, t ) ); + const auto test_mask = ( value == ( 4 + t.indices() ) ) && t.loop_mask(); + BOOST_CHECK_EQUAL( popcount( test_mask ), popcount( t.loop_mask() ) ); + } + + auto view2 = reltable2.buildFromView(); + auto zip2 = LHCb::Event::make_zip( *reltable2.from(), view2 ); + for ( const auto& t : zip2 ) { + auto value = std::invoke( MIN, std::invoke( GET_0, std::invoke( WEIGHT, t ) ) ); + const auto test_mask = ( abs( value - 3.f ) <= std::numeric_limits::min() ) && t.loop_mask(); + BOOST_CHECK_EQUAL( popcount( test_mask ), popcount( t.loop_mask() ) ); + } } BOOST_AUTO_TEST_CASE( test_Value_ValueOrDict ) { diff --git a/Pr/PrAlgorithms/CMakeLists.txt b/Pr/PrAlgorithms/CMakeLists.txt index 4316bf03772b0469d011feae7757b03bc7467b7f..947c0d594456012ed9ae55300b4545e4e2627e02 100644 --- a/Pr/PrAlgorithms/CMakeLists.txt +++ b/Pr/PrAlgorithms/CMakeLists.txt @@ -27,7 +27,6 @@ gaudi_add_module(PrAlgorithms src/PrResidualVeloTracks.cpp src/PrStoreSciFiHits.cpp src/PrStoreUTHit.cpp - src/PrUpstreamFromVelo.cpp src/HitsEmptyProducer.cpp LINK Boost::container diff --git a/Pr/PrAlgorithms/src/PrAddUTHitsTool.cpp b/Pr/PrAlgorithms/src/PrAddUTHitsTool.cpp index 4787de8ec74da4e1febb7f871c764f1aedd93233..81a5fa0205b4957b25bc6784c672aebbfe2c9764 100644 --- a/Pr/PrAlgorithms/src/PrAddUTHitsTool.cpp +++ b/Pr/PrAlgorithms/src/PrAddUTHitsTool.cpp @@ -312,8 +312,8 @@ namespace LHCb::Pr { for ( auto const& track : inputs.simd() ) { //---Define the tolerance parameters const auto qoverp = track.qOverP(); - const auto pos = track.StatePos( 0 ); - const auto dir = track.StateDir( 0 ); + const auto pos = track.StatePos( Event::Enum::State::Location::EndVelo ); + const auto dir = track.StateDir( Event::Enum::State::Location::EndVelo ); auto fState = filteredStates.emplace_back(); fState.field().setPosition( pos.x(), pos.y(), pos.z() ); diff --git a/Pr/PrAlgorithms/src/PrForwardTracking.cpp b/Pr/PrAlgorithms/src/PrForwardTracking.cpp index 3e7e1f727c3a1ae337f7db7a94557b791fd7088d..cf22efe394e92818b3e866947aee3f7c12c54a7d 100644 --- a/Pr/PrAlgorithms/src/PrForwardTracking.cpp +++ b/Pr/PrAlgorithms/src/PrForwardTracking.cpp @@ -1890,22 +1890,26 @@ namespace LHCb::Pr::Forward { direct_debug( "" ); direct_debug( "============================VELO TRACK No.", iTrack, "=================================" ); direct_debug( "" ); - // get position and direction from velo track (state=1 for forward tracks state=0 for backward tracks) + const auto [endv_pos, endv_dir, qOverP] = [&] { if constexpr ( std::is_same_v ) { - const auto endv_pos = tr.StatePos(); - const auto endv_dir = tr.StateDir(); + const auto velozipped = input_tracks.getVeloAncestors()->scalar(); + const auto trackVP = tr.trackVP(); + const auto velo_track = velozipped[trackVP.cast()]; + const auto endv_pos = velo_track.StatePos( Event::Enum::State::Location::EndVelo ); + const auto endv_dir = velo_track.StateDir( Event::Enum::State::Location::EndVelo ); return std::tuple{endv_pos, endv_dir, tr.qOverP().cast()}; } else { - const auto endv_pos = tr.StatePos( 1 ); - const auto endv_dir = tr.StateDir( 1 ); + const auto endv_pos = tr.StatePos( Event::Enum::State::Location::EndVelo ); + const auto endv_dir = tr.StateDir( Event::Enum::State::Location::EndVelo ); return std::tuple{endv_pos, endv_dir, nanMomentum}; } }(); // remove tracks that are so steep in y that they go out of acceptance if ( const auto yStraightEndT = - endv_pos.y() + abs( endv_dir.y() ) * ( static_cast( Z( State::Location::EndT ) ) - endv_pos.z() ); + endv_pos.y() + + abs( endv_dir.y() ) * ( static_cast( Z( State::Location::EndT ).value() ) - endv_pos.z() ); yStraightEndT.cast() > m_maxLinearYEndT ) { direct_debug( "yStraightEndT =", yStraightEndT, "not in acceptance ... skip" ); continue; @@ -2475,29 +2479,33 @@ namespace LHCb::Pr::Forward { } } + static_assert( Event::v3::num_states() == 2 ); + constexpr auto EndVelo = Event::Enum::State::Location::EndVelo; + constexpr auto endT = stateIndex( Event::Enum::State::Location::EndT ); + constexpr auto zEndT = static_cast( Z( Event::Enum::State::Location::EndT ).value() ); + constexpr auto dz = zEndT - zReference; + const auto qOverP = cand.getQoP(); - out.field( 0 ).setQOverP( qOverP ); - out.field( 1 ).setQOverP( qOverP ); - - LHCb::State tState; - const auto dz = static_cast( StateParameters::ZEndT ) - zReference; - tState.setLocation( LHCb::State::Location::EndT ); - tState.setState( cand.x( dz ), cand.y( dz ), static_cast( StateParameters::ZEndT ), cand.xSlope( dz ), - cand.ySlope( dz ), qOverP ); - const auto pos = LHCb::LinAlg::Vec{tState.x(), tState.y(), tState.z()}; - const auto dir = LHCb::LinAlg::Vec{tState.tx(), tState.ty(), 1.f}; - out.field( 1 ).setPosition( pos ); - out.field( 1 ).setDirection( dir ); + const auto pos = LHCb::LinAlg::Vec{cand.x( dz ), cand.y( dz ), zEndT}; + const auto dir = LHCb::LinAlg::Vec{cand.xSlope( dz ), cand.ySlope( dz ), 1.f}; + out.field( endT ).setPosition( pos ); + out.field( endT ).setDirection( dir ); + out.field( endT ).setQOverP( qOverP ); const auto [ancestpos, ancestdir] = [&] { if constexpr ( std::is_same_v ) { - return std::pair{ancestTrack.StatePos(), ancestTrack.StateDir()}; + const auto velozipped = input_tracks.getVeloAncestors()->scalar(); + const auto trackVP = ancestTrack.trackVP(); + const auto velo_scalar = velozipped[trackVP.cast()]; + return std::pair{velo_scalar.StatePos( EndVelo ), velo_scalar.StateDir( EndVelo )}; } else { - return std::pair{ancestTrack.StatePos( 1 ), ancestTrack.StateDir( 1 )}; + return std::pair{ancestTrack.StatePos( EndVelo ), ancestTrack.StateDir( EndVelo )}; } }(); - out.field( 0 ).setPosition( ancestpos ); - out.field( 0 ).setDirection( ancestdir ); + constexpr auto endVeloIndex = stateIndex( EndVelo ); + out.field( endVeloIndex ).setPosition( ancestpos ); + out.field( endVeloIndex ).setDirection( ancestdir ); + out.field( endVeloIndex ).setQOverP( qOverP ); assert( ids.size() <= LHCb::Pr::Long::Tracks::MaxFTHits ); diff --git a/Pr/PrAlgorithms/src/PrHybridSeeding.cpp b/Pr/PrAlgorithms/src/PrHybridSeeding.cpp index d14c038cbbdcfe73b990063cf47b3175fde8c6d5..f4b44ae30765185308f4a1d9ce95390dbc8556f2 100644 --- a/Pr/PrAlgorithms/src/PrHybridSeeding.cpp +++ b/Pr/PrAlgorithms/src/PrHybridSeeding.cpp @@ -24,6 +24,7 @@ #include "Event/PrSeedTracks.h" #include "Event/StateParameters.h" #include "Event/Track.h" +#include "Event/Track_v3.h" #include "FTDAQ/FTInfo.h" #include "FTDet/DeFTDetector.h" #include "GaudiAlg/ISequencerTimerTool.h" @@ -640,9 +641,6 @@ namespace LHCb::Pr { Gaudi::Property> m_MaxChi2Flag{this, "Flag_MaxChi2DoF_11Hits", {0.5, 1.0, 1.0}}; Gaudi::Property> m_MaxX0Flag{this, "Flag_MaxX0_11Hits", {100., 8000., 200.}}; - //== Make LHCb track states tool and parameters - Gaudi::Property> m_zOutputs{ - this, "ZOutputs", {StateParameters::ZBegT, StateParameters::ZMidT, StateParameters::ZEndT}}; PublicToolHandle m_momentumTool{this, "MomentumToolName", "FastMomentumEstimate"}; Gaudi::Property> m_maxNClusters{this, "maxNbestCluster", {2, 4, 4, 3}}; @@ -1447,24 +1445,26 @@ namespace LHCb::Pr { if ( !track.valid() ) continue; auto outTrack = result.emplace_back(); unsigned int iID( 0 ); + auto zFirstMeas = std::numeric_limits::max(); + auto zLastMeas = std::numeric_limits::lowest(); outTrack.field().resize( track.hits().size() ); for ( auto const& hit : track.hits() ) { const auto lhcbid = LHCb::Event::lhcbid_v( sciFiHits.lhcbid( hit.fullDex ).lhcbID() ); outTrack.field()[iID].template field().set( lhcbid ); outTrack.field()[iID].template field().set( hit.fullDex ); + zFirstMeas = std::min( sciFiHits.z( hit.fullDex ), zFirstMeas ); + zLastMeas = std::max( sciFiHits.z( hit.fullDex ), zLastMeas ); iID++; } - State stateZref( Gaudi::TrackVector( track.ax(), track.yRef(), track.xSlope0(), //---LoH: can be simplified - // into - // ax(), ay() - track.ySlope(), 0.f ), - Pr::Hybrid::zReference, State::Location::EndT ); + auto stateZref = State{ + {{track.ax(), track.yRef(), track.xSlope0(), track.ySlope(), std::numeric_limits::signaling_NaN()}, + Pr::Hybrid::zReference}}; double qOverP, sigmaQOverP; const float scaleFactor = magnet.signedRelativeCurrent(); if ( m_momentumTool->calculate( magnet, &stateZref, qOverP, sigmaQOverP, true ).isFailure() ) { - if ( std::fabs( scaleFactor ) < 1.e-4f ) { + if ( std::abs( scaleFactor ) < 1.e-4f ) { qOverP = ( ( track.cx() < 0.f ) ? -1.f : 1.f ) * ( ( scaleFactor < 0.f ) ? -1.f : 1.f ) / Gaudi::Units::GeV; sigmaQOverP = 1.f / Gaudi::Units::MeV; } else { @@ -1472,14 +1472,29 @@ namespace LHCb::Pr { sigmaQOverP = 0.5f * qOverP; } } - unsigned int iState( 0 ); - for ( const float z : m_zOutputs ) { - auto state = outTrack.field( iState ); + + constexpr auto state_locs = + Event::v3::get_state_locations>{}; + for ( const auto loc : state_locs() ) { + // TODO: C++23 or_else + const auto z = [&] { + if ( const auto z = Z( loc ); z.has_value() ) { return static_cast( z.value() ); } + switch ( loc ) { + case Event::Enum::State::Location::FirstMeasurement: + return zFirstMeas; + case Event::Enum::State::Location::LastMeasurement: + return zLastMeas; + default: + throw GaudiException( toString( loc ) + " is currently not created for PrSeedTracks", this->name(), + StatusCode::FAILURE ); + } + }(); + + auto state = outTrack.field( stateIndex( loc ) ); state.setPosition( track.xFromDz( z - Pr::Hybrid::zReference ), track.yFromDz( z - Pr::Hybrid::zReference ), z ); state.setDirection( track.xSlopeFromDz( z - Pr::Hybrid::zReference ), track.ySlope() ); state.setQOverP( static_cast( qOverP ) ); - iState++; } outTrack.field().set( track.chi2PerDoF() ); nTracks++; diff --git a/Pr/PrAlgorithms/src/PrLongLivedTracking.cpp b/Pr/PrAlgorithms/src/PrLongLivedTracking.cpp index e6cd3b918c77c2571bf1d2cce5f31bae57ced000..8b5fefcb56b08de06e4638019f5356dd61eb995a 100644 --- a/Pr/PrAlgorithms/src/PrLongLivedTracking.cpp +++ b/Pr/PrAlgorithms/src/PrLongLivedTracking.cpp @@ -134,10 +134,9 @@ public: // -- Note: You want the state the furthest away from the magnet, as then // the straight-line approximation is the best - const int stateId = 2; - const auto state = _tr.get( stateId ); + const auto state = _tr.StatePosDir( LHCb::Event::Enum::State::Location::EndT ); Gaudi::TrackVector stateVector{state.x().cast(), state.y().cast(), state.tx().cast(), state.ty().cast(), - _tr.qOverP( stateId ).cast()}; + _tr.qOverP().cast()}; PrDownTrack refTrack( stateVector, state.z().cast(), m_zUT, m_zMagnetParams.value(), m_yParams.value(), m_momentumParams.value(), magScaleFactor * ( -1 ) ); diff --git a/Pr/PrAlgorithms/src/PrMatchNN.cpp b/Pr/PrAlgorithms/src/PrMatchNN.cpp index 5f78468b00d66bc04197cf13e334f2ea17609106..606c5127006c7e8d29975e442615e27450b5f359 100644 --- a/Pr/PrAlgorithms/src/PrMatchNN.cpp +++ b/Pr/PrAlgorithms/src/PrMatchNN.cpp @@ -26,6 +26,7 @@ #include "Event/PrVeloTracks.h" #include "Event/SOACollection.h" #include "Event/StateParameters.h" +#include "Event/Track_v3.h" #include "PrKernel/IPrAddUTHitsTool.h" #include "PrKernel/IPrDebugTrackingTool.h" @@ -59,6 +60,9 @@ namespace LHCb::Pr::MatchNN { using SeedTracks = LHCb::Pr::Seeding::Tracks; using VeloTracks = LHCb::Pr::Velo::Tracks; + using VeloTag = LHCb::Pr::Velo::Tag; + using SeedTag = LHCb::Pr::Seeding::Tag; + namespace Tag { struct Index : LHCb::Event::int_field {}; @@ -85,33 +89,36 @@ namespace LHCb::Pr::MatchNN { }; } // namespace - class PrMatchNN - : public LHCb::Algorithm::Transformer> { + template + class PrMatchNN : public Algorithm::Transformer> { + + using base_t = Algorithm::Transformer>; + using KeyValue = typename base_t::KeyValue; public: //============================================================================= // Standard constructor, initializes variables //============================================================================= PrMatchNN( const std::string& name, ISvcLocator* pSvcLocator ) - : Transformer( name, pSvcLocator, - {KeyValue{"VeloInput", "Rec/Track/Velo"}, KeyValue{"SeedInput", "Rec/Track/Seed"}, - KeyValue{"AddUTHitsToolName", "PrAddUTHitsTool"}, - KeyValue{"Magnet", LHCb::Det::Magnet::det_path}}, - KeyValue{"MatchOutput", "Rec/Track/Match"} ) + : base_t( name, pSvcLocator, + {KeyValue{"VeloInput", "Rec/Track/Velo"}, KeyValue{"SeedInput", "Rec/Track/Seed"}, + KeyValue{"AddUTHitsToolName", "PrAddUTHitsTool"}, KeyValue{"Magnet", LHCb::Det::Magnet::det_path}}, + KeyValue{"MatchOutput", "Rec/Track/Match"} ) , m_NN{inputVars} {} StatusCode initialize() override { - return Transformer::initialize().andThen( [this] { + return base_t::initialize().andThen( [this] { if ( m_timerTool.isEnabled() ) m_timerIndex = m_timerTool->addTimer( this->name() ); } ); } // main method - LHCb::Pr::Long::Tracks operator()( const LHCb::Pr::Velo::Tracks&, const LHCb::Pr::Seeding::Tracks&, - const IPrAddUTHitsTool&, const DeMagnet& ) const override; + Long::Tracks operator()( const Velo::Tracks&, const SciFiTracks&, const IPrAddUTHitsTool&, + const DeMagnet& ) const override; private: static constexpr const std::array inputVars = {"chi2", "teta2", "distX", @@ -125,8 +132,8 @@ namespace LHCb::Pr::MatchNN { const VeloSciFiMatch& ) const; // merge velo and seed segment to output track - LHCb::Pr::Long::Tracks makeTracks( const LHCb::Pr::Velo::Tracks& velos, const LHCb::Pr::Seeding::Tracks& seeds, - matchCandidates& matches, const DeMagnet& magnet ) const; + Long::Tracks makeTracks( const Velo::Tracks& velos, const SciFiTracks& seeds, matchCandidates& matches, + const DeMagnet& magnet ) const; Gaudi::Property m_zMatchY{this, "zMatchY", 10000. * Gaudi::Units::mm}; // -- Tolerances @@ -167,27 +174,20 @@ namespace LHCb::Pr::MatchNN { }; // Declaration of the Algorithm Factory - DECLARE_COMPONENT_WITH_ID( PrMatchNN, "PrMatchNN" ) - using VeloTag = LHCb::Pr::Velo::Tag; - using SeedTag = LHCb::Pr::Seeding::Tag; - using TracksTag = LHCb::Pr::Long::Tag; + DECLARE_COMPONENT_WITH_ID( PrMatchNN, "PrMatchNN" ) + DECLARE_COMPONENT_WITH_ID( PrMatchNN, "PrMatchNNv3" ) //============================================================================= // Main execution //============================================================================= - LHCb::Pr::Long::Tracks PrMatchNN::operator()( const LHCb::Pr::Velo::Tracks& velos, - const LHCb::Pr::Seeding::Tracks& seeds, - const IPrAddUTHitsTool& addUTHitsTool, const DeMagnet& magnet ) const { + template + Long::Tracks PrMatchNN::operator()( const Velo::Tracks& velos, const SciFiTracks& seeds, + const IPrAddUTHitsTool& addUTHitsTool, + const DeMagnet& magnet ) const { const auto scopedTimer = m_timerTool.get()->scopedTimer( m_timerIndex, m_timerTool.isEnabled() ); std::array mLPReaderInput = {}; if ( velos.size() == 0 || seeds.size() == 0 ) { - if ( msgLevel( MSG::DEBUG ) ) { - debug() << "Track container '" << inputLocation() << "' has size " << seeds.size() - << endmsg; - debug() << "Track container '" << inputLocation() << "' has size " << velos.size() - << endmsg; - } return {nullptr, nullptr, nullptr, LHCb::Event::Enum::Track::History::PrMatch}; } @@ -202,13 +202,10 @@ namespace LHCb::Pr::MatchNN { auto mlpCounterBuf = m_tracksMLP.buffer(); auto chi2CounterBuf = m_tracksChi2.buffer(); - const int EndVelo = 1; - const int EndT3 = 2; - for ( auto const& velo : velos.scalar() ) { - const auto velo_pos = velo.StatePos( EndVelo ); - const auto velo_dir = velo.StateDir( EndVelo ); + const auto velo_pos = velo.StatePos( Event::Enum::State::Location::EndVelo ); + const auto velo_dir = velo.StateDir( Event::Enum::State::Location::EndVelo ); const float posYApproxV = velo_pos.y().cast() + ( m_zMatchY - velo_pos.z().cast() ) * velo_dir.y().cast(); const auto veloSciFiMatch = VeloSciFiMatch{velo_dir.x(), velo_dir.y(), velo_dir.x() * velo_dir.x(), velo_dir.y() * velo_dir.y()}; @@ -218,7 +215,7 @@ namespace LHCb::Pr::MatchNN { const auto loopMask = s.loop_mask(); const auto seedidx = s.indices(); - const auto seed_state = s.get( EndT3 ); + const auto seed_state = s.StatePosDir( Event::Enum::State::Location::EndT ); const auto seed_pos = LinAlg::Vec{seed_state.x(), seed_state.y(), seed_state.z()}; // to avoid problems in the dSlope calculation later on, set out-of-range x slopes to 0.f const auto seed_dir = @@ -236,7 +233,7 @@ namespace LHCb::Pr::MatchNN { // Following is needed for mva training or data/mc comparison // For mc: option file to run is Moore/Hlt/RecoConf/options/tracking_developments/run_prmatching_debug.py if ( m_matchDebugTool.isEnabled() ) { - const auto state_beam = velo.get( 0 ); + const auto state_beam = velo.template get( 0 ); simd::float_v qOverP, sigmaQOverP; m_fastMomentumTool ->calculate( magnet, seed_state.tx(), state_beam.tx(), state_beam.ty(), qOverP, sigmaQOverP, true ) @@ -277,8 +274,8 @@ namespace LHCb::Pr::MatchNN { } const auto mlpMask = mlp > m_minNN.value(); auto smlp = seedMLP.compress_back( mlpMask && chi2Mask && loopMask ); - smlp.field().set( seedidx ); - smlp.field().set( mlp ); + smlp.template field().set( seedidx ); + smlp.template field().set( mlp ); } // end seed iter @@ -289,12 +286,13 @@ namespace LHCb::Pr::MatchNN { for ( auto const& s : seedMLP.scalar() ) { // keep only the ones that are close enough to best mlp - if ( ( *best_proxy ).get().cast() - s.get().cast() < m_maxdDist.value() ) { + if ( ( *best_proxy ).template get().cast() - s.template get().cast() < + m_maxdDist.value() ) { auto match = matches.emplace_back(); match.field().set( velo.indices() ); - match.field().set( s.get().cast() ); + match.field().set( s.template get().cast() ); - mlpCounterBuf += s.get().cast(); + mlpCounterBuf += s.template get().cast(); } } @@ -320,12 +318,13 @@ namespace LHCb::Pr::MatchNN { * @param vsMatch VeloSciFiMatch object holding parameterisations. * @return simd::mask_v Mask of passing checks. */ - simd::mask_v PrMatchNN::checkChi2Match( const LinAlg::Vec vState_pos, - const LinAlg::Vec vState_dir, - const LinAlg::Vec sState_pos, - const LinAlg::Vec sState_dir, - std::array& mLPReaderInput, - const VeloSciFiMatch& vsMatch ) const { + template + simd::mask_v PrMatchNN::checkChi2Match( const LinAlg::Vec vState_pos, + const LinAlg::Vec vState_dir, + const LinAlg::Vec sState_pos, + const LinAlg::Vec sState_dir, + std::array& mLPReaderInput, + const VeloSciFiMatch& vsMatch ) const { const auto dSlopeAbs = abs( sState_dir.x() - vState_dir.x() ); const auto dSlopeYAbs = abs( sState_dir.y() - vState_dir.y() ); @@ -359,11 +358,18 @@ namespace LHCb::Pr::MatchNN { } //============================================================================= - LHCb::Pr::Long::Tracks PrMatchNN::makeTracks( const LHCb::Pr::Velo::Tracks& velos, - const LHCb::Pr::Seeding::Tracks& seeds, matchCandidates& matches, - const DeMagnet& magnet ) const { + template + Long::Tracks PrMatchNN::makeTracks( const Velo::Tracks& velos, const SciFiTracks& seeds, + matchCandidates& matches, const DeMagnet& magnet ) const { + auto result = [&] { + if constexpr ( std::is_same_v ) { + return Long::Tracks{&velos, nullptr, &seeds, Event::Enum::Track::History::PrMatch}; + } else if constexpr ( std::is_same_v ) { + // the v3 tracks do not work here as ancestors, this can be implemented if needed. + return Long::Tracks{&velos, nullptr, nullptr, Event::Enum::Track::History::PrMatch}; + } + }(); - LHCb::Pr::Long::Tracks result( &velos, nullptr, &seeds, LHCb::Event::Enum::Track::History::PrMatch ); result.reserve( matches.size() ); auto const seediter = seeds.simd(); @@ -378,13 +384,13 @@ namespace LHCb::Pr::MatchNN { auto loopMask = match.loop_mask(); - auto const seed_track = seediter.gather( match.get(), loopMask ); - auto const velo_track = veloiter.gather( match.get(), loopMask ); + auto const seed_track = seediter.gather( match.template get(), loopMask ); + auto const velo_track = veloiter.gather( match.template get(), loopMask ); //== get Velo and T states at the usual pattern reco positions - auto state_endvelo = velo_track.get( 1 ); - auto state_endT = seed_track.get( 2 ); - auto state_beam = velo_track.get( 0 ); + auto state_endvelo = velo_track.template get( 1 ); + auto state_endT = seed_track.StatePosDir( Event::Enum::State::Location::EndT ); + auto state_beam = velo_track.template get( 0 ); //== estimate q/p simd::float_v qOverP, sigmaQOverP; @@ -412,35 +418,51 @@ namespace LHCb::Pr::MatchNN { loopMask = loopMask && ptMask; } - auto const oTrack = result.compress_back( loopMask ); - - oTrack.field().set( match.get() ); - oTrack.field().set( -1 ); - oTrack.field().set( match.get() ); + auto const oTrack = result.template compress_back( loopMask ); + using TracksTag = LHCb::Pr::Long::Tag; + oTrack.template field().set( match.get() ); + oTrack.template field().set( -1 ); + oTrack.template field().set( match.get() ); auto const n_fthits = seed_track.nHits(); auto const n_vphits = velo_track.nHits(); - oTrack.field().resize( n_vphits ); - oTrack.field().resize( 0 ); - oTrack.field().resize( n_fthits ); + oTrack.template field().resize( n_vphits ); + oTrack.template field().resize( 0 ); + oTrack.template field().resize( n_fthits ); for ( auto idx{0}; idx < n_vphits.hmax( loopMask ); ++idx ) { - oTrack.field()[idx].template field().set( velo_track.vp_index( idx ) ); - oTrack.field()[idx].template field().set( velo_track.vp_lhcbID( idx ) ); + oTrack.template field()[idx].template field().set( + velo_track.vp_index( idx ) ); + oTrack.template field()[idx].template field().set( + velo_track.vp_lhcbID( idx ) ); } for ( auto idx{0}; idx < n_fthits.hmax( loopMask ); ++idx ) { - oTrack.field()[idx].template field().set( seed_track.ft_index( idx ) ); - oTrack.field()[idx].template field().set( seed_track.ft_lhcbID( idx ) ); + const auto ft_index = [&] { + if constexpr ( std::is_same_v ) { + return seed_track.ft_index( idx ); + } else if constexpr ( std::is_same_v ) { + // the v3 tracks do not store the index, if this is needed it can be implemented + return -1; + } + }(); + oTrack.template field()[idx].template field().set( ft_index ); + oTrack.template field()[idx].template field().set( + seed_track.ft_lhcbID( idx ) ); } - // store end of VELO state - oTrack.field( 0 ).setPosition( state_endvelo.x(), state_endvelo.y(), state_endvelo.z() ); - oTrack.field( 0 ).setDirection( state_endvelo.tx(), state_endvelo.ty() ); - oTrack.field( 0 ).setQOverP( qOverP ); + static_assert( Event::v3::num_states() == 2 ); + constexpr auto endVelo = stateIndex( Event::Enum::State::Location::EndVelo ); + constexpr auto endT = stateIndex( Event::Enum::State::Location::EndT ); - oTrack.field( 1 ).setPosition( state_endT.x(), state_endT.y(), state_endT.z() ); - oTrack.field( 1 ).setDirection( state_endT.tx(), state_endT.ty() ); - oTrack.field( 1 ).setQOverP( qOverP ); + // store end of VELO state + oTrack.template field( endVelo ).setPosition( state_endvelo.x(), state_endvelo.y(), + state_endvelo.z() ); + oTrack.template field( endVelo ).setDirection( state_endvelo.tx(), state_endvelo.ty() ); + oTrack.template field( endVelo ).setQOverP( qOverP ); + + oTrack.template field( endT ).setPosition( state_endT.x(), state_endT.y(), state_endT.z() ); + oTrack.template field( endT ).setDirection( state_endT.tx(), state_endT.ty() ); + oTrack.template field( endT ).setQOverP( qOverP ); } return result; diff --git a/Pr/PrAlgorithms/src/PrUpstreamFromVelo.cpp b/Pr/PrAlgorithms/src/PrUpstreamFromVelo.cpp deleted file mode 100644 index 13cdbe2b664e219807870912d3fabe240627ed50..0000000000000000000000000000000000000000 --- a/Pr/PrAlgorithms/src/PrUpstreamFromVelo.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/*****************************************************************************\ -* (c) Copyright 2019 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. * -\*****************************************************************************/ -#include "Event/PrUpstreamTracks.h" -#include "Event/PrVeloTracks.h" -#include "GaudiKernel/SystemOfUnits.h" -#include "LHCbAlgs/Transformer.h" - -namespace { - using TracksVP = LHCb::Pr::Velo::Tracks; - using TracksUT = LHCb::Pr::Upstream::Tracks; - using Transformer = LHCb::Algorithm::Transformer; -} // namespace - -using TracksTag = LHCb::Pr::Upstream::Tag; -namespace Pr { - /** @class UpstreamFromVelo PrUpstreamFromVelo.cpp - * - * Converts a container of Velo tracks into a container of Upstream ones - * with some fixed pT value. - */ - struct UpstreamFromVelo final : public Transformer { - UpstreamFromVelo( const std::string& name, ISvcLocator* pSvcLocator ) - : Transformer( name, pSvcLocator, {"Input", ""}, {"Output", ""} ) {} - - TracksUT operator()( TracksVP const& inputTracks ) const override { - using dType = SIMDWrapper::best::types; - using F = dType::float_v; - TracksUT outputTracks{&inputTracks}; - outputTracks.reserve( inputTracks.size() ); - float invAssumedPT{1.f / m_assumedPT}; - for ( auto const& track : inputTracks.simd() ) { - auto mask = track.loop_mask(); - auto cov = track.StateCovX( 1 ); - auto pos = track.StatePos( 1 ); - auto dir = track.StateDir( 1 ); - - // Assign q/p assuming q=+1 and pT is 'AssumedPT' - auto txy2 = dir.x() * dir.x() + dir.y() * dir.y(); - F const qop = invAssumedPT * sqrt( txy2 / ( 1 + txy2 ) ); - - auto oTrack = outputTracks.compress_back( mask ); - oTrack.field().set( track.indices() ); - oTrack.field().resize( 0 ); - oTrack.field().resize( 0 ); - oTrack.field().setQOverP( qop ); - oTrack.field().setPosition( pos ); - oTrack.field().setDirection( dir ); - oTrack.field( LHCb::Pr::Upstream::CovXVector::x_x ).set( cov.x() ); - oTrack.field( LHCb::Pr::Upstream::CovXVector::x_tx ).set( cov.y() ); - oTrack.field( LHCb::Pr::Upstream::CovXVector::tx_tx ).set( cov.z() ); - } - return outputTracks; - } - - Gaudi::Property m_assumedPT{this, "AssumedPT", 4.5 * Gaudi::Units::GeV}; - }; -} // namespace Pr - -DECLARE_COMPONENT_WITH_ID( Pr::UpstreamFromVelo, "PrUpstreamFromVelo" ) diff --git a/Pr/PrConverters/CMakeLists.txt b/Pr/PrConverters/CMakeLists.txt index 2f35743d30c506a1790063632bd4236bf1730b99..8f74bd7e9cfcc1405c6c2d755679cb45c6aa8cbe 100644 --- a/Pr/PrConverters/CMakeLists.txt +++ b/Pr/PrConverters/CMakeLists.txt @@ -19,8 +19,6 @@ gaudi_add_module(PrConverters src/SOATrackConverters.cpp src/TrackCompactVertexToV1Vertex.cpp src/fromLHCbTrackVector.cpp - src/fromPrSeedTrackTrackv2.cpp - src/fromTrackv2PrSeedingTrack.cpp src/fromV1TrackV2Track.cpp src/fromV2TrackV1Track.cpp src/fromV3TrackV1Track.cpp diff --git a/Pr/PrConverters/src/PrConvertersInfo.h b/Pr/PrConverters/src/PrConvertersInfo.h index 3f993df3ad0cd5099a3ddab15a4ec1c30c2d62b7..87cc8836bee0b459c4e894e7456ecb7bdada02de 100644 --- a/Pr/PrConverters/src/PrConvertersInfo.h +++ b/Pr/PrConverters/src/PrConvertersInfo.h @@ -13,46 +13,51 @@ #include "Event/PrUpstreamTracks.h" #include "Event/PrVeloTracks.h" #include "Event/Track_v1.h" +#include "Event/Track_v3.h" namespace LHCb::Pr::ConversionInfo { + template + constexpr auto stateLocations() { + constexpr auto state_locs = Event::v3::get_state_locations>{}; + return state_locs(); + } + struct Downstream { static constexpr LHCb::Event::v1::Track::Types Type = LHCb::Event::v1::Track::Types::Downstream; static constexpr LHCb::Event::v1::Track::History PrHistory = LHCb::Event::v1::Track::History::PrDownstream; using Ancestor1 = LHCb::Pr::Downstream::Tag::trackSeed; - static constexpr std::array, 1> StateLocations = { - std::make_pair( LHCb::State::Location::AtUT, 1 )}; + + static constexpr auto StateLocations = stateLocations(); static constexpr bool AddStatesFromAncestor = false; - static constexpr std::array AncestorLocations = { - "SeedTracksLocation"}; // std::string does not work prior to C++20, as it cannot be constexpr'd + static constexpr std::array AncestorLocations = {"SeedTracksLocation"}; }; struct Upstream { - static constexpr LHCb::Event::v1::Track::Types Type = LHCb::Event::v1::Track::Types::Upstream; - static constexpr LHCb::Event::v1::Track::History PrHistory = LHCb::Event::v1::Track::History::PrVeloUT; - using Ancestor1 = LHCb::Pr::Upstream::Tag::trackVP; - static constexpr std::array, 0> StateLocations = {{}}; // UT does not add - // states in this case + static constexpr LHCb::Event::v1::Track::Types Type = LHCb::Event::v1::Track::Types::Upstream; + static constexpr LHCb::Event::v1::Track::History PrHistory = LHCb::Event::v1::Track::History::PrVeloUT; + using Ancestor1 = LHCb::Pr::Upstream::Tag::trackVP; + static constexpr auto StateLocations = stateLocations(); static constexpr bool AddStatesFromAncestor = false; static constexpr std::array AncestorLocations = {"VeloTracksLocation"}; }; struct Match { - static constexpr LHCb::Event::v1::Track::Types Type = LHCb::Event::v1::Track::Types::Long; - static constexpr LHCb::Event::v1::Track::History PrHistory = LHCb::Event::v1::Track::History::PrMatch; - using Ancestor1 = LHCb::Pr::Long::Tag::trackVP; - using Ancestor2 = LHCb::Pr::Long::Tag::trackSeed; - static constexpr std::array, 0> StateLocations = {{}}; - static constexpr bool AddStatesFromAncestor = true; - static constexpr std::array AncestorLocations = {"VeloTracksLocation", "SeedTracksLocation"}; + static constexpr LHCb::Event::v1::Track::Types Type = LHCb::Event::v1::Track::Types::Long; + static constexpr LHCb::Event::v1::Track::History PrHistory = LHCb::Event::v1::Track::History::PrMatch; + using Ancestor1 = LHCb::Pr::Long::Tag::trackVP; + using Ancestor2 = LHCb::Pr::Long::Tag::trackSeed; + static constexpr auto StateLocations = stateLocations(); + static constexpr bool AddStatesFromAncestor = true; + static constexpr std::array AncestorLocations = {"VeloTracksLocation", "SeedTracksLocation"}; }; struct Forward { static constexpr LHCb::Event::v1::Track::Types Type = LHCb::Event::v1::Track::Types::Long; static constexpr LHCb::Event::v1::Track::History PrHistory = LHCb::Event::v1::Track::History::PrForward; using Ancestor1 = LHCb::Pr::Long::Tag::trackVP; - static constexpr std::array, 1> StateLocations = { - std::make_pair( LHCb::State::Location::EndT, 1 )}; + + static constexpr auto StateLocations = stateLocations(); static constexpr bool AddStatesFromAncestor = false; static constexpr std::array AncestorLocations = {"VeloTracksLocation"}; }; @@ -61,8 +66,8 @@ namespace LHCb::Pr::ConversionInfo { static constexpr LHCb::Event::v1::Track::Types Type = LHCb::Event::v1::Track::Types::Long; static constexpr LHCb::Event::v1::Track::History PrHistory = LHCb::Event::v1::Track::History::PrForward; using Ancestor1 = LHCb::Pr::Long::Tag::trackUT; - static constexpr std::array, 1> StateLocations = { - std::make_pair( LHCb::State::Location::EndT, 1 )}; + + static constexpr auto StateLocations = stateLocations(); static constexpr bool AddStatesFromAncestor = false; static constexpr std::array AncestorLocations = {"UpstreamTracksLocation"}; }; @@ -70,8 +75,8 @@ namespace LHCb::Pr::ConversionInfo { struct VeloForward { static constexpr LHCb::Event::v1::Track::Types Type = LHCb::Event::v1::Track::Types::Velo; static constexpr LHCb::Event::v1::Track::History PrHistory = LHCb::Event::v1::Track::History::PrPixel; - static constexpr std::array, 2> StateLocations = { - std::make_pair( LHCb::State::Location::ClosestToBeam, 0 ), std::make_pair( LHCb::State::Location::EndVelo, 1 )}; + + static constexpr auto StateLocations = stateLocations(); static constexpr bool AddStatesFromAncestor = false; static constexpr std::array AncestorLocations = {}; }; @@ -79,8 +84,8 @@ namespace LHCb::Pr::ConversionInfo { struct VeloBackward { static constexpr LHCb::Event::v1::Track::Types Type = LHCb::Event::v1::Track::Types::VeloBackward; static constexpr LHCb::Event::v1::Track::History PrHistory = LHCb::Event::v1::Track::History::PrPixel; - static constexpr std::array, 1> StateLocations = { - std::make_pair( LHCb::State::Location::ClosestToBeam, 0 )}; + + static constexpr auto StateLocations = stateLocations(); static constexpr bool AddStatesFromAncestor = false; static constexpr std::array AncestorLocations = {{}}; }; @@ -93,8 +98,8 @@ namespace LHCb::Pr::ConversionInfo { return LHCb::Event::v1::Track::Types::Velo; } static constexpr LHCb::Event::v1::Track::History PrHistory = LHCb::Event::v1::Track::History::PrPixel; - static constexpr std::array, 2> StateLocations = { - std::make_pair( LHCb::State::Location::ClosestToBeam, 0 ), std::make_pair( LHCb::State::Location::EndVelo, 1 )}; + + static constexpr auto StateLocations = stateLocations(); static constexpr bool AddStatesFromAncestor = false; static constexpr std::array AncestorLocations = {}; }; @@ -102,9 +107,8 @@ namespace LHCb::Pr::ConversionInfo { struct Seeding { static constexpr LHCb::Event::v1::Track::Types Type = LHCb::Event::v1::Track::Types::Ttrack; static constexpr LHCb::Event::v1::Track::History PrHistory = LHCb::Event::v1::Track::History::PrSeeding; - static constexpr std::array, 3> StateLocations = { - std::make_pair( LHCb::State::Location::FirstMeasurement, 0 ), std::make_pair( LHCb::State::Location::EndT, 1 ), - std::make_pair( LHCb::State::Location::LastMeasurement, 2 )}; + + static constexpr auto StateLocations = stateLocations(); static constexpr bool AddStatesFromAncestor = false; static constexpr std::array AncestorLocations = {{}}; }; diff --git a/Pr/PrConverters/src/SOATrackConverters.cpp b/Pr/PrConverters/src/SOATrackConverters.cpp index f89b2f96fb322a042049a62736ef43622f3e8a4a..476e8404581c25e6e54814c687c38a9e27365515 100644 --- a/Pr/PrConverters/src/SOATrackConverters.cpp +++ b/Pr/PrConverters/src/SOATrackConverters.cpp @@ -21,6 +21,7 @@ #include "GaudiAlg/FunctionalDetails.h" #include "LHCbAlgs/Transformer.h" #include "SelKernel/TrackZips.h" +#include "SelKernel/Utilities.h" #include /** @@ -72,55 +73,57 @@ namespace LHCb::Converters::v2::Event { Output operator()( const TrackContainer& fitted_tracks, const LHCb::UniqueIDGenerator& unique_id_gen ) const override { - using Gaudi::Functional::details::deref; auto zn = Zipping::generateZipIdentifier(); - - // declare track type to be build - auto intracks_type = [&]( auto const& track ) { - if ( !conversion::ref_is_valid( track ) ) throw std::runtime_error( "Null track pointer detected" ); - return m_only_type.value() != LHCb::Event::v3::TrackType::Unknown ? m_only_type.value() : deref( track ).type(); - }; - const auto outputTrackType = - !fitted_tracks.empty() ? intracks_type( *fitted_tracks.begin() ) : LHCb::Event::v3::TrackType::Long; - // declare output -- we do not know the fit history yet, because tracks may be mixed within one shared container - auto output = std::tuple{OutTracks( outputTrackType, Enum::Track::FitHistory::Unknown, - outputTrackType == Enum::Track::Type::VeloBackward, unique_id_gen, zn ), - V3ToV1Mapping( &fitted_tracks )}; - auto& [out, relations] = output; - // check if there are tracks if ( fitted_tracks.empty() ) { ++m_emptyTracks; + // assume that track was fitted + auto output = Output{OutTracks( m_only_type, Enum::Track::FitHistory::PrKalmanFilter, + m_only_type == Enum::Track::Type::VeloBackward, unique_id_gen, zn ), + V3ToV1Mapping( &fitted_tracks )}; return output; } + const auto& firstTrack = Sel::Utils::deref_if_ptr( *fitted_tracks.begin() ); + const auto outputTrackType = + m_only_type != LHCb::Event::v3::TrackType::Unknown ? m_only_type.value() : firstTrack.type(); + // find the first track with selected track type and use its fit history + const auto firstOfType = std::find_if( fitted_tracks.begin(), fitted_tracks.end(), [&]( const auto& track ) { + return Sel::Utils::deref_if_ptr( track ).type() == outputTrackType; + } ); + const auto outputFitHistory = firstOfType != fitted_tracks.end() + ? Sel::Utils::deref_if_ptr( *firstOfType ).fitHistory() + : Enum::Track::FitHistory::PrKalmanFilter; + + auto output = Output{OutTracks( outputTrackType, outputFitHistory, + outputTrackType == Enum::Track::Type::VeloBackward, unique_id_gen, zn ), + V3ToV1Mapping( &fitted_tracks )}; + auto& [out, relations] = output; + out.reserve( fitted_tracks.size() ); relations.reserve( fitted_tracks.size() ); for ( auto const& rtrack : fitted_tracks ) { if ( !conversion::ref_is_valid( rtrack ) ) continue; if ( m_only_type.value() != LHCb::Event::v3::TrackType::Unknown && - m_only_type.value() != deref( rtrack ).type() ) + m_only_type.value() != Sel::Utils::deref_if_ptr( rtrack ).type() ) continue; auto outTrack = out.template emplace_back(); - if ( outTrack.fitHistory() != deref( rtrack ).fitHistory() ) { - // this should be done only once in the beginning when we found the first track of the desired type - // if the FitHistory of rtrack is Unknown in the first place, this scope is never entered - // the assert triggers when there's tracks with known but varying fit history - assert( outTrack.fitHistory() == Enum::Track::FitHistory::Unknown ); - out.setFitHistory( deref( rtrack ).fitHistory() ); + if ( outTrack.fitHistory() != Sel::Utils::deref_if_ptr( rtrack ).fitHistory() ) { + throw GaudiException( "Expected fit history " + toString( outTrack.fitHistory() ) + " but got " + + toString( Sel::Utils::deref_if_ptr( rtrack ).fitHistory() ), + this->name(), StatusCode::FAILURE ); } conversion::Status status, result = conversion::convert_track( out.type(), outTrack, rtrack, unique_id_gen ); do { std::tie( result, status ) = conversion::process_result( result ); - if ( status == conversion::DifferentType ) + if ( status == conversion::DifferentType ) { ++m_different_types; - else if ( status == conversion::InvalidStates ) + } else if ( status == conversion::InvalidStates ) { ++m_invalid_states; - else { - }; + } } while ( status != conversion::Success ); relations.add( outTrack.indices().cast(), get_index_v1( rtrack ) ); diff --git a/Pr/PrConverters/src/fromPrSeedTrackTrackv2.cpp b/Pr/PrConverters/src/fromPrSeedTrackTrackv2.cpp deleted file mode 100644 index f9a5a3ba8713c37c646061e5191bb74bc5ec8c53..0000000000000000000000000000000000000000 --- a/Pr/PrConverters/src/fromPrSeedTrackTrackv2.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/*****************************************************************************\ -* (c) Copyright 2000-2020 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. * -\*****************************************************************************/ -#include "Event/PrSeedTracks.h" -#include "Event/StateParameters.h" -#include "Event/Track.h" -#include "GaudiKernel/StdArrayAsProperty.h" -#include "LHCbAlgs/ScalarTransformer.h" -#include "LHCbAlgs/Transformer.h" -#include "LHCbMath/MatVec.h" -#include "LHCbMath/bit_cast.h" -#include - -/** - * Converter between LHCb::Pr::Seeding::Tracks ( SoA PoD ) and vector - * @author Louis Henry - */ -namespace LHCb::Converters::Track::v2 { - using SeedTag = Pr::Seeding::Tag; - - class fromPrSeedTrackTrackv2 - : public Algorithm::Transformer( Pr::Seeding::Tracks const& )> { - - public: - using KeyValue = Transformer::KeyValue; - - fromPrSeedTrackTrackv2( const std::string& name, ISvcLocator* pSvcLocator ) - : Transformer( name, pSvcLocator, {KeyValue{"InputTracks", ""}}, KeyValue{"OutputTracks", ""} ) {} - - std::vector operator()( Pr::Seeding::Tracks const& inputTracks ) const override { - - std::vector outputTracks; - outputTracks.reserve( inputTracks.size() ); - for ( auto inputTrack : inputTracks.scalar() ) { - auto& outTrack = outputTracks.emplace_back(); - outTrack.setType( Event::v2::Track::Type::Ttrack ); - outTrack.setHistory( Event::v2::Track::History::PrSeeding ); - outTrack.setPatRecStatus( Event::v2::Track::PatRecStatus::PatRecIDs ); - - auto nHits = ( inputTrack.field() ).size().cast(); - auto chi2PerDoF = ( inputTrack.get() ).cast(); - auto getP = outTrack.setChi2PerDoF( {chi2PerDoF, static_cast( nHits ) - 5} ); - for ( int iID = 0; iID < nHits; iID++ ) outTrack.addToLhcbIDs( inputTrack.ft_lhcbID( iID ).LHCbID() ); - // Copying the states - for ( int iState = 0; iState < 3; iState++ ) { - auto state = inputTrack.getLHCbState( iState ); - Gaudi::TrackSymMatrix& cov = state.covariance(); - cov( 0, 0 ) = m_stateErrorX2; - cov( 1, 1 ) = m_stateErrorY2; - cov( 2, 2 ) = m_stateErrorTX2; - cov( 3, 3 ) = m_stateErrorTY2; - cov( 4, 4 ) = m_stateErrorP; - outTrack.addToStates( state ); - } - } - m_nbTracksCounter += outputTracks.size(); - return outputTracks; - } - - private: - // - StateErrorX2: Error^2 on x-position (for making Track) - Gaudi::Property m_stateErrorX2{this, "StateErrorX2", 4.0}; - // - StateErrorY2: Error^2 on y-position (for making Track) - Gaudi::Property m_stateErrorY2{this, "StateErrorY2", 400.}; - // - StateErrorTX2: Error^2 on tx-slope (for making Track) - Gaudi::Property m_stateErrorTX2{this, "StateErrorTX2", 6.e-5}; - // - StateErrorTY2: Error^2 on ty-slope (for making Track) - Gaudi::Property m_stateErrorTY2{this, "StateErrorTY2", 1.e-4}; - // - StateErrorP: Error^2 on momentum (for making Track) - Gaudi::Property m_stateErrorP{this, "StateErrorP", 0.15}; - - mutable Gaudi::Accumulators::SummingCounter<> m_nbTracksCounter{this, "Nb of converted Tracks"}; - }; // namespace - - DECLARE_COMPONENT( fromPrSeedTrackTrackv2 ) - -} // namespace LHCb::Converters::Track::v2 diff --git a/Pr/PrConverters/src/fromPrTracksV1Track.cpp b/Pr/PrConverters/src/fromPrTracksV1Track.cpp index 382c1d384214e6a79f31046803bbcd281863cea6..16d6f634b593284f852681b0dd429b4bb8f192d9 100644 --- a/Pr/PrConverters/src/fromPrTracksV1Track.cpp +++ b/Pr/PrConverters/src/fromPrTracksV1Track.cpp @@ -127,7 +127,6 @@ namespace { void calculateQOverPForVelo( const PrTrackProxy& inTrack, LHCb::Event::v1::Track* outTr, const float pTVelo ) { const int firstRow = outTr->lhcbIDs()[0].channelID(); const int charge = ( firstRow % 2 == 0 ? -1 : 1 ); - int index = 0; for ( auto& aState : outTr->states() ) { // -- Calculate the momentum per state const float tx1 = aState->tx(); @@ -137,8 +136,8 @@ namespace { aState->setQOverP( qop ); aState->setErrQOverP2( 1e-6 ); // -- fille the covariance - auto covX = inTrack.StateCovX( index ); - auto covY = inTrack.StateCovY( index ); + auto covX = inTrack.StateCovX( aState->location() ); + auto covY = inTrack.StateCovY( aState->location() ); Gaudi::TrackSymMatrix c; c( 0, 0 ) = covX.x().cast(); c( 2, 0 ) = covX.y().cast(); @@ -148,7 +147,6 @@ namespace { c( 3, 3 ) = covY.z().cast(); c( 4, 4 ) = 1.f; aState->setCovariance( c ); - index++; } } @@ -197,11 +195,8 @@ namespace { void ConvertTrack( LHCb::Event::v1::Track* outTr, const PrTrackProxy& inTrack, const StateErrors& errors, const float veloPT, const ITrackAddClusters* clusterAdder ) { - using Tag = LHCb::Pr::tag_type_t; - constexpr auto stateLocations = ConversionInfo::StateLocations; constexpr bool isVeloTrack = std::is_same_v; - constexpr bool isForwardTrack = ( ConversionInfo::PrHistory == LHCb::Event::v1::Track::History::PrForward ); float QOverP = 1.0f; float errQOverP = 1e-6f; @@ -231,217 +226,193 @@ namespace { outTr->setGhostProbability( 999.9f ); outTr->setPatRecStatus( LHCb::Event::v1::Track::PatRecStatus::PatRecIDs ); - if constexpr ( stateLocations.size() > 0 ) { - - for ( std::size_t i = 0; i < stateLocations.size(); ++i ) { - LHCb::State state; - if constexpr ( stateLocations.size() == 1 && !isVeloTrack && !isForwardTrack ) { - auto s = inTrack.template get(); - state.setState( s.x().cast(), s.y().cast(), s.z().cast(), s.tx().cast(), s.ty().cast(), QOverP ); - } else { - auto s = inTrack.template get( stateLocations[i].second ); - state.setState( s.x().cast(), s.y().cast(), s.z().cast(), s.tx().cast(), s.ty().cast(), QOverP ); - } - state.setLocation( stateLocations[i].first ); - - Gaudi::TrackSymMatrix cov; - cov( 0, 0 ) = errors.stateErrorX2; - cov( 1, 1 ) = errors.stateErrorY2; - cov( 2, 2 ) = errors.stateErrorTX2; - cov( 3, 3 ) = errors.stateErrorTY2; - cov( 4, 4 ) = errQOverP * errQOverP; - - state.setCovariance( cov ); - outTr->addToStates( state ); - } - // -- Velo tracks get an artifical momentum assigned, based on a constant pT - if constexpr ( std::is_same_v ) - calculateQOverPForVelo( inTrack, outTr, veloPT ); + for ( const auto loc : stateLocations ) { + auto s = inTrack.StatePosDir( loc ); + Gaudi::TrackSymMatrix cov; + cov( 0, 0 ) = errors.stateErrorX2; + cov( 1, 1 ) = errors.stateErrorY2; + cov( 2, 2 ) = errors.stateErrorTX2; + cov( 3, 3 ) = errors.stateErrorTY2; + cov( 4, 4 ) = errQOverP * errQOverP; + + outTr->addToStates( + LHCb::State{{s.x().cast(), s.y().cast(), s.tx().cast(), s.ty().cast(), QOverP}, cov, s.z().cast(), loc} ); + } + // -- Velo tracks get an artifical momentum assigned, based on a constant pT + if constexpr ( std::is_same_v && stateLocations.size() > 0 ) { + calculateQOverPForVelo( inTrack, outTr, veloPT ); } } } // namespace -namespace LHCb { - namespace Converters { - namespace Track { - namespace v1 { - - template - struct fromPrTracksV1Track - : public Algorithm::Transformer { - - using base_class_t = - Algorithm::Transformer; - using V1Tracks = LHCb::Event::v1::Tracks; - - fromPrTracksV1Track( std::string const& name, ISvcLocator* pSvcLocator ) - : base_class_t( name, pSvcLocator, IOHelper::InputLocations(), - IOHelper::OutputLocation() ) {} - /** - * @brief The main function - * @param inTracks The set of input tracks - * @param anecestorTracks The sets of tracks that serve as ancestors for inTracks - * @return Keyed container with v1::Tracks - */ - LHCb::Event::v1::Tracks operator()( const PrTracksType& inTracks, - const VOneTracks&... ancestorTracks ) const override { - - auto outTracks = LHCb::Event::v1::Tracks{}; - outTracks.reserve( inTracks.size() ); - m_nbTracksCounter += inTracks.size(); - - // -- It's not strictly speaking wrong, but it will add an additional uninitialized state, so let's issue a - // warning. - if constexpr ( std::is_same_v ) { - if ( inTracks.backward() ) ++m_nbWrongVeloBackwardsConversion; - } - - StateErrors errors{m_stateErrorX2, m_stateErrorY2, m_stateErrorTX2, m_stateErrorTY2, m_stateErrorP}; - - for ( auto const& inTrack : inTracks.scalar() ) { - - using TrackType = decltype( *std::declval().scalar().begin() ); - auto outTrack = createFromAncestor( inTrack, ancestorTracks... ); - // --- - ConvertTrack( outTrack, inTrack, errors, m_veloPT, - m_clusterAdder.get() ); - if constexpr ( std::is_same_v ) - outTrack->setType( ConversionInfo::Type( inTrack.backward() ) ); - else - outTrack->setType( ConversionInfo::Type ); - outTrack->setHistory( ConversionInfo::PrHistory ); - outTracks.insert( outTrack ); - } - return outTracks; - } - - private: - ToolHandle m_clusterAdder{this, "TrackAddClusterTool", "AddClustersToTrackTool"}; - - // - StateErrorX2: Error^2 on x-position (for making Track) - Gaudi::Property m_stateErrorX2{this, "StateErrorX2", 4.0}; - // - StateErrorY2: Error^2 on y-position (for making Track) - Gaudi::Property m_stateErrorY2{this, "StateErrorY2", 400.}; - // - StateErrorTX2: Error^2 on tx-slope (for making Track) - Gaudi::Property m_stateErrorTX2{this, "StateErrorTX2", 6.e-5}; - // - StateErrorTY2: Error^2 on ty-slope (for making Track) - Gaudi::Property m_stateErrorTY2{this, "StateErrorTY2", 1.e-4}; - // - StateErrorP: Error^2 on momentum (for making Track) - Gaudi::Property m_stateErrorP{this, "StateErrorP", 0.15}; - // - VeloPT: Default PT for VeloTracks - Gaudi::Property m_veloPT{this, "VeloPT", 400 * Gaudi::Units::MeV}; - // - A counter for the tracks - mutable Gaudi::Accumulators::SummingCounter<> m_nbTracksCounter{this, "Nb of converted Tracks"}; - mutable Gaudi::Accumulators::MsgCounter m_nbWrongVeloBackwardsConversion{ - this, "Using Velo forward tracks conversion options on Velo backward tracks. Use at your own risk."}; - }; - using PrDownstreamConverter = - fromPrTracksV1Track; - DECLARE_COMPONENT_WITH_ID( PrDownstreamConverter, "fromPrDownstreamTracksV1Tracks" ) - using PrMatchConverter = fromPrTracksV1Track; - DECLARE_COMPONENT_WITH_ID( PrMatchConverter, "fromPrMatchTracksV1Tracks" ) - using PrUpstreamConverter = fromPrTracksV1Track; - DECLARE_COMPONENT_WITH_ID( PrUpstreamConverter, "fromPrUpstreamTracksV1Tracks" ) - using PrForwardConverter = - fromPrTracksV1Track; - DECLARE_COMPONENT_WITH_ID( PrForwardConverter, "fromPrForwardTracksV1Tracks" ) - using PrForwardFromVeloUTConverter = - fromPrTracksV1Track; - DECLARE_COMPONENT_WITH_ID( PrForwardFromVeloUTConverter, "fromPrForwardTracksFromVeloUTV1Tracks" ) - using PrSeedingConverter = fromPrTracksV1Track; - DECLARE_COMPONENT_WITH_ID( PrSeedingConverter, "fromPrSeedingTracksV1Tracks" ) - using PrVeloConverter = fromPrTracksV1Track; - DECLARE_COMPONENT_WITH_ID( PrVeloConverter, "fromPrVeloTracksV1Tracks" ) - using PrVeloBackwardConverter = - fromPrTracksV1Track; - DECLARE_COMPONENT_WITH_ID( PrVeloBackwardConverter, "fromPrVeloBackwardTracksV1Tracks" ) - - // -- This is the version when you need to merge two input containers with PrTracks into one output container - // -- Mostly for Velo forward tracks + Velo backward tracks. - template - struct fromPrTracksV1TrackMerger : public Algorithm::Transformer { - - using base_class_t = Algorithm::Transformer; - using V1Tracks = LHCb::Event::v1::Tracks; - - fromPrTracksV1TrackMerger( std::string const& name, ISvcLocator* pSvcLocator ) - : base_class_t( name, pSvcLocator, IOHelperMerger::InputLocations(), - IOHelperMerger::OutputLocation() ) {} - - /** - * @brief The main function - * @param inTracks1 First set of input tracks - * @param inTracks2 Second set of input tracks - * @param anecestorTracks The sets of tracks that serve as ancestors for inTracks1 and inTracks2 - * @return Keyed container with v1::Tracks - */ - LHCb::Event::v1::Tracks operator()( const PrTracksType& inTracks1, const PrTracksType& inTracks2, - const VOneTracks&... ancestorTracks ) const override { - - auto outTracks = LHCb::Event::v1::Tracks{}; - outTracks.reserve( inTracks1.size() + inTracks2.size() ); - m_nbTracksCounter += inTracks1.size() + inTracks2.size(); - - StateErrors errors{m_stateErrorX2, m_stateErrorY2, m_stateErrorTX2, m_stateErrorTY2, m_stateErrorP}; - - for ( auto const& inTrack : inTracks1.scalar() ) { - - using TrackType = decltype( *std::declval().scalar().begin() ); - auto outTrack = createFromAncestor( inTrack, ancestorTracks... ); - // --- - ConvertTrack( outTrack, inTrack, errors, m_veloPT, - m_clusterAdder.get() ); - outTrack->setType( ConversionInfo1::Type ); - outTrack->setHistory( ConversionInfo1::PrHistory ); - outTracks.insert( outTrack ); - } - - for ( auto const& inTrack : inTracks2.scalar() ) { - - using TrackType = decltype( *std::declval().scalar().begin() ); - auto outTrack = createFromAncestor( inTrack, ancestorTracks... ); - // --- - ConvertTrack( outTrack, inTrack, errors, m_veloPT, - m_clusterAdder.get() ); - outTrack->setType( ConversionInfo2::Type ); - outTrack->setHistory( ConversionInfo2::PrHistory ); - outTracks.insert( outTrack ); - } - - return outTracks; - } - - private: - ToolHandle m_clusterAdder{this, "TrackAddClusterTool", "AddClustersToTrackTool"}; - - // - StateErrorX2: Error^2 on x-position (for making Track) - Gaudi::Property m_stateErrorX2{this, "StateErrorX2", 4.0}; - // - StateErrorY2: Error^2 on y-position (for making Track) - Gaudi::Property m_stateErrorY2{this, "StateErrorY2", 400.}; - // - StateErrorTX2: Error^2 on tx-slope (for making Track) - Gaudi::Property m_stateErrorTX2{this, "StateErrorTX2", 6.e-5}; - // - StateErrorTY2: Error^2 on ty-slope (for making Track) - Gaudi::Property m_stateErrorTY2{this, "StateErrorTY2", 1.e-4}; - // - StateErrorP: Error^2 on momentum (for making Track) - Gaudi::Property m_stateErrorP{this, "StateErrorP", 0.15}; - // - VeloPT: Default PT for VeloTracks - Gaudi::Property m_veloPT{this, "VeloPT", 400 * Gaudi::Units::MeV}; - // - A counter for the tracks - mutable Gaudi::Accumulators::SummingCounter<> m_nbTracksCounter{this, "Nb of converted Tracks"}; - }; - - using PrVeloMergerConverter = - fromPrTracksV1TrackMerger; - DECLARE_COMPONENT_WITH_ID( PrVeloMergerConverter, "fromPrVeloTracksV1TracksMerger" ) - - } // namespace v1 - } // namespace Track - } // namespace Converters -} // namespace LHCb +namespace LHCb::Converters::Track::v1 { + + template + struct fromPrTracksV1Track + : public Algorithm::Transformer { + + using base_class_t = Algorithm::Transformer; + using V1Tracks = LHCb::Event::v1::Tracks; + + fromPrTracksV1Track( std::string const& name, ISvcLocator* pSvcLocator ) + : base_class_t( name, pSvcLocator, IOHelper::InputLocations(), + IOHelper::OutputLocation() ) {} + /** + * @brief The main function + * @param inTracks The set of input tracks + * @param anecestorTracks The sets of tracks that serve as ancestors for inTracks + * @return Keyed container with v1::Tracks + */ + LHCb::Event::v1::Tracks operator()( const PrTracksType& inTracks, + const VOneTracks&... ancestorTracks ) const override { + + auto outTracks = LHCb::Event::v1::Tracks{}; + outTracks.reserve( inTracks.size() ); + m_nbTracksCounter += inTracks.size(); + + // -- It's not strictly speaking wrong, but it will add an additional uninitialized state, so let's issue a + // warning. + if constexpr ( std::is_same_v ) { + if ( inTracks.backward() ) ++m_nbWrongVeloBackwardsConversion; + } + + StateErrors errors{m_stateErrorX2, m_stateErrorY2, m_stateErrorTX2, m_stateErrorTY2, m_stateErrorP}; + + for ( auto const& inTrack : inTracks.scalar() ) { + + using TrackType = decltype( *std::declval().scalar().begin() ); + auto outTrack = createFromAncestor( inTrack, ancestorTracks... ); + // --- + ConvertTrack( outTrack, inTrack, errors, m_veloPT, + m_clusterAdder.get() ); + if constexpr ( std::is_same_v ) + outTrack->setType( ConversionInfo::Type( inTrack.backward() ) ); + else + outTrack->setType( ConversionInfo::Type ); + outTrack->setHistory( ConversionInfo::PrHistory ); + outTracks.insert( outTrack ); + } + return outTracks; + } + + private: + ToolHandle m_clusterAdder{this, "TrackAddClusterTool", "AddClustersToTrackTool"}; + // - StateErrorX2: Error^2 on x-position (for making Track) + Gaudi::Property m_stateErrorX2{this, "StateErrorX2", 4.0}; + // - StateErrorY2: Error^2 on y-position (for making Track) + Gaudi::Property m_stateErrorY2{this, "StateErrorY2", 400.}; + // - StateErrorTX2: Error^2 on tx-slope (for making Track) + Gaudi::Property m_stateErrorTX2{this, "StateErrorTX2", 6.e-5}; + // - StateErrorTY2: Error^2 on ty-slope (for making Track) + Gaudi::Property m_stateErrorTY2{this, "StateErrorTY2", 1.e-4}; + // - StateErrorP: Error^2 on momentum (for making Track) + Gaudi::Property m_stateErrorP{this, "StateErrorP", 0.15}; + // - VeloPT: Default PT for VeloTracks + Gaudi::Property m_veloPT{this, "VeloPT", 400 * Gaudi::Units::MeV}; + // - A counter for the tracks + mutable Gaudi::Accumulators::SummingCounter<> m_nbTracksCounter{this, "Nb of converted Tracks"}; + mutable Gaudi::Accumulators::MsgCounter m_nbWrongVeloBackwardsConversion{ + this, "Using Velo forward tracks conversion options on Velo backward tracks. Use at your own risk."}; + }; + using PrDownstreamConverter = + fromPrTracksV1Track; + DECLARE_COMPONENT_WITH_ID( PrDownstreamConverter, "fromPrDownstreamTracksV1Tracks" ) + using PrMatchConverter = fromPrTracksV1Track; + DECLARE_COMPONENT_WITH_ID( PrMatchConverter, "fromPrMatchTracksV1Tracks" ) + using PrUpstreamConverter = + fromPrTracksV1Track; + DECLARE_COMPONENT_WITH_ID( PrUpstreamConverter, "fromPrUpstreamTracksV1Tracks" ) + using PrForwardConverter = + fromPrTracksV1Track; + DECLARE_COMPONENT_WITH_ID( PrForwardConverter, "fromPrForwardTracksV1Tracks" ) + using PrForwardFromVeloUTConverter = + fromPrTracksV1Track; + DECLARE_COMPONENT_WITH_ID( PrForwardFromVeloUTConverter, "fromPrForwardTracksFromVeloUTV1Tracks" ) + using PrSeedingConverter = fromPrTracksV1Track; + DECLARE_COMPONENT_WITH_ID( PrSeedingConverter, "fromPrSeedingTracksV1Tracks" ) + using PrVeloConverter = fromPrTracksV1Track; + DECLARE_COMPONENT_WITH_ID( PrVeloConverter, "fromPrVeloTracksV1Tracks" ) + using PrVeloBackwardConverter = fromPrTracksV1Track; + DECLARE_COMPONENT_WITH_ID( PrVeloBackwardConverter, "fromPrVeloBackwardTracksV1Tracks" ) + + // -- This is the version when you need to merge two input containers with PrTracks into one output container + // -- Mostly for Velo forward tracks + Velo backward tracks. + template + struct fromPrTracksV1TrackMerger : public Algorithm::Transformer { + + using base_class_t = Algorithm::Transformer; + using V1Tracks = LHCb::Event::v1::Tracks; + + fromPrTracksV1TrackMerger( std::string const& name, ISvcLocator* pSvcLocator ) + : base_class_t( name, pSvcLocator, IOHelperMerger::InputLocations(), + IOHelperMerger::OutputLocation() ) {} + + /** + * @brief The main function + * @param inTracks1 First set of input tracks + * @param inTracks2 Second set of input tracks + * @param anecestorTracks The sets of tracks that serve as ancestors for inTracks1 and inTracks2 + * @return Keyed container with v1::Tracks + */ + LHCb::Event::v1::Tracks operator()( const PrTracksType& inTracks1, const PrTracksType& inTracks2, + const VOneTracks&... ancestorTracks ) const override { + + auto outTracks = LHCb::Event::v1::Tracks{}; + outTracks.reserve( inTracks1.size() + inTracks2.size() ); + m_nbTracksCounter += inTracks1.size() + inTracks2.size(); + + StateErrors errors{m_stateErrorX2, m_stateErrorY2, m_stateErrorTX2, m_stateErrorTY2, m_stateErrorP}; + + for ( auto const& inTrack : inTracks1.scalar() ) { + + using TrackType = decltype( *std::declval().scalar().begin() ); + auto outTrack = createFromAncestor( inTrack, ancestorTracks... ); + // --- + ConvertTrack( outTrack, inTrack, errors, m_veloPT, + m_clusterAdder.get() ); + outTrack->setType( ConversionInfo1::Type ); + outTrack->setHistory( ConversionInfo1::PrHistory ); + outTracks.insert( outTrack ); + } + + for ( auto const& inTrack : inTracks2.scalar() ) { + + using TrackType = decltype( *std::declval().scalar().begin() ); + auto outTrack = createFromAncestor( inTrack, ancestorTracks... ); + // --- + ConvertTrack( outTrack, inTrack, errors, m_veloPT, + m_clusterAdder.get() ); + outTrack->setType( ConversionInfo2::Type ); + outTrack->setHistory( ConversionInfo2::PrHistory ); + outTracks.insert( outTrack ); + } + + return outTracks; + } + + private: + ToolHandle m_clusterAdder{this, "TrackAddClusterTool", "AddClustersToTrackTool"}; + // - StateErrorX2: Error^2 on x-position (for making Track) + Gaudi::Property m_stateErrorX2{this, "StateErrorX2", 4.0}; + // - StateErrorY2: Error^2 on y-position (for making Track) + Gaudi::Property m_stateErrorY2{this, "StateErrorY2", 400.}; + // - StateErrorTX2: Error^2 on tx-slope (for making Track) + Gaudi::Property m_stateErrorTX2{this, "StateErrorTX2", 6.e-5}; + // - StateErrorTY2: Error^2 on ty-slope (for making Track) + Gaudi::Property m_stateErrorTY2{this, "StateErrorTY2", 1.e-4}; + // - StateErrorP: Error^2 on momentum (for making Track) + Gaudi::Property m_stateErrorP{this, "StateErrorP", 0.15}; + // - VeloPT: Default PT for VeloTracks + Gaudi::Property m_veloPT{this, "VeloPT", 400 * Gaudi::Units::MeV}; + // - A counter for the tracks + mutable Gaudi::Accumulators::SummingCounter<> m_nbTracksCounter{this, "Nb of converted Tracks"}; + }; + + using PrVeloMergerConverter = fromPrTracksV1TrackMerger; + DECLARE_COMPONENT_WITH_ID( PrVeloMergerConverter, "fromPrVeloTracksV1TracksMerger" ) + +} // namespace LHCb::Converters::Track::v1 diff --git a/Pr/PrConverters/src/fromTrackv2PrSeedingTrack.cpp b/Pr/PrConverters/src/fromTrackv2PrSeedingTrack.cpp deleted file mode 100644 index 39cd705c634669466b9155f8687413496f1e439a..0000000000000000000000000000000000000000 --- a/Pr/PrConverters/src/fromTrackv2PrSeedingTrack.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/*****************************************************************************\ -* (c) Copyright 2000-2020 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. * -\*****************************************************************************/ -#include "Event/PrHits.h" -#include "Event/PrSeedTracks.h" -#include "Event/StateParameters.h" -#include "Event/Track.h" -#include "Event/ZipUtils.h" -#include "FTDAQ/FTInfo.h" -#include "GaudiKernel/StdArrayAsProperty.h" -#include "LHCbAlgs/ScalarTransformer.h" -#include "LHCbAlgs/Transformer.h" -#include "LHCbMath/MatVec.h" -#include "LHCbMath/bit_cast.h" -#include - -/** - * Converter between LHCb::Pr::Seeding::Tracks ( SoA PoD ) and vector - * @author Sascha Stahl - */ -namespace LHCb::Converters::Track::PrSeeding { - using Tag = LHCb::Pr::Seeding::Tag; - using LHCb::Pr::FT::Hits; - class fromTrackv2PrSeedingTracks - : public Algorithm::Transformer&, const Hits& )> { - - public: - fromTrackv2PrSeedingTracks( const std::string& name, ISvcLocator* pSvcLocator ) - : Transformer( name, pSvcLocator, - {KeyValue{"InputTracks", ""}, KeyValue{"InputSciFiHits", PrFTInfo::SciFiHitsLocation}}, - KeyValue{"OutputTracks", ""} ) {} - - LHCb::Pr::Seeding::Tracks operator()( const EventContext& evtCtx, const std::vector& inputTracks, - const Hits& fthits ) const override { - - LHCb::Pr::Seeding::Tracks outputTracks{Zipping::generateZipIdentifier(), LHCb::getMemResource( evtCtx )}; - outputTracks.reserve( inputTracks.size() ); - - for ( unsigned int t = 0; t < inputTracks.size(); t++ ) { - const auto& inTrack = inputTracks[t]; - auto outTrack = outputTracks.emplace_back(); - - const auto qop = inTrack.firstState().qOverP(); - - outTrack.field().set( static_cast( inTrack.chi2PerDoF() ) ); - - // -- copy LHCbIDs - outTrack.field().resize( inTrack.lhcbIDs().size() ); - int i = 0; - for ( auto id : inTrack.lhcbIDs() ) { - if ( i == LHCb::Pr::Seeding::Tracks::MaxFTHits ) { - ++m_exceed_max_hits; - break; - } - const auto lhcbid = LHCb::Event::lhcbid_v( id ); - outTrack.field()[i].template field().set( lhcbid ); - for ( unsigned int ihit = 0; ihit != fthits.size(); ihit++ ) { - if ( id == fthits.lhcbid( ihit ) ) { - outTrack.field()[i].template field().set( bit_cast( ihit ) ); - break; - } - } - ++i; - } - - // -- copy states - int istate = 0; - for ( const auto& state : inTrack.states() ) { - if ( istate == LHCb::Pr::Seeding::Tracks::NumSeedStates ) { - Transformer::error() << "Reached maximum number of states in LHCb::Pr::Seeding::Tracks " - << LHCb::Pr::Seeding::Tracks::NumSeedStates << "No more states will be added" - << endmsg; - break; - } - auto outState = outTrack.field( istate ); - outState.setPosition( state.x(), state.y(), state.z() ); - outState.setDirection( state.tx(), state.ty() ); - outState.setQOverP( qop ); - ++istate; - } - if ( istate < static_cast( LHCb::Pr::Seeding::Tracks::NumSeedStates ) ) { - Transformer::error() << "Missing states in LHCb::Pr::Seeding::Tracks got only" << istate << endmsg; - } - } - m_nbTracksCounter += outputTracks.size(); - return outputTracks; - } - - private: - mutable Gaudi::Accumulators::SummingCounter<> m_nbTracksCounter{this, "Nb of converted Tracks"}; - mutable Gaudi::Accumulators::MsgCounter m_exceed_max_hits{ - this, "Reached maximum number of hits in LHCb::Pr::Seeding::Tracks 12. No more hits will be added"}; - }; // namespace - - DECLARE_COMPONENT( fromTrackv2PrSeedingTracks ) - -} // namespace LHCb::Converters::Track::PrSeeding diff --git a/Pr/PrConverters/src/fromV3TrackV1Track.cpp b/Pr/PrConverters/src/fromV3TrackV1Track.cpp index 680492fdfb0fb081291f1945f388fe77c88b395c..28eb88018ec777ee16c8f5f901905bb18f3cac5a 100644 --- a/Pr/PrConverters/src/fromV3TrackV1Track.cpp +++ b/Pr/PrConverters/src/fromV3TrackV1Track.cpp @@ -126,9 +126,13 @@ namespace { case LHCb::Event::v3::TrackType::Long: switch ( inTrack.fitHistory() ) { case LHCb::Event::Enum::Track::FitHistory::Unknown: + return update_states_impl( new_track, inTrack, LHCb::Event::v3::available_states_t{} ); case LHCb::Event::Enum::Track::FitHistory::PrKalmanFilter: case LHCb::Event::Enum::Track::FitHistory::TrackMasterFitter: - return update_states_impl( new_track, inTrack, LHCb::Event::v3::available_states_t{} ); + return update_states_impl( + new_track, inTrack, + LHCb::Event::v3::available_states_t{} ); case LHCb::Event::Enum::Track::FitHistory::VeloKalman: return update_states_impl( new_track, inTrack, @@ -138,15 +142,80 @@ namespace { } __builtin_unreachable(); case LHCb::Event::v3::TrackType::Downstream: - return update_states_impl( new_track, inTrack, LHCb::Event::v3::available_states_t{} ); + switch ( inTrack.fitHistory() ) { + case LHCb::Event::Enum::Track::FitHistory::Unknown: + return update_states_impl( new_track, inTrack, LHCb::Event::v3::available_states_t{} ); + case LHCb::Event::Enum::Track::FitHistory::PrKalmanFilter: + case LHCb::Event::Enum::Track::FitHistory::TrackMasterFitter: + return update_states_impl( + new_track, inTrack, + LHCb::Event::v3::available_states_t{} ); + case LHCb::Event::Enum::Track::FitHistory::VeloKalman: + case LHCb::Event::Enum::Track::FitHistory::Last: + throw GaudiException( "Not a valid FitHistory.", "SOATrackConversion", StatusCode::FAILURE ); + } + __builtin_unreachable(); case LHCb::Event::v3::TrackType::Velo: - return update_states_impl( new_track, inTrack, LHCb::Event::v3::available_states_t{} ); + switch ( inTrack.fitHistory() ) { + case LHCb::Event::Enum::Track::FitHistory::Unknown: + return update_states_impl( new_track, inTrack, LHCb::Event::v3::available_states_t{} ); + case LHCb::Event::Enum::Track::FitHistory::PrKalmanFilter: + case LHCb::Event::Enum::Track::FitHistory::TrackMasterFitter: + return update_states_impl( + new_track, inTrack, + LHCb::Event::v3::available_states_t{} ); + case LHCb::Event::Enum::Track::FitHistory::VeloKalman: + case LHCb::Event::Enum::Track::FitHistory::Last: + throw GaudiException( "Not a valid FitHistory.", "SOATrackConversion", StatusCode::FAILURE ); + } + __builtin_unreachable(); case LHCb::Event::v3::TrackType::VeloBackward: - return update_states_impl( new_track, inTrack, LHCb::Event::v3::available_states_t{} ); + switch ( inTrack.fitHistory() ) { + case LHCb::Event::Enum::Track::FitHistory::Unknown: + return update_states_impl( new_track, inTrack, LHCb::Event::v3::available_states_t{} ); + case LHCb::Event::Enum::Track::FitHistory::PrKalmanFilter: + case LHCb::Event::Enum::Track::FitHistory::TrackMasterFitter: + return update_states_impl( + new_track, inTrack, + LHCb::Event::v3::available_states_t{} ); + case LHCb::Event::Enum::Track::FitHistory::VeloKalman: + case LHCb::Event::Enum::Track::FitHistory::Last: + throw GaudiException( "Not a valid FitHistory.", "SOATrackConversion", StatusCode::FAILURE ); + } + __builtin_unreachable(); case LHCb::Event::v3::TrackType::Ttrack: - return update_states_impl( new_track, inTrack, LHCb::Event::v3::available_states_t{} ); + switch ( inTrack.fitHistory() ) { + case LHCb::Event::Enum::Track::FitHistory::Unknown: + return update_states_impl( new_track, inTrack, LHCb::Event::v3::available_states_t{} ); + case LHCb::Event::Enum::Track::FitHistory::PrKalmanFilter: + case LHCb::Event::Enum::Track::FitHistory::TrackMasterFitter: + return update_states_impl( + new_track, inTrack, + LHCb::Event::v3::available_states_t{} ); + case LHCb::Event::Enum::Track::FitHistory::VeloKalman: + case LHCb::Event::Enum::Track::FitHistory::Last: + throw GaudiException( "Not a valid FitHistory.", "SOATrackConversion", StatusCode::FAILURE ); + } + __builtin_unreachable(); case LHCb::Event::v3::TrackType::Upstream: - return update_states_impl( new_track, inTrack, LHCb::Event::v3::available_states_t{} ); + switch ( inTrack.fitHistory() ) { + case LHCb::Event::Enum::Track::FitHistory::Unknown: + return update_states_impl( new_track, inTrack, LHCb::Event::v3::available_states_t{} ); + case LHCb::Event::Enum::Track::FitHistory::PrKalmanFilter: + case LHCb::Event::Enum::Track::FitHistory::TrackMasterFitter: + return update_states_impl( + new_track, inTrack, + LHCb::Event::v3::available_states_t{} ); + case LHCb::Event::Enum::Track::FitHistory::VeloKalman: + case LHCb::Event::Enum::Track::FitHistory::Last: + throw GaudiException( "Not a valid FitHistory.", "SOATrackConversion", StatusCode::FAILURE ); + } + __builtin_unreachable(); case LHCb::Event::v3::TrackType::Muon: return update_states_impl( new_track, inTrack, LHCb::Event::v3::available_states_t{} ); case LHCb::Event::v3::TrackType::UT: diff --git a/Pr/PrFilters/CMakeLists.txt b/Pr/PrFilters/CMakeLists.txt index fd7ef4ac5f919ecc537614aac43420074ee1dd86..6bb92cf72c3bb3327377a916c405c2e5b62cb0fd 100644 --- a/Pr/PrFilters/CMakeLists.txt +++ b/Pr/PrFilters/CMakeLists.txt @@ -29,6 +29,7 @@ gaudi_add_module(PrFilters src/PrGECFilter.cpp src/PrFilterIPSoA.cpp src/PrFilter.cpp + src/PrFilterTrackRelation.cpp LINK PrFiltersLib Gaudi::GaudiKernel diff --git a/Pr/PrFilters/src/PrFilterIPSoA.cpp b/Pr/PrFilters/src/PrFilterIPSoA.cpp index d9d9fe0be3be6c9564bd38a4f24429c521553adb..6adb11e39d640208ae99a624d203ceaa7099f165 100644 --- a/Pr/PrFilters/src/PrFilterIPSoA.cpp +++ b/Pr/PrFilters/src/PrFilterIPSoA.cpp @@ -52,8 +52,8 @@ namespace LHCb::Pr { for ( auto const& track : tracks.simd() ) { auto loop_mask = track.loop_mask(); // true if track.offset() +#include +#include +#include + +namespace LHCb::Pr { + + namespace { + using OutTracks = Event::v3::Tracks; + template typename BasicType> + struct is_specialisation : std::false_type {}; + + template