From ce0ed19c44fb82e1a2410537ae25417b77e45f19 Mon Sep 17 00:00:00 2001 From: Michel De Cian Date: Mon, 26 Oct 2020 17:16:32 +0100 Subject: [PATCH 1/7] Add functor for error of corrected mass --- Phys/LoKiPhys/LoKi/Particles38.h | 41 +++++ Phys/LoKiPhys/python/LoKiPhys/functions.py | 4 +- Phys/LoKiPhys/src/Particles38.cpp | 167 +++++++++++++++++++++ 3 files changed, 211 insertions(+), 1 deletion(-) diff --git a/Phys/LoKiPhys/LoKi/Particles38.h b/Phys/LoKiPhys/LoKi/Particles38.h index a39c38fc2..9a5c8671b 100644 --- a/Phys/LoKiPhys/LoKi/Particles38.h +++ b/Phys/LoKiPhys/LoKi/Particles38.h @@ -254,6 +254,28 @@ namespace LoKi { std::ostream& fillStream( std::ostream& s ) const override; // ====================================================================== }; + // ======================================================================== + /** @class MCorrectedErrorWithBestVertex + * Evaluator for corrected mass error + * + * @see LoKi::Cuts::BPVCORRMERROR + * @author Michel De Cian, michel.de.cian@cern.ch + * @date 2020-10-26 + */ + // ======================================================================== + struct GAUDI_API MCorrectedErrorWithBestVertex : LoKi::Particles::PtFlightWithBestVertex { + // ===================================================================== + /// constructor + MCorrectedErrorWithBestVertex() : AuxFunBase( std::tie() ){}; + /// MANDATORY: clone method ("virtual constructor") + MCorrectedErrorWithBestVertex* clone() const override; + /// MANDATORY: the only one essential method + result_type operator()( argument p ) const override; + /// OPTIONAL: the specific printout + std::ostream& fillStream( std::ostream& s ) const override; + // ====================================================================== + }; + // ======================================================================== /** @class BremMCorrectedWithBestVertex * Simple evaluator for 'HOP' mass @@ -378,6 +400,25 @@ namespace LoKi { */ typedef LoKi::Particles::MCorrectedWithBestVertex BPVCORRM; // ======================================================================== + /** @typedef BPVCORRMERROR + * Functor to evaluate the corrected mass error with respect to + * particle flight direction + * + * @see LoKi::Particles::MCorrectedWithBestVertex + * @see LoKi::Particles::MCorrected + * @see LoKi::Particles::PtFlightWithBestVertex + * @see LoKi::Particles::PtFlight + * @see LoKi::Particles::TransverseMomentumRel + * @see LoKi::Cuts::CORRM + * @see LoKi::Cuts::BPVCORRM + * @see LoKi::Cuts::PTFLIGHT + * @see LoKi::Cuts::BPVPTFLIGHT + * @see LoKi::Cuts::PTDIR + * @author Michel De Cian, michel.de.cian@cern.ch + * @date 2020-10-26 + */ + typedef LoKi::Particles::MCorrectedWithBestVertex BPVCORRMERROR; + // ======================================================================== /** @typedef HOPM * Simple functor to evaluate the HOP mass with respect to * particle flight direction diff --git a/Phys/LoKiPhys/python/LoKiPhys/functions.py b/Phys/LoKiPhys/python/LoKiPhys/functions.py index 2b7c6da02..9c9ead28f 100755 --- a/Phys/LoKiPhys/python/LoKiPhys/functions.py +++ b/Phys/LoKiPhys/python/LoKiPhys/functions.py @@ -1017,6 +1017,7 @@ M2ERR2 = LoKi.Particles.M2err2() # @see LoKi::Cuts::BPVPTFLIGHT # @see LoKi::Cuts::CORRM # @see LoKi::Cuts::BPVCORRM +# @see LoKi::Cuts::BPVCORRMERROR # ============================================================================= ## @see LoKi::Cuts::PTFLIGHT @@ -1027,7 +1028,8 @@ BPVPTFLIGHT = LoKi.Particles.PtFlightWithBestVertex() CORRM = LoKi.Particles.MCorrected ## @see LoKi::Cuts::BPVCORRM BPVCORRM = LoKi.Particles.MCorrectedWithBestVertex() - +## @see LoKi::Cuts::BPVCORRMERROR +BPVCORRMERROR = LoKi.Particles.MCorrectedErrorWithBestVertex() # ============================================================================= ## @see LoKi:::Cuts::ANNPID ANNPID = LoKi.Particles.ANNPID diff --git a/Phys/LoKiPhys/src/Particles38.cpp b/Phys/LoKiPhys/src/Particles38.cpp index cc4ff8be0..85f0a531f 100644 --- a/Phys/LoKiPhys/src/Particles38.cpp +++ b/Phys/LoKiPhys/src/Particles38.cpp @@ -46,6 +46,127 @@ namespace { const LoKi::ThreeVector s_VECTOR = LoKi::ThreeVector( 0, 0, -1 * Gaudi::Units::TeV ); /// the invalid 3Dpoint const LoKi::Point3D s_POINT = LoKi::Point3D( 0, 0, -1 * Gaudi::Units::km ); + + double dPTdx( const double dAdx, const double dBdx, const double PT, const double A, const double B ) { + return 1 / PT * -0.5 * ( 2 * A * B * dAdx - A * A * dBdx ) / ( B * B ); + } + //========================================================================= + // -- Calculate the corrected mass error + //========================================================================= + double mCorrErrors( const LoKi::ThreeVector sv, const LoKi::ThreeVector pv, const Gaudi::LorentzVector p, + const Gaudi::SymMatrix7x7 covP, const Gaudi::SymMatrix3x3 covPV ) { + // -- + // -- m_corr = sqrt( m_vis² + pT² ) + pT + // -- + // -- To transform the errors on the vertices and the momentum to the corrected mass, one essentially needs to do + // -- mcorr_err² = Sum_i,j( d(m_corr)/dx_i d(m_corr)/dx_j M_ij )_PV + Sum_n,m( d(m_corr)/dx_n d(m_corr)/dx_m M_nm + // )_SV + // -- where M_ij is the covariance matrix of the PV, and M_nm the covariance matrix of the SV, including + // uncertainties of the momenta + // -- of the particles that formed the SV. + // -- + // -- For the vertex coordinates: + // -- d(m_corr) / dx = d(m_corr)/dpT * dpT/dx + // -- d(m_corr)/dpT = 1/2 * 1/std::sqrt( m_vis² + pT² ) * 2 * pT + 1; + // -- pT = sqrt( (p_vec - (x_SV_vec - x_PV_vec) * A/B)² ) + // -- with A = px(x_SV - x_PV) + py(y_SV - y_PV) + pz(z_SV - z_PV) + // -- and B = (x_SV - x_PV)² + (y_SV - y_PV)² + (z_SV - z_PV)², or the magnitude squared of x_SV_vec - x_PV_vec + // -- + // -- For the momentum coordinates: + // -- m_vis² = E² - (px² + py² + pz²) + // -- d(m_corr) / dpx = 1/2 * 1 / sqrt( m_vis² + pT²) * ( -2A/B(x_SV-x_PV) ) + 1/pT * ( px - 2A/B(x_SV - x_PV) ) + // -- d(m_corr) / dE = 1/2 * / sqrt( m_vis² + pT²) * 2E + + const double x_SV = sv.x(); // SV + const double y_SV = sv.y(); // SV + const double z_SV = sv.z(); // SV + const double x_PV = pv.x(); // PV + const double y_PV = pv.y(); // PV + const double z_PV = pv.z(); // PV + const double px = p.Px(); + const double py = p.Py(); + const double pz = p.Pz(); + const double E = p.E(); + + const LoKi::ThreeVector pVec( p.Px(), p.Py(), p.Pz() ); + const double PT = std::sqrt( ( LoKi::Kinematics::perpendicular( pVec, ( sv - pv ) ) ).mag2() ); + const double A = px * ( x_SV - x_PV ) + py * ( y_SV - y_PV ) + pz * ( z_SV - z_PV ); + const double B = ( sv - pv ).Mag2(); + + const double invSqrtMassPT = 1 / std::sqrt( p.M2() + PT * PT ); + const double dMcorrdPT = 0.5 * invSqrtMassPT * 2 * PT + 1; + + // -- First let's calculate the derivates of 'A' and 'B' + // -- A + const double dAdx_SV = px; + const double dAdy_SV = py; + const double dAdz_SV = pz; + + const double dAdx_PV = -px; + const double dAdy_PV = -py; + const double dAdz_PV = -pz; + + const double dAdpx = x_SV - x_PV; + const double dAdpy = y_SV - y_PV; + const double dAdpz = z_SV - z_PV; + + // -- B + const double dBdx_SV = 2 * ( x_SV - x_PV ); + const double dBdy_SV = 2 * ( y_SV - y_PV ); + const double dBdz_SV = 2 * ( z_SV - z_PV ); + + const double dBdx_PV = -2 * ( x_SV - x_PV ); + const double dBdy_PV = -2 * ( y_SV - y_PV ); + const double dBdz_PV = -2 * ( z_SV - z_PV ); + + // -- the vertices + const double dMcdx_SV = dMcorrdPT * dPTdx( dAdx_SV, dBdx_SV, PT, A, B ); + const double dMcdy_SV = dMcorrdPT * dPTdx( dAdy_SV, dBdy_SV, PT, A, B ); + const double dMcdz_SV = dMcorrdPT * dPTdx( dAdz_SV, dBdz_SV, PT, A, B ); + + const double dMcdx_PV = dMcorrdPT * dPTdx( dAdx_PV, dBdx_PV, PT, A, B ); + const double dMcdy_PV = dMcorrdPT * dPTdx( dAdy_PV, dBdy_PV, PT, A, B ); + const double dMcdz_PV = dMcorrdPT * dPTdx( dAdz_PV, dBdz_PV, PT, A, B ); + + // -- the momentum + const double dMcdpx = -1 * invSqrtMassPT * A / B * dAdpx + 1 / PT * ( px - A / B * dAdpx ); + const double dMcdpy = -1 * invSqrtMassPT * A / B * dAdpy + 1 / PT * ( py - A / B * dAdpy ); + const double dMcdpz = -1 * invSqrtMassPT * A / B * dAdpz + 1 / PT * ( pz - A / B * dAdpz ); + const double dMcdE = invSqrtMassPT * E; + + // -- the errors on the vertices + const double errsqVertex = + // -- the diagonal for SV + covP( 0, 0 ) * dMcdx_SV * dMcdx_SV + covP( 1, 1 ) * dMcdy_SV * dMcdy_SV + covP( 2, 2 ) * dMcdz_SV * dMcdz_SV + + // -- the diagonal for PV + covPV( 0, 0 ) * dMcdx_PV * dMcdx_PV + covPV( 1, 1 ) * dMcdy_PV * dMcdy_PV + + covPV( 2, 2 ) * dMcdz_PV * dMcdz_PV + + // -- the cross terms for SV + covP( 0, 1 ) * 2. * dMcdx_SV * dMcdy_SV + covP( 0, 2 ) * 2. * dMcdx_SV * dMcdz_SV + + covP( 1, 2 ) * 2. * dMcdy_SV * dMcdz_SV + + // -- the cross terms for PV + covPV( 0, 1 ) * 2. * dMcdx_PV * dMcdy_PV + covPV( 0, 2 ) * 2. * dMcdx_PV * dMcdz_PV + + covPV( 1, 2 ) * 2. * dMcdy_PV * dMcdz_PV; + + // -- the errors on the momentum x vertex + const double errsqMom = + // -- the diagonal for the momentum + covP( 3, 3 ) * dMcdpx * dMcdpx + covP( 4, 4 ) * dMcdpy * dMcdpy + covP( 5, 5 ) * dMcdpz * dMcdpz + + covP( 6, 6 ) * dMcdE * dMcdE + + // -- momentum x momomentum cross terms + covP( 3, 4 ) * 2. * dMcdpx * dMcdpy + covP( 3, 5 ) * 2. * dMcdpx * dMcdpz + covP( 3, 6 ) * 2. * dMcdpx * dMcdE + + covP( 4, 5 ) * 2. * dMcdpy * dMcdpz + covP( 4, 6 ) * 2. * dMcdpy * dMcdE + covP( 5, 6 ) * 2. * dMcdpz * dMcdE + + // -- momentum x position terms + covP( 0, 3 ) * 2. * dMcdx_SV * dMcdpx + covP( 1, 3 ) * 2. * dMcdy_SV * dMcdpx + + covP( 2, 3 ) * 2. * dMcdz_SV * dMcdpx + covP( 0, 4 ) * 2. * dMcdx_SV * dMcdpy + + covP( 1, 4 ) * 2. * dMcdy_SV * dMcdpy + covP( 2, 4 ) * 2. * dMcdz_SV * dMcdpy + + covP( 0, 5 ) * 2. * dMcdx_SV * dMcdpz + covP( 1, 5 ) * 2. * dMcdy_SV * dMcdpz + + covP( 2, 5 ) * 2. * dMcdz_SV * dMcdpz + covP( 0, 6 ) * 2. * dMcdx_SV * dMcdE + + covP( 1, 6 ) * 2. * dMcdy_SV * dMcdE + covP( 2, 6 ) * 2. * dMcdz_SV * dMcdE; + + return std::sqrt( errsqVertex + errsqMom ); + } + // ========================================================================== } // namespace // ============================================================================ @@ -250,6 +371,52 @@ LoKi::Particles::MCorrectedWithBestVertex::result_type LoKi::Particles::MCorrect std::ostream& LoKi::Particles::MCorrectedWithBestVertex::fillStream( std::ostream& s ) const { return s << "BPVCORRM"; } // ============================================================================ +// ============================================================================ +// MANDATORY: clone method ("virtual constructor") +// ============================================================================ +LoKi::Particles::MCorrectedErrorWithBestVertex* LoKi::Particles::MCorrectedErrorWithBestVertex::clone() const { + return new LoKi::Particles::MCorrectedErrorWithBestVertex( *this ); +} +// ============================================================================ +// MANDATORY: the only one essential method +// ============================================================================ +LoKi::Particles::MCorrectedErrorWithBestVertex::result_type LoKi::Particles::MCorrectedErrorWithBestVertex:: + operator()( LoKi::Particles::MCorrectedErrorWithBestVertex::argument p ) const { + if ( 0 == p ) { + Error( "Invalid argument, return 'Invalid Mass'" ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ ); + return LoKi::Constants::InvalidMass; + } + // get the decay vertex: + const LHCb::VertexBase* vx = p->endVertex(); + if ( 0 == vx ) { + Error( "EndVertex is invalid, return 'Invalid Mass'" ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ ); + return LoKi::Constants::InvalidMass; + } + // + const LHCb::VertexBase* pv = bestVertex( p ); + if ( 0 == pv ) { + Error( "BestVertex is invalid, return 'Invalid Mass'" ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ ); + return LoKi::Constants::InvalidMass; + } + // + setVertex( pv ); + // + Assert( LoKi::Vertices::VertexHolder::valid(), "Vertex-Information is not valid" ); + // + + LoKi::ThreeVector sv( vx->position().X(), vx->position().Y(), vx->position().Z() ); + LoKi::ThreeVector primV( pv->position().X(), pv->position().Y(), pv->position().Z() ); + + return mCorrErrors( sv, primV, p->momentum(), p->covMatrix(), pv->covMatrix() ); +} +// ============================================================================ +// OPTIONAL: the specific printout +// ============================================================================ +std::ostream& LoKi::Particles::MCorrectedErrorWithBestVertex::fillStream( std::ostream& s ) const { + return s << "BPVCORRMERROR"; +} +// ============================================================================ + // ========== //00oo..oo00// =============== // Implementation of the Bremshtralung corrected B mass // ============================================================================ -- GitLab From 1fac650b737a09696871c73302bc1e6958496dd9 Mon Sep 17 00:00:00 2001 From: Michel De Cian Date: Tue, 27 Oct 2020 20:36:27 +0100 Subject: [PATCH 2/7] Add functor to get the pt of a daughter relative to the flight direction of the mother --- Phys/LoKiPhys/LoKi/Particles38.h | 37 +++++++++++ Phys/LoKiPhys/python/LoKiPhys/functions.py | 2 + Phys/LoKiPhys/src/Particles38.cpp | 76 ++++++++++++++++++++++ 3 files changed, 115 insertions(+) diff --git a/Phys/LoKiPhys/LoKi/Particles38.h b/Phys/LoKiPhys/LoKi/Particles38.h index 9a5c8671b..5411060d2 100644 --- a/Phys/LoKiPhys/LoKi/Particles38.h +++ b/Phys/LoKiPhys/LoKi/Particles38.h @@ -222,6 +222,29 @@ namespace LoKi { std::ostream& fillStream( std::ostream& s ) const override; // ====================================================================== }; + // ======================================================================== + /** @class PtFlightDaughterWithBestVertex + * Evaluator for transverse momentum of daughter relative to flight direction of this particle + * Useful e.g. for B -> rho mu nu, where one wants the relative pT of the rho, but using the rho+mu vertex + * @see LoKi::Cuts::BPVPTFLIGHTDAUGHTER + * @author Michel De Cian, michel.de.cian@cern.ch + * @date 2020-10-27 + */ + // ======================================================================== + struct GAUDI_API PtFlightDaughterWithBestVertex : LoKi::Particles::PtFlight, virtual LoKi::AuxDesktopBase { + // ===================================================================== + /// constructor + PtFlightDaughterWithBestVertex( const std::string& name, LHCb::IParticlePropertySvc* ppsvc = 0 ); + /// MANDATORY: clone method ("virtual constructor") + PtFlightDaughterWithBestVertex* clone() const override; + /// MANDATORY: the only one essential method + result_type operator()( argument p ) const override; + /// OPTIONAL: the specific printout + std::ostream& fillStream( std::ostream& s ) const override; + unsigned int m_pid = 0; + // ====================================================================== + }; + // ======================================================================== /** @class MCorrectedWithBestVertex * Simple evaluator for corrected mass relative to flight direction @@ -347,6 +370,20 @@ namespace LoKi { */ typedef LoKi::Particles::PtFlightWithBestVertex BPVPTFLIGHT; // ======================================================================== + /** @typedef BPVPTFLIGHTDAUGHTER + * Evaluator for transverse momentum of daughter relative to flight direction of this particle + * Useful e.g. for B -> rho mu nu, where one wants the relative pT of the rho, but using the rho+mu vertex + * @see LoKi::Particles::PtFlightDaughterWithBestVertex + * @see LoKi::Particles::PtFlightWithBestVertex + * @see LoKi::Particles::PtFlight + * @see LoKi::Particles::TransverseMomentumRel + * @see LoKi::Cuts::PTFLIGHT + * @see LoKi::Cuts::PTDIR + * @author Michel De Cian, michel.de.cian@cern.ch + * @date 2020-10-27 + */ + typedef LoKi::Particles::PtFlightDaughterWithBestVertex BPVPTFLIGHTDAUGHTER; + // ======================================================================== /** @typedef CORRM * Simple functor to evaluate the 'corrected mass' with respect to * particle fligth direction diff --git a/Phys/LoKiPhys/python/LoKiPhys/functions.py b/Phys/LoKiPhys/python/LoKiPhys/functions.py index 9c9ead28f..178d4b767 100755 --- a/Phys/LoKiPhys/python/LoKiPhys/functions.py +++ b/Phys/LoKiPhys/python/LoKiPhys/functions.py @@ -1024,6 +1024,8 @@ M2ERR2 = LoKi.Particles.M2err2() PTFLIGHT = LoKi.Particles.PtFlight ## @see LoKi::Cuts::BPVPTFLIGHT BPVPTFLIGHT = LoKi.Particles.PtFlightWithBestVertex() +## @see LoKi::Cuts::BPVPTFLIGHT +BPVPTFLIGHTDAUGHTER = LoKi.Particles.PtFlightDaughterWithBestVertex ## @see LoKi::Cuts::CORRM CORRM = LoKi.Particles.MCorrected ## @see LoKi::Cuts::BPVCORRM diff --git a/Phys/LoKiPhys/src/Particles38.cpp b/Phys/LoKiPhys/src/Particles38.cpp index 85f0a531f..a161aa1c9 100644 --- a/Phys/LoKiPhys/src/Particles38.cpp +++ b/Phys/LoKiPhys/src/Particles38.cpp @@ -11,6 +11,11 @@ // ============================================================================ // Include files // ============================================================================ +// PartProp +// ============================================================================ +#include "Kernel/IParticlePropertySvc.h" +#include "Kernel/ParticleProperty.h" +// ============================================================================ // LoKi // ============================================================================ #include "LoKi/Particles38.h" @@ -331,6 +336,77 @@ std::ostream& LoKi::Particles::PtFlightWithBestVertex::fillStream( std::ostream& } // ============================================================================ +// ============================================================================ +// constructor +// ============================================================================ +LoKi::Particles::PtFlightDaughterWithBestVertex::PtFlightDaughterWithBestVertex( const std::string& name, + LHCb::IParticlePropertySvc* ppsvc ) + : AuxFunBase{std::tie()}, LoKi::Particles::PtFlight( s_POINT ), m_pid( 0 ) { + + const LHCb::ParticleProperty* pp = 0; + if ( ppsvc ) { + pp = ppsvc->find( name ); + } else { + pp = LoKi::Particles::ppFromName( name ); + } + if ( 0 == pp ) { Exception( "PtFlightDaughterWithBestVertex(): Unknow particle name '" + name + "'" ); } + + m_pid = pp->pdgID().abspid(); +} +// ============================================================================ +// MANDATORY: clone method ("virtual constructor") +// ============================================================================ +LoKi::Particles::PtFlightDaughterWithBestVertex* LoKi::Particles::PtFlightDaughterWithBestVertex::clone() const { + return new LoKi::Particles::PtFlightDaughterWithBestVertex( *this ); +} +// ============================================================================ +// MANDATORY: the only one essential method +// ============================================================================ +LoKi::Particles::PtFlightDaughterWithBestVertex::result_type LoKi::Particles::PtFlightDaughterWithBestVertex:: + operator()( LoKi::Particles::PtFlightDaughterWithBestVertex::argument p ) const { + if ( 0 == p ) { + Error( "Invalid argument, return 'Invalid Momentum'" ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ ); + return LoKi::Constants::InvalidMomentum; + } + + // -- We want the flight direction of the mother, but the momentum of the daughter + // -- Used e.g. for B -> rho mu nu, where one wants the endvertex of the B (=rho+mu), but the momentum of the rho + const LHCb::Particle::ConstVector& daughters = p->daughtersVector(); + auto it = std::find_if( daughters.begin(), daughters.end(), + [&]( const LHCb::Particle* dau ) { return dau->particleID().abspid() == m_pid; } ); + if ( it == daughters.end() || !it ) { + Error( "Daughter not found, return 'Invalid Momentum'" ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ ); + return LoKi::Constants::InvalidMomentum; + } + const LHCb::Particle* partForPT = *it; + + // get the decay vertex of the 'mother': + const LHCb::VertexBase* vx = p->endVertex(); + if ( 0 == vx ) { + Error( "EndVertex is invalid, return 'Invalid Momentum'" ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ ); + return LoKi::Constants::InvalidMomentum; + } + // + const LHCb::VertexBase* pv = bestVertex( p ); + if ( 0 == pv ) { + Error( "BestVertex is invalid, return 'Invalid Momentum'" ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ ); + return LoKi::Constants::InvalidMomentum; + } + // + setVertex( pv ); + // + Assert( LoKi::Vertices::VertexHolder::valid(), "Vertex-Information is not valid" ); + // + return ptFlight( partForPT->momentum(), vx->position(), position() ); +} +// ============================================================================ +// OPTIONAL: the specific printout +// ============================================================================ +std::ostream& LoKi::Particles::PtFlightDaughterWithBestVertex::fillStream( std::ostream& s ) const { + return s << "BPVPTFLIGHTDAUGHTER"; +} +// ============================================================================ + // ============================================================================ // MANDATORY: clone method ("virtual constructor") // ============================================================================ -- GitLab From 3cd44698c5e31db96cd9c059cdd16ea82bf55465 Mon Sep 17 00:00:00 2001 From: Michel De Cian Date: Thu, 29 Oct 2020 09:45:27 +0000 Subject: [PATCH 3/7] Add forgotten * --- Phys/LoKiPhys/src/Particles38.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Phys/LoKiPhys/src/Particles38.cpp b/Phys/LoKiPhys/src/Particles38.cpp index a161aa1c9..abc761a00 100644 --- a/Phys/LoKiPhys/src/Particles38.cpp +++ b/Phys/LoKiPhys/src/Particles38.cpp @@ -374,7 +374,7 @@ LoKi::Particles::PtFlightDaughterWithBestVertex::result_type LoKi::Particles::Pt const LHCb::Particle::ConstVector& daughters = p->daughtersVector(); auto it = std::find_if( daughters.begin(), daughters.end(), [&]( const LHCb::Particle* dau ) { return dau->particleID().abspid() == m_pid; } ); - if ( it == daughters.end() || !it ) { + if ( it == daughters.end() || !(*it) ) { Error( "Daughter not found, return 'Invalid Momentum'" ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ ); return LoKi::Constants::InvalidMomentum; } -- GitLab From 68cee28f101c4c8f400c083999fb5f9da4e986da Mon Sep 17 00:00:00 2001 From: Michel De Cian Date: Thu, 29 Oct 2020 10:59:19 +0100 Subject: [PATCH 4/7] fix formatting --- Phys/LoKiPhys/src/Particles38.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Phys/LoKiPhys/src/Particles38.cpp b/Phys/LoKiPhys/src/Particles38.cpp index abc761a00..83d0fd1ce 100644 --- a/Phys/LoKiPhys/src/Particles38.cpp +++ b/Phys/LoKiPhys/src/Particles38.cpp @@ -374,7 +374,7 @@ LoKi::Particles::PtFlightDaughterWithBestVertex::result_type LoKi::Particles::Pt const LHCb::Particle::ConstVector& daughters = p->daughtersVector(); auto it = std::find_if( daughters.begin(), daughters.end(), [&]( const LHCb::Particle* dau ) { return dau->particleID().abspid() == m_pid; } ); - if ( it == daughters.end() || !(*it) ) { + if ( it == daughters.end() || !( *it ) ) { Error( "Daughter not found, return 'Invalid Momentum'" ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ ); return LoKi::Constants::InvalidMomentum; } -- GitLab From 7fb174a5c91c65ccdfb2b037af9009f2fe53ec7a Mon Sep 17 00:00:00 2001 From: Michel De Cian Date: Thu, 29 Oct 2020 20:54:21 +0100 Subject: [PATCH 5/7] Add functor to calculate momentum or energy in restframe of mother whose momentum is approximated with the 'rest-frame approximation' --- Phys/LoKiPhys/LoKi/Particles38.h | 86 ++++++++++ Phys/LoKiPhys/python/LoKiPhys/functions.py | 11 ++ Phys/LoKiPhys/src/Particles38.cpp | 175 ++++++++++++++++++++- 3 files changed, 267 insertions(+), 5 deletions(-) diff --git a/Phys/LoKiPhys/LoKi/Particles38.h b/Phys/LoKiPhys/LoKi/Particles38.h index 5411060d2..a8454203f 100644 --- a/Phys/LoKiPhys/LoKi/Particles38.h +++ b/Phys/LoKiPhys/LoKi/Particles38.h @@ -14,6 +14,11 @@ // ============================================================================ // Include files // ============================================================================ +// PartProp +// ============================================================================ +#include "Kernel/IParticlePropertySvc.h" +#include "Kernel/ParticleProperty.h" +// ============================================================================ // LoKi // ============================================================================ #include "LoKi/AuxDesktopBase.h" @@ -324,6 +329,54 @@ namespace LoKi { // ====================================================================== }; // ======================================================================== + /** @class PDaughterRestFrameApproxWithBestVertex + * Evaluator for momentum of daughter in restframe of mother, where the restframe of the mother is approximated + * with m_B/m_vis * p_z * (1 + tan(alpha)) + * @see LoKi::Cuts::BPVPDAUGHTERRESTFRAMEAPPROX + * @see LoKi::Cuts::BPVPDAUGHTERRFA + * @author Michel De Cian, michel.de.cian@cern.ch + * @date 2020-10-29 + */ + // ======================================================================== + struct GAUDI_API PDaughterRestFrameApproxWithBestVertex : LoKi::Particles::PtFlight, virtual LoKi::AuxDesktopBase { + // ===================================================================== + /// constructor + PDaughterRestFrameApproxWithBestVertex( const std::string& name, LHCb::IParticlePropertySvc* ppsvc = 0 ); + /// MANDATORY: clone method ("virtual constructor") + PDaughterRestFrameApproxWithBestVertex* clone() const override; + /// MANDATORY: the only one essential method + result_type operator()( argument p ) const override; + /// OPTIONAL: the specific printout + std::ostream& fillStream( std::ostream& s ) const override; + unsigned int m_pid = 0; + LHCb::IParticlePropertySvc* m_ppsvc = nullptr; + // ====================================================================== + }; + // ======================================================================== + /** @class EDaughterRestFrameApproxWithBestVertex + * Evaluator for energy of daughter in restframe of mother, where the momentum of the mother is approximated with + * pB = m_B/m_vis * p_z * (1 + tan(alpha)) + * @see LoKi::Cuts::BPVEDAUGHTERRESTFRAMEAPPROX + * @see LoKi::Cuts::BPVEDAUGHTERRFA + * @author Michel De Cian, michel.de.cian@cern.ch + * @date 2020-10-29 + */ + // ======================================================================== + struct GAUDI_API EDaughterRestFrameApproxWithBestVertex : LoKi::Particles::PtFlight, virtual LoKi::AuxDesktopBase { + // ===================================================================== + /// constructor + EDaughterRestFrameApproxWithBestVertex( const std::string& name, LHCb::IParticlePropertySvc* ppsvc = 0 ); + /// MANDATORY: clone method ("virtual constructor") + EDaughterRestFrameApproxWithBestVertex* clone() const override; + /// MANDATORY: the only one essential method + result_type operator()( argument p ) const override; + /// OPTIONAL: the specific printout + std::ostream& fillStream( std::ostream& s ) const override; + unsigned int m_pid = 0; + LHCb::IParticlePropertySvc* m_ppsvc = nullptr; + // ====================================================================== + }; + // ======================================================================== } // namespace Particles // ========================================================================== namespace Cuts { @@ -498,6 +551,39 @@ namespace LoKi { */ typedef LoKi::Particles::BremMCorrectedWithBestVertex BPVHOPM; // ======================================================================== + /** @typedef BPVPDAUGHTERRESTFRAMEAPPROX + * Evaluator for momentum of daughter in restframe of mother, where the momentum of the mother is approximated with + * pB = m_B/m_vis * p_z * (1 + tan(alpha)) + * For more information see + * LHCb-PAPER-2015-025 + * + * @see LoKi::Particles::PDaughterRestFrameApproxWithBestVertex + * @see LoKi::Particles::EDaughterRestFrameApproxWithBestVertex + * @see LoKi::Cuts::BPVPDAUGHTERRESTFRAMEAPPROX + * @see LoKi::Cuts::BPVEDAUGHTERRESTFRAMEAPPROX + * @authors Michel De Cian, michel.de.cian@cern.ch + * @date 2020-10-29 + */ + typedef LoKi::Particles::PDaughterRestFrameApproxWithBestVertex BPVPDAUGHTERRESTFRAMEAPPROX; + typedef LoKi::Particles::PDaughterRestFrameApproxWithBestVertex BPVPDAUGHTERRFA; + // ======================================================================== + // ======================================================================== + /** @typedef BPVEDAUGHTERRESTFRAMEAPPROX + * Evaluator for energy of daughter in restframe of mother, where the momentum of the mother is approximated with + * pB = m_B/m_vis * p_z * (1 + tan(alpha)) + * For more information see + * LHCb-PAPER-2015-025 + * + * @see LoKi::Particles::EDaughterRestFrameApproxWithBestVertex + * @see LoKi::Particles::PDaughterRestFrameApproxWithBestVertex + * @see LoKi::Cuts::BPVEDAUGHTERRESTFRAMEAPPROX + * @see LoKi::Cuts::BPVPDAUGHTERRESTFRAMEAPPROX + * @authors Michel De Cian, michel.de.cian@cern.ch + * @date 2020-10-29 + */ + typedef LoKi::Particles::PDaughterRestFrameApproxWithBestVertex BPVEDAUGHTERRESTFRAMEAPPROX; + typedef LoKi::Particles::PDaughterRestFrameApproxWithBestVertex BPVEDAUGHTERRFA; + // ======================================================================== // ======================================================================== } // namespace Cuts // ========================================================================== diff --git a/Phys/LoKiPhys/python/LoKiPhys/functions.py b/Phys/LoKiPhys/python/LoKiPhys/functions.py index 178d4b767..d0d450016 100755 --- a/Phys/LoKiPhys/python/LoKiPhys/functions.py +++ b/Phys/LoKiPhys/python/LoKiPhys/functions.py @@ -1012,12 +1012,15 @@ M2ERR2 = LoKi.Particles.M2err2() # see # Mike's slides at Trigger meeting 28 September 2k+10 and # Savannah task #17418 +# Some more functions used in semileptonic decays # @thanks Mike Williams # @see LoKi::Cuts::PTFLIGHT # @see LoKi::Cuts::BPVPTFLIGHT # @see LoKi::Cuts::CORRM # @see LoKi::Cuts::BPVCORRM # @see LoKi::Cuts::BPVCORRMERROR +# @see LoKi::Cuts::BPVPDAUGHTERRESTFRAMEAPPROX +# @see LoKi::Cuts::BPVEDAUGHTERRESTFRAMEAPPROX # ============================================================================= ## @see LoKi::Cuts::PTFLIGHT @@ -1032,6 +1035,14 @@ CORRM = LoKi.Particles.MCorrected BPVCORRM = LoKi.Particles.MCorrectedWithBestVertex() ## @see LoKi::Cuts::BPVCORRMERROR BPVCORRMERROR = LoKi.Particles.MCorrectedErrorWithBestVertex() +## @see LoKi::Cuts::BPVPDAUGHTERRESTFRAMEAPPROX +## @see LoKi::Cuts::BPVPDAUGHTERRFA +BPVPDAUGHTERRESTFRAMEAPPROX = LoKi.Particles.PDaughterRestFrameApproxWithBestVertex +BPVPDAUGHTERRFA = LoKi.Particles.PDaughterRestFrameApproxWithBestVertex +## @see LoKi::Cuts::BPVEDAUGHTERRESTFRAMEAPPROX +## @see LoKi::Cuts::BPVEDAUGHTERRFA +BPVEDAUGHTERRESTFRAMEAPPROX = LoKi.Particles.EDaughterRestFrameApproxWithBestVertex +BPVEDAUGHTERRFA = LoKi.Particles.EDaughterRestFrameApproxWithBestVertex # ============================================================================= ## @see LoKi:::Cuts::ANNPID ANNPID = LoKi.Particles.ANNPID diff --git a/Phys/LoKiPhys/src/Particles38.cpp b/Phys/LoKiPhys/src/Particles38.cpp index 83d0fd1ce..ccca5fedf 100644 --- a/Phys/LoKiPhys/src/Particles38.cpp +++ b/Phys/LoKiPhys/src/Particles38.cpp @@ -11,11 +11,6 @@ // ============================================================================ // Include files // ============================================================================ -// PartProp -// ============================================================================ -#include "Kernel/IParticlePropertySvc.h" -#include "Kernel/ParticleProperty.h" -// ============================================================================ // LoKi // ============================================================================ #include "LoKi/Particles38.h" @@ -172,6 +167,18 @@ namespace { return std::sqrt( errsqVertex + errsqMom ); } + // -- Rest frame approximation, see e.g. LHCb-PAPER-2015-025 + LoKi::LorentzVector pRestFrameApprox( LoKi::LorentzVector P, LoKi::ThreeVector flightDir, double mass ) { + const double visMass = P.M(); + const double pZ = P.Vect().Z(); + const double alpha = flightDir.Theta(); + const double Bmom = mass / visMass * pZ * std::sqrt( 1 + std::tan( alpha ) * std::tan( alpha ) ); + const Gaudi::XYZVector pB = Bmom * flightDir; + const double EB = std::sqrt( mass * mass + pB.Mag2() ); + const Gaudi::LorentzVector p4B( pB.X(), pB.Y(), pB.Z(), EB ); + return p4B; + } + // ========================================================================== } // namespace // ============================================================================ @@ -695,6 +702,164 @@ std::ostream& LoKi::Particles::BremMCorrectedWithBestVertex::fillStream( std::os } // ============================================================================ +// ============================================================================ +// constructor +// ============================================================================ +LoKi::Particles::PDaughterRestFrameApproxWithBestVertex::PDaughterRestFrameApproxWithBestVertex( + const std::string& name, LHCb::IParticlePropertySvc* ppsvc ) + : AuxFunBase{std::tie()}, LoKi::Particles::PtFlight( s_POINT ), m_pid( 0 ), m_ppsvc( ppsvc ) { + + const LHCb::ParticleProperty* pp = 0; + if ( ppsvc ) { + pp = ppsvc->find( name ); + } else { + pp = LoKi::Particles::ppFromName( name ); + } + if ( 0 == pp ) { Exception( "PDaughterRestFrameApproxWithBestVertex(): Unknow particle name '" + name + "'" ); } + + m_pid = pp->pdgID().abspid(); +} +// ============================================================================ +// MANDATORY: clone method ("virtual constructor") +// ============================================================================ +LoKi::Particles::PDaughterRestFrameApproxWithBestVertex* +LoKi::Particles::PDaughterRestFrameApproxWithBestVertex::clone() const { + return new LoKi::Particles::PDaughterRestFrameApproxWithBestVertex( *this ); +} +// ============================================================================ +// MANDATORY: the only one essential method +// ============================================================================ +LoKi::Particles::PDaughterRestFrameApproxWithBestVertex::result_type +LoKi::Particles::PDaughterRestFrameApproxWithBestVertex:: +operator()( LoKi::Particles::PDaughterRestFrameApproxWithBestVertex::argument p ) const { + if ( 0 == p ) { + Error( "Invalid argument, return 'Invalid Momentum'" ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ ); + return LoKi::Constants::InvalidMomentum; + } + + const LHCb::Particle::ConstVector& daughters = p->daughtersVector(); + auto it = std::find_if( daughters.begin(), daughters.end(), + [&]( const LHCb::Particle* dau ) { return dau->particleID().abspid() == m_pid; } ); + if ( it == daughters.end() || !( *it ) ) { + Error( "Daughter not found, return 'Invalid Momentum'" ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ ); + return LoKi::Constants::InvalidMomentum; + } + const LHCb::Particle* partForP = *it; + + // get the decay vertex of the 'mother': + const LHCb::VertexBase* vx = p->endVertex(); + if ( 0 == vx ) { + Error( "EndVertex is invalid, return 'Invalid Momentum'" ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ ); + return LoKi::Constants::InvalidMomentum; + } + // + const LHCb::VertexBase* pv = bestVertex( p ); + if ( 0 == pv ) { + Error( "BestVertex is invalid, return 'Invalid Momentum'" ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ ); + return LoKi::Constants::InvalidMomentum; + } + // + setVertex( pv ); + // + Assert( LoKi::Vertices::VertexHolder::valid(), "Vertex-Information is not valid" ); + // + + double mass = 5279.3; + if ( m_ppsvc ) { + const LHCb::ParticleProperty* pp = m_ppsvc->find( p->particleID() ); + mass = pp->mass(); + } + + LoKi::LorentzVector p4B = pRestFrameApprox( p->momentum(), vx->position() - position(), mass ); + return LoKi::Kinematics::restMomentum( p4B, partForP->momentum() ); +} +// ============================================================================ +// OPTIONAL: the specific printout +// ============================================================================ +std::ostream& LoKi::Particles::PDaughterRestFrameApproxWithBestVertex::fillStream( std::ostream& s ) const { + return s << "BPVPDAUGHTERRESTFRAMEAPPROX"; +} +// ============================================================================ + +// ============================================================================ +// constructor +// ============================================================================ +LoKi::Particles::EDaughterRestFrameApproxWithBestVertex::EDaughterRestFrameApproxWithBestVertex( + const std::string& name, LHCb::IParticlePropertySvc* ppsvc ) + : AuxFunBase{std::tie()}, LoKi::Particles::PtFlight( s_POINT ), m_pid( 0 ), m_ppsvc( ppsvc ) { + + const LHCb::ParticleProperty* pp = 0; + if ( ppsvc ) { + pp = ppsvc->find( name ); + } else { + pp = LoKi::Particles::ppFromName( name ); + } + if ( 0 == pp ) { Exception( "EDaughterRestFrameApproxWithBestVertex(): Unknow particle name '" + name + "'" ); } + + m_pid = pp->pdgID().abspid(); +} +// ============================================================================ +// MANDATORY: clone method ("virtual constructor") +// ============================================================================ +LoKi::Particles::EDaughterRestFrameApproxWithBestVertex* +LoKi::Particles::EDaughterRestFrameApproxWithBestVertex::clone() const { + return new LoKi::Particles::EDaughterRestFrameApproxWithBestVertex( *this ); +} +// ============================================================================ +// MANDATORY: the only one essential method +// ============================================================================ +LoKi::Particles::EDaughterRestFrameApproxWithBestVertex::result_type +LoKi::Particles::EDaughterRestFrameApproxWithBestVertex:: +operator()( LoKi::Particles::EDaughterRestFrameApproxWithBestVertex::argument p ) const { + if ( 0 == p ) { + Error( "Invalid argument, return 'Invalid Momentum'" ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ ); + return LoKi::Constants::InvalidMomentum; + } + + const LHCb::Particle::ConstVector& daughters = p->daughtersVector(); + auto it = std::find_if( daughters.begin(), daughters.end(), + [&]( const LHCb::Particle* dau ) { return dau->particleID().abspid() == m_pid; } ); + if ( it == daughters.end() || !( *it ) ) { + Error( "Daughter not found, return 'Invalid Momentum'" ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ ); + return LoKi::Constants::InvalidMomentum; + } + const LHCb::Particle* partForP = *it; + + // get the decay vertex of the 'mother': + const LHCb::VertexBase* vx = p->endVertex(); + if ( 0 == vx ) { + Error( "EndVertex is invalid, return 'Invalid Momentum'" ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ ); + return LoKi::Constants::InvalidMomentum; + } + // + const LHCb::VertexBase* pv = bestVertex( p ); + if ( 0 == pv ) { + Error( "BestVertex is invalid, return 'Invalid Momentum'" ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ ); + return LoKi::Constants::InvalidMomentum; + } + // + setVertex( pv ); + // + Assert( LoKi::Vertices::VertexHolder::valid(), "Vertex-Information is not valid" ); + // + + double mass = 5279.3; + if ( m_ppsvc ) { + const LHCb::ParticleProperty* pp = m_ppsvc->find( p->particleID() ); + mass = pp->mass(); + } + + LoKi::LorentzVector p4B = pRestFrameApprox( p->momentum(), vx->position() - position(), mass ); + return LoKi::Kinematics::restEnergy( p4B, partForP->momentum() ); +} +// ============================================================================ +// OPTIONAL: the specific printout +// ============================================================================ +std::ostream& LoKi::Particles::EDaughterRestFrameApproxWithBestVertex::fillStream( std::ostream& s ) const { + return s << "BPVEDAUGHTERRESTFRAMEAPPROX"; +} +// ============================================================================ + // ============================================================================ // The END // ============================================================================ -- GitLab From 110ea0ec8486d026f274c44973ef7dc2d552ca4f Mon Sep 17 00:00:00 2001 From: Michel De Cian Date: Fri, 30 Oct 2020 22:38:34 +0100 Subject: [PATCH 6/7] fix wrong calculation of rest frame energy / momentum --- Phys/LoKiPhys/src/Particles38.cpp | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/Phys/LoKiPhys/src/Particles38.cpp b/Phys/LoKiPhys/src/Particles38.cpp index ccca5fedf..f48624a0f 100644 --- a/Phys/LoKiPhys/src/Particles38.cpp +++ b/Phys/LoKiPhys/src/Particles38.cpp @@ -764,14 +764,19 @@ operator()( LoKi::Particles::PDaughterRestFrameApproxWithBestVertex::argument p Assert( LoKi::Vertices::VertexHolder::valid(), "Vertex-Information is not valid" ); // - double mass = 5279.3; + const LHCb::ParticleProperty* pp = nullptr; if ( m_ppsvc ) { - const LHCb::ParticleProperty* pp = m_ppsvc->find( p->particleID() ); - mass = pp->mass(); + pp = m_ppsvc->find( p->particleID() ); + } else { + pp = LoKi::Particles::ppFromPID( p->particleID() ); + } + if ( 0 == pp ) { + Exception( "PDaughterRestFrameApproxWithBestVertex(): Unknow particle id '" + p->particleID().toString() + "'" ); } + const double mass = pp->mass(); - LoKi::LorentzVector p4B = pRestFrameApprox( p->momentum(), vx->position() - position(), mass ); - return LoKi::Kinematics::restMomentum( p4B, partForP->momentum() ); + LoKi::LorentzVector p4B = pRestFrameApprox( p->momentum(), ( vx->position() - position() ).Unit(), mass ); + return LoKi::Kinematics::restMomentum( partForP->momentum(), p4B ); } // ============================================================================ // OPTIONAL: the specific printout @@ -843,14 +848,19 @@ operator()( LoKi::Particles::EDaughterRestFrameApproxWithBestVertex::argument p Assert( LoKi::Vertices::VertexHolder::valid(), "Vertex-Information is not valid" ); // - double mass = 5279.3; + const LHCb::ParticleProperty* pp = nullptr; if ( m_ppsvc ) { - const LHCb::ParticleProperty* pp = m_ppsvc->find( p->particleID() ); - mass = pp->mass(); + pp = m_ppsvc->find( p->particleID() ); + } else { + pp = LoKi::Particles::ppFromPID( p->particleID() ); + } + if ( 0 == pp ) { + Exception( "EDaughterRestFrameApproxWithBestVertex(): Unknow particle id '" + p->particleID().toString() + "'" ); } + const double mass = pp->mass(); - LoKi::LorentzVector p4B = pRestFrameApprox( p->momentum(), vx->position() - position(), mass ); - return LoKi::Kinematics::restEnergy( p4B, partForP->momentum() ); + LoKi::LorentzVector p4B = pRestFrameApprox( p->momentum(), ( vx->position() - position() ).Unit(), mass ); + return LoKi::Kinematics::restEnergy( partForP->momentum(), p4B ); } // ============================================================================ // OPTIONAL: the specific printout -- GitLab From be65aa2d63bd9336f8b0b44815c9a408bff67040 Mon Sep 17 00:00:00 2001 From: Michel De Cian Date: Wed, 11 Nov 2020 22:11:48 +0100 Subject: [PATCH 7/7] add option for user-defined mass in RFA functors --- Phys/LoKiPhys/LoKi/Particles38.h | 16 ++++-- Phys/LoKiPhys/src/Particles38.cpp | 84 +++++++++++++++++++++++++------ 2 files changed, 80 insertions(+), 20 deletions(-) diff --git a/Phys/LoKiPhys/LoKi/Particles38.h b/Phys/LoKiPhys/LoKi/Particles38.h index a8454203f..6eaee1c0d 100644 --- a/Phys/LoKiPhys/LoKi/Particles38.h +++ b/Phys/LoKiPhys/LoKi/Particles38.h @@ -342,14 +342,18 @@ namespace LoKi { // ===================================================================== /// constructor PDaughterRestFrameApproxWithBestVertex( const std::string& name, LHCb::IParticlePropertySvc* ppsvc = 0 ); + /// constructor with optional mass value + PDaughterRestFrameApproxWithBestVertex( const std::string& name, const double mass, + LHCb::IParticlePropertySvc* ppsvc = 0 ); /// MANDATORY: clone method ("virtual constructor") PDaughterRestFrameApproxWithBestVertex* clone() const override; /// MANDATORY: the only one essential method result_type operator()( argument p ) const override; /// OPTIONAL: the specific printout std::ostream& fillStream( std::ostream& s ) const override; - unsigned int m_pid = 0; - LHCb::IParticlePropertySvc* m_ppsvc = nullptr; + unsigned int m_pid = 0; + double m_motherMass = -1.0; + LHCb::IParticlePropertySvc* m_ppsvc = nullptr; // ====================================================================== }; // ======================================================================== @@ -366,14 +370,18 @@ namespace LoKi { // ===================================================================== /// constructor EDaughterRestFrameApproxWithBestVertex( const std::string& name, LHCb::IParticlePropertySvc* ppsvc = 0 ); + /// constructor with optional mass value + EDaughterRestFrameApproxWithBestVertex( const std::string& name, const double mass, + LHCb::IParticlePropertySvc* ppsvc = 0 ); /// MANDATORY: clone method ("virtual constructor") EDaughterRestFrameApproxWithBestVertex* clone() const override; /// MANDATORY: the only one essential method result_type operator()( argument p ) const override; /// OPTIONAL: the specific printout std::ostream& fillStream( std::ostream& s ) const override; - unsigned int m_pid = 0; - LHCb::IParticlePropertySvc* m_ppsvc = nullptr; + unsigned int m_pid = 0; + double m_motherMass = -1.0; + LHCb::IParticlePropertySvc* m_ppsvc = nullptr; // ====================================================================== }; // ======================================================================== diff --git a/Phys/LoKiPhys/src/Particles38.cpp b/Phys/LoKiPhys/src/Particles38.cpp index f48624a0f..8994638a4 100644 --- a/Phys/LoKiPhys/src/Particles38.cpp +++ b/Phys/LoKiPhys/src/Particles38.cpp @@ -720,6 +720,23 @@ LoKi::Particles::PDaughterRestFrameApproxWithBestVertex::PDaughterRestFrameAppro m_pid = pp->pdgID().abspid(); } // ============================================================================ +// constructor with mass value +// ============================================================================ +LoKi::Particles::PDaughterRestFrameApproxWithBestVertex::PDaughterRestFrameApproxWithBestVertex( + const std::string& name, const double mass, LHCb::IParticlePropertySvc* ppsvc ) + : AuxFunBase{std::tie()}, LoKi::Particles::PtFlight( s_POINT ), m_pid( 0 ), m_motherMass( mass ), m_ppsvc( ppsvc ) { + + const LHCb::ParticleProperty* pp = 0; + if ( ppsvc ) { + pp = ppsvc->find( name ); + } else { + pp = LoKi::Particles::ppFromName( name ); + } + if ( 0 == pp ) { Exception( "PDaughterRestFrameApproxWithBestVertex(): Unknow particle name '" + name + "'" ); } + + m_pid = pp->pdgID().abspid(); +} +// ============================================================================ // MANDATORY: clone method ("virtual constructor") // ============================================================================ LoKi::Particles::PDaughterRestFrameApproxWithBestVertex* @@ -764,16 +781,25 @@ operator()( LoKi::Particles::PDaughterRestFrameApproxWithBestVertex::argument p Assert( LoKi::Vertices::VertexHolder::valid(), "Vertex-Information is not valid" ); // - const LHCb::ParticleProperty* pp = nullptr; - if ( m_ppsvc ) { - pp = m_ppsvc->find( p->particleID() ); + double mass = -1.0; + if ( m_motherMass < 0.0 ) { + const LHCb::ParticleProperty* pp = nullptr; + if ( m_ppsvc ) { + pp = m_ppsvc->find( p->particleID() ); + } else { + pp = LoKi::Particles::ppFromPID( p->particleID() ); + } + if ( 0 == pp ) { + Exception( "PDaughterRestFrameApproxWithBestVertex(): Unknow particle id '" + p->particleID().toString() + "'" ); + } + mass = pp->mass(); } else { - pp = LoKi::Particles::ppFromPID( p->particleID() ); + mass = m_motherMass; } - if ( 0 == pp ) { - Exception( "PDaughterRestFrameApproxWithBestVertex(): Unknow particle id '" + p->particleID().toString() + "'" ); - } - const double mass = pp->mass(); + + if ( mass < 0.0 ) + Exception( "PDaughterRestFrameApproxWithBestVertex(): Invalid mass for mother particle: " + + std::to_string( mass ) ); LoKi::LorentzVector p4B = pRestFrameApprox( p->momentum(), ( vx->position() - position() ).Unit(), mass ); return LoKi::Kinematics::restMomentum( partForP->momentum(), p4B ); @@ -804,6 +830,23 @@ LoKi::Particles::EDaughterRestFrameApproxWithBestVertex::EDaughterRestFrameAppro m_pid = pp->pdgID().abspid(); } // ============================================================================ +// constructor with mass value +// ============================================================================ +LoKi::Particles::EDaughterRestFrameApproxWithBestVertex::EDaughterRestFrameApproxWithBestVertex( + const std::string& name, const double mass, LHCb::IParticlePropertySvc* ppsvc ) + : AuxFunBase{std::tie()}, LoKi::Particles::PtFlight( s_POINT ), m_pid( 0 ), m_motherMass( mass ), m_ppsvc( ppsvc ) { + + const LHCb::ParticleProperty* pp = 0; + if ( ppsvc ) { + pp = ppsvc->find( name ); + } else { + pp = LoKi::Particles::ppFromName( name ); + } + if ( 0 == pp ) { Exception( "EDaughterRestFrameApproxWithBestVertex(): Unknow particle name '" + name + "'" ); } + + m_pid = pp->pdgID().abspid(); +} +// ============================================================================ // MANDATORY: clone method ("virtual constructor") // ============================================================================ LoKi::Particles::EDaughterRestFrameApproxWithBestVertex* @@ -848,16 +891,25 @@ operator()( LoKi::Particles::EDaughterRestFrameApproxWithBestVertex::argument p Assert( LoKi::Vertices::VertexHolder::valid(), "Vertex-Information is not valid" ); // - const LHCb::ParticleProperty* pp = nullptr; - if ( m_ppsvc ) { - pp = m_ppsvc->find( p->particleID() ); + double mass = -1.0; + if ( m_motherMass < 0.0 ) { + const LHCb::ParticleProperty* pp = nullptr; + if ( m_ppsvc ) { + pp = m_ppsvc->find( p->particleID() ); + } else { + pp = LoKi::Particles::ppFromPID( p->particleID() ); + } + if ( 0 == pp ) { + Exception( "PDaughterRestFrameApproxWithBestVertex(): Unknow particle id '" + p->particleID().toString() + "'" ); + } + mass = pp->mass(); } else { - pp = LoKi::Particles::ppFromPID( p->particleID() ); + mass = m_motherMass; } - if ( 0 == pp ) { - Exception( "EDaughterRestFrameApproxWithBestVertex(): Unknow particle id '" + p->particleID().toString() + "'" ); - } - const double mass = pp->mass(); + + if ( mass < 0.0 ) + Exception( "PDaughterRestFrameApproxWithBestVertex(): Invalid mass for mother particle: " + + std::to_string( mass ) ); LoKi::LorentzVector p4B = pRestFrameApprox( p->momentum(), ( vx->position() - position() ).Unit(), mass ); return LoKi::Kinematics::restEnergy( partForP->momentum(), p4B ); -- GitLab