Source code for Functors

###############################################################################
# (c) Copyright 2019-2023 CERN for the benefit of the LHCb Collaboration      #
#                                                                             #
# This software is distributed under the terms of the GNU General Public      #
# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
#                                                                             #
# In applying this licence, CERN does not waive the privileges and immunities #
# granted to it by virtue of its status as an Intergovernmental Organization  #
# or submit itself to any jurisdiction.                                       #
###############################################################################
from typing import List, Union
from array import array
from Functors.grammar import BoundFunctor, Functor, ComposedBoundFunctor
from PyConf.dataflow import DataHandle
import functools
from GaudiKernel import SystemOfUnits
from Functors.math import sign, similarity


def setComposedFunctor(functor, name, desc):
    """Change a composed functor's name and docstring"""
    functor._strname = name
    functor.__doc__ = desc
    return functor


CAST_TO_INT = Functor('CAST_TO_INT', "Functional::CastTo<int>",
                      '''Return argment as int''')

NaN = float('nan')

VALUE = Functor(
    'VALUE', "Functional::Value",
    '''Return contained value of an optional. If no value is contained, it throws an exception.
    This functor is used currently for example to store Tis/Tos information using relation table, where a value
    is always expected in the optional.''')

VALUE_OR = Functor(
    'VALUE_OR',
    "Functional::ValueOr",
    '''Return contained value of optional or specified default if optional is empty''',
    Params=[('Value', 'The default value.', (bool, int, float, str, list,
                                             tuple, dict, array))])
HAS_VALUE = Functor('HAS_VALUE', "Functional::HasValue",
                    '''Return true if the input has a valid value.''')

VALUE_FROM_DICT = Functor(
    'VALUE_FROM_DICT',
    "Functional::ValueFromDict",
    '''Return value from a dictionary with specified key. If the key is not found, it throws an exception.''',
    Params=[('Key', 'The key to look up.', (str, ))])


[docs]def require_all(*cuts): """Return a functor expression requiring all arguments. Example: >>> import Functors as F >>> functor = F.require_all(F.PT > 1, F.PID_K < 0) >>> functor.code_repr() '( ( ( RHO_COORDINATE @ THREEMOMENTUM ) > 1 ) & ( ( VALUE_OR(Value=nan) @ _PID_K ) < 0 ) )' """ if not cuts: raise TypeError("at least one argument is required") if len(cuts) == 1: return cuts[0] return ComposedBoundFunctor("&", *cuts)
[docs]def require_any(*cuts): """Return a functor expression requiring at least one of arguments. Example: >>> import Functors as F >>> functor = F.require_any(F.PT > 1, F.PID_K < 0) >>> functor.code_repr() '( ( ( RHO_COORDINATE @ THREEMOMENTUM ) > 1 ) | ( ( VALUE_OR(Value=nan) @ _PID_K ) < 0 ) )' """ return functools.reduce(lambda f, g: f | g, cuts)
def rename(functor, name): """Change a composed functor's name""" functor._strname = name return functor FILTER = Functor( 'FILTER', 'Filter', 'Adapt a predicate to filter a container.', Params=[('Functor', 'Predicate to filter the container with.', BoundFunctor)]) ADDRESSOF = Functor('ADDRESSOF', "Common::AddressOf", 'Return address of input. E.g. for pointer comparison') _FORWARDARGS = Functor( '_FORWARDARGS', "Common::ForwardArgs", 'Forward all arguments or a specific one as indicated by index', TemplateParams= [('index', 'Nth argument to forward. If not specified all arguments will be forwarded.', lambda x: str(x))]) FORWARDARGS = setComposedFunctor( _FORWARDARGS, "FORWARDARGS", """Forward all the arguments. It can be used in binding operation for composed functors with argument. While binding, one (or more) argument is fixed and all the other will be forwarded. Example: The call operator of :py:func:`~BPV`, which is composed as `BEST_PV.bind(TES(Vertices), FORWARDARGS)`, expects two arguments: list of primary vertices and a reconstructed particle. The bind fixes the first argument to the output of the :py:func:`~TES` functor and :py:func:`~FORWARDARGS` functor simply forwards all other arguments (in this instance the reconstructed particle). """) FORWARDARG0 = setComposedFunctor( _FORWARDARGS(index=0), "FORWARDARG0", """ Forward the first argument. Note: For reference, have a look at :py:func:`~FORWARDARGS` """) FORWARDARG1 = setComposedFunctor( _FORWARDARGS(index=1), "FORWARDARG1", """ Forward the second argument Note: For reference, have a look at :py:func:`~FORWARDARGS` """) FORWARDARG2 = setComposedFunctor( _FORWARDARGS(index=2), "FORWARDARG2", """ Forward the third argument Note: For reference, have a look at :py:func:`~FORWARDARGS` """) # FIXME to avoid fixing all ADL problems TOLINALG = Functor('TOLINALG', "Common::ToLinAlg", 'trafo gaudi/root classes to linalg vecs.') X_COORDINATE = Functor('X_COORDINATE', "Common::X_Coordinate", 'Get X coordinate. Functor to be used in composition.') Y_COORDINATE = Functor('Y_COORDINATE', "Common::Y_Coordinate", 'Get Y coordinate. Functor to be used in composition.') Z_COORDINATE = Functor('Z_COORDINATE', "Common::Z_Coordinate", 'Get Z coordinate. Functor to be used in composition.') E_COORDINATE = Functor('E_COORDINATE', "Common::E_Coordinate", 'Get E coordinate. Functor to be used in composition.') # PHI already has the meaning of phi(slopes) so for now we use PHI_COORDINATE PHI_COORDINATE = Functor( 'PHI_COORDINATE', "Common::Phi_Coordinate", 'Get phi coordinate. Functor to be used in composition.') # same problem as above ETA_COORDINATE = Functor( 'ETA_COORDINATE', "Common::Eta_Coordinate", 'Get eta coordinate (pseudorapidity). Functor to be used in composition.') RHO_COORDINATE = Functor( 'RHO_COORDINATE', "Common::Rho_Coordinate", 'Get rho coordinate. Functor to be used in composition.') MAGNITUDE = Functor('MAGNITUDE', "Common::Magnitude", 'Get magnitude of vector.') DOT = Functor('DOT', "Common::Dot", 'Dot product.') NORMEDDOT = Functor('NORMEDDOT', "Common::NormedDot", 'Normalized dot product.') COSANGLE = setComposedFunctor(NORMEDDOT, "COSANGLE", """Evaluates dot product of two unit vectors""") UNITVECTOR = Functor('UNITVECTOR', "Common::UnitVector", 'Normalize vector.') REFERENCEPOINT = Functor( 'REFERENCEPOINT', "Track::ReferencePoint", 'Get the track reference point (position at which the momentum of the particle is evaluated)' ) SLOPES = Functor('SLOPES', "Track::Slopes", 'Get the slopes vector (tx=dx/dz,ty=dy/dz,1.) from a track') FOURMOMENTUM = Functor('FOURMOMENTUM', "Track::FourMomentum", "4-Momentum vector.") THREEMOMENTUM = Functor('THREEMOMENTUM', "Track::ThreeMomentum", "3-Momentum vector.") REFERENCEPOINT_X = setComposedFunctor( X_COORDINATE @ REFERENCEPOINT, "REFERENCEPOINT_X", """Get the X-coordinate of the reference point (see :py:func:`~REFERENCEPOINT` for definition).""" ) REFERENCEPOINT_Y = setComposedFunctor( Y_COORDINATE @ REFERENCEPOINT, "REFERENCEPOINT_Y", """Get the Y-coordinate of the reference point (see :py:func:`~REFERENCEPOINT` for definition).""" ) REFERENCEPOINT_Z = setComposedFunctor( Z_COORDINATE @ REFERENCEPOINT, "REFERENCEPOINT_Z", """Get the Z-coordinate of the reference point (see :py:func:`~REFERENCEPOINT` for definition).""" ) TX = setComposedFunctor( X_COORDINATE @ SLOPES, "TX", """Get the X-coordinate of the slope (see :py:func:`~SLOPES` for definition). Functor's call expects a particle-like object""") TY = setComposedFunctor( Y_COORDINATE @ SLOPES, "TY", """Get the Y-coordinate of the slope (see :py:func:`~SLOPES` for definition). Functor's call expects a particle-like object""") PHI = setComposedFunctor( PHI_COORDINATE @ SLOPES, "PHI", """Get the phi coordinate of a slope (see :py:func:`~SLOPES` for definition). Functor's call expects a particle-like object""") ETA = setComposedFunctor( ETA_COORDINATE @ SLOPES, "ETA", """Get the eta (pseudorapidity) coordinate of a slope (see :py:func:`~SLOPES` for definition). Functor's call expects a particle-like object""") P = setComposedFunctor( MAGNITUDE @ THREEMOMENTUM, "P", """Get the magnitude of the momentum vector (see :py:func:`~THREEMOMENTUM` for definition). Functor's call expects a particle-like object""") PX = setComposedFunctor( X_COORDINATE @ THREEMOMENTUM, "PX", """Get the X-coordinate of the momentum (see :py:func:`~THREEMOMENTUM` for definition). Functor's call expects a particle-like object""") PY = setComposedFunctor( Y_COORDINATE @ THREEMOMENTUM, "PY", """Get the Y-coordinate of the momentum (see :py:func:`~THREEMOMENTUM` for definition). Functor's call expects a particle-like object""") PZ = setComposedFunctor( Z_COORDINATE @ THREEMOMENTUM, "PZ", """Get the Z-coordinate of the momentum (see :py:func:`~THREEMOMENTUM` for definition). Functor's call expects a particle-like object""") ENERGY = setComposedFunctor( E_COORDINATE @ FOURMOMENTUM, "ENERGY", """Get the energy (see :py:func:`~FOURMOMENTUM` for definition). Functor's call expects a particle-like object""") PT = setComposedFunctor( RHO_COORDINATE @ THREEMOMENTUM, "PT", """Get the transverse momentum (see :py:func:`~THREEMOMENTUM` for definition). Functor's call expects a particle-like object""") SIZE_OF = Functor('SIZE_OF', "detail::SizeOf", 'Get Size of input') # LHCbMath MATH_VALUE = Functor('MATH_VALUE', 'LHCbMath::ValueWithError::Value', 'Returns the value of Gaudi::Math::ValueWithError') MATH_ERROR = Functor('MATH_ERROR', 'LHCbMath::ValueWithError::Error', 'Returns the error of Gaudi::Math::ValueWithError') MATH_SCALAR_MOMENTUM = Functor( 'MATH_SCALAR_MOMENTUM', 'LHCbMath::scalarMomentum', 'Returns the scalar momentum by input.scalarMomentum()') MATH_INVARIANT_MASS = Functor( 'MATH_INVARIANT_MASS', 'LHCbMath::invariantMass', 'Returns the scalar momentum by input.invariantMass()') # ParticleParams PARTICLE_PARAMS_FLIGHT_DISTANCE = Functor( 'PARTICLE_PARAMS_FLIGHT_DISTANCE', 'LHCbMath::ParticleParams::flightDistance', 'Returns the flight distance of Gaudi::Math::ParticleParams') PARTICLE_PARAMS_CTAU = Functor( 'PARTICLE_PARAMS_CTAU', 'LHCbMath::ParticleParams::ctau', 'Returns the c*tau of Gaudi::Math::ParticleParams') PARTICLE_PARAMS_LEN_POS_COV = Functor( 'PARTICLE_PARAMS_LEN_POS_COV', 'LHCbMath::ParticleParams::lenPosCov', 'Returns the "Matrix" with correlation errors between position and decay length from Gaudi::Math::ParticleParams' ) PARTICLE_PARAMS_LEN_MOM_COV = Functor( 'PARTICLE_PARAMS_LEN_MOM_COV', 'LHCbMath::ParticleParams::lenMomCov', 'Returns the "Matrix" with correlation errors between momentum and decay length from Gaudi::Math::ParticleParams' ) def template_list_arg_formatter(args: list): """Format a list for use as template arguments""" # return "a1,a2,a3..." return ", ".join([str(a) for a in args]) _TES = Functor( '_TES', "Common::TES", 'Returns a tuple of references to data in the TES', Params=[('DataHandles', "List of DataHandles", list)], TemplateParams=[("DataTypes", "Types of the data that will be retrieved from TES", template_list_arg_formatter)])
[docs]def TES(datahandles: Union[DataHandle, List[DataHandle]]) -> BoundFunctor: """ Return references to specified TES locations When invoked, this functor will return a tuple of references to the specified TES locations. Note: This functor is not for direct use in selection, but rather for the composition of more complex functors. Internally it is a helper function to create :py:func:`~Functors._TES` functor Args: datahandles: Datahandles of the TES locations """ if not isinstance(datahandles, list): datahandles = [datahandles] for dh in datahandles: if not isinstance(dh, DataHandle): raise TypeError( "TES Functor only accepts DataHandle but received: " + str(dh) + " of type " + str(type(dh))) if dh.type == 'unknown_t': raise TypeError( "TES Functor only accepts DataHandles that have a correct C++ type." "You have to force the C++ type of your DataHandle." "See DataHandle's force_type() member function") return _TES( DataHandles=datahandles, DataTypes=[dh.type for dh in datahandles])
[docs]def SIZE(dh: DataHandle): """Size of the container at the given TES location Args: dh: Datahandle of TES location from which container will be retrieved """ return SIZE_OF @ TES(dh)
_CALL = Functor( '_CALL', 'Common::Call', 'Invoke call operator with integer values, e.g. to retrieve (i, j)th element of a covariance matrix.', TemplateParams=[('Args', 'Integer values to pass into the operator()', template_list_arg_formatter)])
[docs]def CALL(Row: int, Col: int): """Return an element of a matrix Args: Row: row of element Col: column of element """ return _CALL(Args=[Row, Col])
TRACK_COVARIANCE = Functor( 'TRACK_COVARIANCE', 'Track::Covariance', 'Get the covariance matrix for an track state: (x,y,tx,ty,qop).', ) # old COV Functor for compatibility
[docs]def COV(Row: int, Col: int): """Return an element of a track's covariance :py:func:`~TRACK_COVARIANCE`: (x,y,tx,ty,qop) Args: Row: row of element Col: column of element """ return CALL(Row, Col) @ TRACK_COVARIANCE
THREE_MOM_COV_MATRIX = Functor( 'THREE_MOM_COV_MATRIX', 'Particle::threeMomCovMatrix', 'Get the covariance matrix for (px, py, pz)', ) THREE_MOM_POS_COV_MATRIX = Functor( 'THREE_MOM_POS_COV_MATRIX', 'Particle::threeMomPosCovMatrix', """Get the covariance matrix for (px, py, pz) x (x, y, z): [(x,px), (x,py), (x,pz)] [(y,px), (y,py), (y,pz)] [(z,px), (z,py), (z,pz)] """, ) MOM_POS_COV_MATRIX = Functor( 'MOM_POS_COV_MATRIX', 'Particle::momPosCovMatrix', """Get the covariance matrix for (px, py, pz, pe) x (x, y, z): [(x,px), (x,py), (x,pz), (x,pe)] [(y,px), (y,py), (y,pz), (y,pe)] [(z,px), (z,py), (z,pz), (z,pe)] """, ) POS_COV_MATRIX = Functor( 'MOM_POS_COV_MATRIX', 'Particle::posCovMatrix', 'Get the covariance matrix for (x, y, z)', ) BEST_PV = Functor('BEST_PV', "Common::BestPV", 'Given list of vertices, get best PV of particle.') ENDVERTEX = Functor('ENDVERTEX', "Common::EndVertex", 'Get the endvertex of an object.') POSITION = Functor('POSITION', "Common::Position", 'Get the position of an object.') OWNPV = Functor('OWNPV', "Common::OwnPV", 'Get PV associated to particle.') POSITION_X = setComposedFunctor( X_COORDINATE @ POSITION, "POSITION_X", """Get the X-coordinate of the :py:func:`~POSITION`""") POSITION_Y = setComposedFunctor( Y_COORDINATE @ POSITION, "POSITION_Y", """Get the Y-coordinate of the :py:func:`~POSITION`""") POSITION_Z = setComposedFunctor( Z_COORDINATE @ POSITION, "POSITION_Z", """Get the Z-coordinate of the :py:func:`~POSITION`""") # FIXME remove trafo hack ENDVERTEX_POS = setComposedFunctor( TOLINALG @ (POSITION @ ENDVERTEX), "ENDVERTEX_POS", """Get the 3-vector position of the :py:func:`~ENDVERTEX` of a particle. Functor's call operator expects a particle-like object.""") END_VX = setComposedFunctor( X_COORDINATE @ ENDVERTEX_POS, "END_VX", """Get the X-coordinate of the :py:func:`~ENDVERTEX` of a particle. Functor's call operator expects a particle-like object.""") END_VY = setComposedFunctor( Y_COORDINATE @ ENDVERTEX_POS, "END_VY", """Get the Y-coordinate of the :py:func:`~ENDVERTEX` of a particle. Functor's call operator expects a particle-like object.""") END_VZ = setComposedFunctor( Z_COORDINATE @ ENDVERTEX_POS, "END_VZ", """Get the Z--coordinate of the :py:func:`~ENDVERTEX` of a particle. Functor's call operator expects a particle-like object.""") END_VRHO = setComposedFunctor( RHO_COORDINATE @ ENDVERTEX_POS, "END_VRHO", """Get the rho-coordinate of the :py:func:`~ENDVERTEX` of a particle. Functor's call operator expects a particle-like object.""")
[docs]def BPV(Vertices: DataHandle = None): """ Determine Best Primary Vertex of a particle Functor's call operator expects a particle-like object. Note: "Best" is chosen as the PV for which the particle has the smallest impact parameter (IP). Note that this is different to Run 1+2, where "best" was chosen based on IP chi^2. See also :py:func:`~BEST_PV` functor for links to where this is defined in the code. See also final slide of final talk in https://indico.cern.ch/event/1361613/ for more details. Args: Vertices: DataHandle of the vertices - if not provided will use :py:func:`~OWNPV` """ if Vertices is None: return OWNPV.bind(FORWARDARGS) return BEST_PV.bind(TES(Vertices), FORWARDARGS)
[docs]def BPV_POS(Vertices: DataHandle = None): """ Position of :py:func:`~BPV` Functor's call operator expects a particle-like object. Args: Vertices: DataHandle of the vertices """ # FIXME remove linalg trafo hack return TOLINALG @ (POSITION @ BPV(Vertices))
[docs]def OWNPV_POS(): """ Position of :py:func:`~OWNPV` Functor's call operator expects a particle-like object. Args: Vertices: DataHandle of the vertices """ # FIXME remove linalg trafo hack return TOLINALG @ (POSITION @ OWNPV)
[docs]def BPVX(Vertices: DataHandle = None): """ X position of :py:func:`~BPV_POS` Functor's call operator expects a particle-like object. Args: Vertices: DataHandle of the vertices """ return X_COORDINATE @ BPV_POS(Vertices)
[docs]def BPVY(Vertices: DataHandle = None): """ Y position of :py:func:`~BPV_POS` Functor's call operator expects a particle-like object. Args: Vertices: DataHandle of the vertices """ return Y_COORDINATE @ BPV_POS(Vertices)
[docs]def BPVZ(Vertices: DataHandle = None): """ Z position of :py:func:`~BPV_POS` Functor's call operator expects a particle-like object. Args: Vertices: DataHandle of the vertices """ return Z_COORDINATE @ BPV_POS(Vertices)
[docs]def BPVVDX(Vertices: DataHandle = None): """ X distance between :py:func:`~ENDVERTEX_POS` and :py:func:`~BPV_POS` Functor's call operator expects a particle-like object. Args: Vertices: DataHandle of the vertices """ return END_VX - X_COORDINATE @ BPV_POS(Vertices)
[docs]def BPVVDY(Vertices: DataHandle = None): """ Y distance between :py:func:`~ENDVERTEX_POS` and :py:func:`~BPV_POS` Functor's call operator expects a particle-like object. Args: Vertices: DataHandle of the vertices """ return END_VY - Y_COORDINATE @ BPV_POS(Vertices)
[docs]def BPVVDZ(Vertices: DataHandle = None): """ Z distance between :py:func:`~ENDVERTEX_POS` and :py:func:`~BPV_POS` Functor's call operator expects a particle-like object. Args: Vertices: DataHandle of the vertices """ return END_VZ - Z_COORDINATE @ BPV_POS(Vertices)
[docs]def BPVFDVEC(Vertices: DataHandle = None): """ Distance vector between :py:func:`~ENDVERTEX_POS` and :py:func:`~BPV_POS` Functor's call operator expects a particle-like object. Args: Vertices: DataHandle of the vertices """ return ENDVERTEX_POS - BPV_POS(Vertices)
[docs]def BPVVDRHO(Vertices: DataHandle = None): """ Rho coordinate of the distance vector between :py:func:`~ENDVERTEX_POS` and :py:func:`~BPV_POS` Functor's call operator expects a particle-like object. Args: Vertices: DataHandle of the vertices """ return RHO_COORDINATE @ BPVFDVEC(Vertices)
# why is BPVETA not BPVVDETA?! # and why VD instead of FD? all of this seems aribtrary....
[docs]def BPVETA(Vertices: DataHandle = None): """ Eta (pseudorapidity) coordinate of the distance vector between :py:func:`~ENDVERTEX_POS` and :py:func:`~BPV_POS` Functor's call operator expects a particle-like object. Args: Vertices: DataHandle of the vertices """ return ETA_COORDINATE @ BPVFDVEC(Vertices)
[docs]def BPVFD(Vertices: DataHandle = None): """ Flight distance (magnitude of :py:func:`~BPVFDVEC`) Functor's call operator expects a particle-like object. Args: Vertices: DataHandle of the vertices """ return MAGNITUDE @ BPVFDVEC(Vertices)
[docs]def BPVFDIR(Vertices: DataHandle = None): """ Normalized flight direction vector (unitvector of :py:func:`~BPVFDVEC`) Functor's call operator expects a particle-like object. Args: Vertices: DataHandle of the vertices """ return UNITVECTOR @ BPVFDVEC(Vertices)
[docs]def BPVDIRA(Vertices: DataHandle = None): """ Cosine of angle between particle momentum and flight direction (:py:func:`~BPVFDVEC`) Functor's call operator expects a particle-like object. Args: Vertices: DataHandle of the vertices """ return NORMEDDOT.bind(THREEMOMENTUM, BPVFDVEC(Vertices))
ABS = Functor("ABS", "Common::Abs", "Evaluates the absolute value of a scalar quantity") ADJUST_ANGLE = Functor('ADJUST_ANGLE', "Common::AdjustAngle", "Adjust angle if larger than pi") SQRT = Functor("SQRT", "Common::Sqrt", "Evaluates the square root of a scalar quantity") #binary functors on angles DETA = setComposedFunctor((ETA_COORDINATE @ SLOPES) @ FORWARDARG0 - (ETA_COORDINATE @ SLOPES) @ FORWARDARG1, "DETA", """ Evaluates the difference between the pseudorapidity of two particles Binary functor: Functor's call operator expects two particle-like objects Example: >>> import Functors as F >>> from Functors.tests.categories import dummy_data_particle_range >>> from PyConf.Algorithms import WeightedRelTableAlg >>> alg = WeightedRelTableAlg( >>> InputCandidates = dummy_data_particle_range, >>> ReferenceParticles = dummy_data_particle_range, >>> Cut = F.DETA < 0.2) >>> alg.OutputRelations DataHandle('/Event/WeightedRelTableAlg/OutputRelations') """) DPHI = setComposedFunctor( ADJUST_ANGLE @ ((PHI_COORDINATE @ SLOPES) @ FORWARDARG0 - (PHI_COORDINATE @ SLOPES) @ FORWARDARG1), "DPHI", """ Evaluates the difference between the phi angle of two particles The difference is then adjusted in the range [-pi, pi] (see :py:func:`~ADJUST_ANGLE`) Binary functor: Functor's call operator expects two particle-like objects Example: >>> import Functors as F >>> from Functors.tests.categories import dummy_data_particle_range >>> from PyConf.Algorithms import WeightedRelTableAlg >>> alg = WeightedRelTableAlg( >>> InputCandidates = dummy_data_particle_range, >>> ReferenceParticles = dummy_data_particle_range, >>> Cut = F.DPHI < 0.2) >>> alg.OutputRelations DataHandle('/Event/WeightedRelTableAlg/OutputRelations') """) DR2 = setComposedFunctor( DETA * DETA + DPHI * DPHI, "DR2", """ Evaluates the dr2 between two particles, defined as DETA^2+DPHI^2 Binary functor: Functor's call operator expects two particle-like objects Example: >>> import Functors as F >>> from Functors.tests.categories import dummy_data_particle_range >>> from PyConf.Algorithms import WeightedRelTableAlg >>> alg = WeightedRelTableAlg( >>> InputCandidates = dummy_data_particle_range, >>> ReferenceParticles = dummy_data_particle_range, >>> Cut = F.DR2 < 0.4) >>> alg.OutputRelations DataHandle('/Event/WeightedRelTableAlg/OutputRelations') """) ISBASICPARTICLE = Functor( 'ISBASICPARTICLE', "Particle::IsBasicParticle", """IsBasicParticle. Returns the 'isBasicParticle' of the Particle object.""") TRACK = Functor('TRACK', "Particle::GetTrack", "Get the track object from a ChargedBasic") STATES = Functor('STATES', "Track::States", "Retrieve const Container with pointers to all the states")
[docs]def STATE_AT(location: str): """Access the state at the requested location. Throws if state not present. Args: location (str): LHCb::Event::Enum::State::Location string. Returns: Functor: The actual functor. """ _STATE_AT = Functor( '_STATE_AT', "Track::StateAt", "Return the state at the given location.", Params=[('Location', "LHCb::Event::Enum::State::Location", str)]) return _STATE_AT(Location=location)
INMUON = Functor( 'INMUON', "PID::InAcceptance", """InAcceptance. Functor's call operator expects a particle-like object.""") ISMUON = Functor( 'ISMUON', "PID::IsMuon", """IsMuon. Functor's call operator expects a particle-like object.""") ISMUONTIGHT = Functor( 'ISMUONTIGHT', "PID::IsMuonTight", """IsMuonTight. Functor's call operator expects a particle-like object.""") MUONCHI2CORR = Functor( 'MUONCHI2CORR', "PID::MuonChi2Corr", """MuonChi2Corr. Functor's call operator expects a particle-like object.""") MUONLLMU = Functor( 'MUONLLMU', "PID::MuonLLMu", """MuonLLMu. Functor's call operator expects a particle-like object.""") MUONLLBG = Functor( 'MUONLLBG', "PID::MuonLLBg", """MuonLLBg. Functor's call operator expects a particle-like object.""") MUONCATBOOST = Functor( 'MUONCATBOOST', "PID::MuonCatBoost", """CatBoost. Functor's call operator expects a particle-like object.""") HASBREM = Functor( 'HASBREM', "PID::HasBrem", """Has non-zero brem momentum-recovery energy. Functor's call operator expects a particle-like object.""") HASBREMADDED = Functor( 'HASBREMADDED', "Track::HasBremAdded", """Has non-zero brem momentum-recovery energy added (using Particle class flag). Functor's call operator expects a particle-like object in v1 event model.""" ) INECAL = Functor( 'INECAL', "PID::InEcal", """In Ecal acceptance. Functor's call operator expects a particle-like object.""") INHCAL = Functor( 'INHCAL', "PID::InHcal", """In Hcal acceptance. Functor's call operator expects a particle-like object.""") INBREM = Functor( 'INBREM', "PID::InBrem", """In Brem acceptance. Functor's call operator expects a particle-like object.""") BREMENERGY = Functor( 'BREMENERGY', "PID::BremEnergy", """Brem momentum-recovery energy. Functor's call operator expects a particle-like object.""" ) BREMBENDCORR = Functor( 'BREMBENDCORR', "PID::BremBendCorr", """Correction factor accounting for bending biases in track due to brem. Functor's call operator expects a particle-like object.""") BREMPIDE = Functor( 'BREMPIDE', "PID::BremPIDe", """Brem-based DLL for electron-ID. Functor's call operator expects a particle-like object.""") ECALPIDE = Functor( 'ECALPIDE', "PID::EcalPIDe", """Ecal-based DLL for electron-ID. Functor's call operator expects a particle-like object.""") ECALPIDMU = Functor( 'ECALPIDMU', "PID::EcalPIDmu", """Ecal-based DLL for mu-ID. Functor's call operator expects a particle-like object.""") HCALPIDE = Functor( 'HCALPIDE', "PID::HcalPIDe", """Hcal-based DLL for electron-ID. Functor's call operator expects a particle-like object.""") HCALPIDMU = Functor( 'HCALPIDMU', "PID::HcalPIDmu", """Hcal-based DLL for mu-ID. Functor's call operator expects a particle-like object.""") RICH_DLL_E = Functor( 'RICH_DLL_E', "PID::RichDLLe", """Rich-based DLL for electron-ID. Functor's call operator expects a particle-like object.""") RICH_DLL_MU = Functor( 'RICH_DLL_MU', "PID::RichDLLmu", """Rich-based DLL for mu-ID. Functor's call operator expects a particle-like object.""") RICH_DLL_P = Functor( 'RICH_DLL_P', "PID::RichDLLp", """Rich-based DLL for proton-ID. Functor's call operator expects a particle-like object.""") RICH_DLL_K = Functor( 'RICH_DLL_K', "PID::RichDLLk", """Rich-based DLL for kaon-ID. Functor's call operator expects a particle-like object.""") RICH_DLL_PI = Functor( 'RICH_DLL_PI', "PID::RichDLLpi", """Rich-based DLL for pion-ID. Functor's call operator expects a particle-like object.""") RICH_DLL_D = Functor( 'RICH_DLL_D', "PID::RichDLLd", """Rich-based DLL for deuteron-ID. Functor's call operator expects a particle-like object.""") RICH_DLL_BT = Functor( 'RICH_DLL_BT', "PID::RichDLLbt", """Rich-based DLL for below threshold tracks. Functor's call operator expects a particle-like object.""") RICH_SCALED_DLL_E = Functor( 'RICH_SCALED_DLL_E', "PID::RichScaledDLLe", """Rich-based DLL for electron-ID. Scaled with monotonic function to approximate true DLL. For usage in combined DLLs (with other subdetectors). Functor's call operator expects a particle-like object.""") RICH_SCALED_DLL_MU = Functor( 'RICH_SCALED_DLL_MU', "PID::RichScaledDLLmu", """Rich-based DLL for mu-ID. Scaled with monotonic function to approximate true DLL. For usage in combined DLLs (with other subdetectors). Functor's call operator expects a particle-like object.""") RICH1_GAS_USED = Functor( 'RICH1_GAS_USED', "PID::Rich1GasUsed", """Rich 1 gas flag. Functor's call operator expects a particle-like object.""") RICH2_GAS_USED = Functor( 'RICH2_GAS_USED', "PID::Rich2GasUsed", """Rich 2 gas flag. Functor's call operator expects a particle-like object.""") RICH_THRESHOLD_EL = Functor( 'RICH_THRESHOLD_EL', "PID::RichThresholdEl", """Rich threshold for electrons. Functor's call operator expects a particle-like object.""") RICH_THRESHOLD_KA = Functor( 'RICH_THRESHOLD_KA', "PID::RichThresholdKa", """Rich threshold for kaons. Functor's call operator expects a particle-like object.""") RICH_THRESHOLD_MU = Functor( 'RICH_THRESHOLD_MU', "PID::RichThresholdMu", """Rich threshold for muons. Functor's call operator expects a particle-like object.""") RICH_THRESHOLD_PI = Functor( 'RICH_THRESHOLD_PI', "PID::RichThresholdPi", """Rich threshold for pions. Functor's call operator expects a particle-like object.""") RICH_THRESHOLD_PR = Functor( 'RICH_THRESHOLD_PR', "PID::RichThresholdPr", """Rich threshold for protons. Functor's call operator expects a particle-like object.""") RICH_THRESHOLD_DE = Functor( 'RICH_THRESHOLD_DE', "PID::RichThresholdDe", """Rich threshold for deuterons. Functor's call operator expects a particle-like object.""") ELECTRONSHOWEREOP = Functor( 'ELECTRONSHOWEREOP', "PID::ElectronShowerEoP", """Electron energy/momentum with track-based cell selection. Functor's call operator expects a particle-like object.""") CLUSTERMATCH_CHI2 = Functor( 'CLUSTERMATCH', "PID::ClusterMatch", """CaloID estimator : 2D chi2 for Track/CaloCluster matching (neutral + charged). Functor's call operator expects a particle-like object.""") ELECTRONMATCH_CHI2 = Functor( 'ELECTRONMATCH', "PID::ElectronMatch", """CaloID estimator : 3D chi2 for Track/CaloHypo(e) matching (charged). Functor's call operator expects a particle-like object.""") BREMHYPOID = Functor( 'BREMHYPOID', "PID::BremHypoID", """All significant bits representation of CellID (32bits), i.e. CellID.all(), for CaloHypo (photon) associated to track for brem recovery 0 is invalid/unavailable (see Detector/Calo/include/Detector/Calo/CaloCellID.h) Functor's call operator expects a particle-like object.""") BREMHYPOMATCH_CHI2 = Functor( 'BREMHYPOMATCH', "PID::BremHypoMatch", """2D chi2 of CaloHypo (photon) associated to track for brem recovery Functor's call operator expects a particle-like object.""") ELECTRONENERGY = Functor( 'ELECTRONENERGY', "PID::ElectronEnergy", """Cluster energy associated to CaloHypo (charged) Functor's call operator expects a particle-like object.""") BREMHYPOENERGY = Functor( 'BREMHYPOENERGY', "PID::BremHypoEnergy", """Energy of CaloHypo (photon) associated to track for brem recovery. Functor's call operator expects a particle-like object.""") BREMHYPODELTAX = Functor( 'BREMHYPODELTAX', "PID::BremHypoDeltaX", """Test statistic of being first-state like of CaloHypo (photon) for brem recovery Functor's call operator expects a particle-like object.""") BREMTRACKBASEDENERGY = Functor( 'BREMTRACKBASEDENERGY', "PID::BremTrackBasedEnergy", """Track-based brem energy determination Functor's call operator expects a particle-like object.""") ELECTRONID = Functor( 'ELECTRONID', "PID::ElectronID", """All significant bits representation of CellID (32bits), i.e. CellID.all(), associated to CaloHypo seed (electron hypo) 0 is invalid/unavailable (see Detector/Calo/include/Detector/Calo/CaloCellID.h) Functor's call operator expects a particle-like object.""") HCALEOP = Functor( 'HCALEOP', "PID::HcalEoP", """Hcal energy deposit over momentum (track) Functor's call operator expects a particle-like object.""") CLUSTERID = Functor( 'CLUSTERID', "PID::ClusterID", """CellID.all() of the best matching cluster for a given reconstructed track. 0 is invalid/unavailable (see Detector/Calo/include/Detector/Calo/CaloCellID.h) Functor's call operator expects a particle-like object.""") ELECTRONSHOWERDLL = Functor( 'ELECTRONSHOWERDLL', "PID::ElectronShowerDLL", """Summed per-cell E/p DLL (electron versus pion) with track-based cell selection and energy estimation. Functor's call operator expects a particle-like object.""") NDOF = Functor('NDOF', 'Track::nDoF', 'Number of degrees of freedom [for chi2]') QOVERP = Functor('QOVERP', 'Track::QoverP', 'q/p') _CHI2DOF = Functor('_CHI2DOF', "Track::Chi2PerDoF", "Vertex or track chi^2 per degree of freedom.") CHI2DOF = setComposedFunctor( VALUE_OR(NaN) @ _CHI2DOF, "CHI2DOF", """Vertex or track chi^2 per degrees of freedom.""") _CHI2 = Functor('_CHI2', "Track::Chi2", "Vertex or track chi^2.") CHI2 = setComposedFunctor( VALUE_OR(NaN) @ _CHI2, "CHI2", """Vertex or track chi^2.""") _GHOSTPROB = Functor('_GHOSTPROB', "Track::GhostProbability", "Ghost probability.") GHOSTPROB = setComposedFunctor( VALUE_OR(NaN) @ _GHOSTPROB @ TRACK, "GHOSTPROB", """Track ghost probability (see :py:func:`~TRACK` for definition). Functor's call operator expects a ChargedBasic""") ### Track Event TRACKTYPE = Functor('TRACKTYPE', "Track::Type", "Track type.") _TRACKHAST = Functor('TRACKHAST', "Track::HasT", "Track has T.") _TRACKHASUT = Functor('TRACKHASUT', "Track::HasUT", "Track has UT.") _TRACKHASVELO = Functor('TRACKHASVELO', "Track::HasVelo", "Track has Velo.") TRACKHAST = setComposedFunctor( _TRACKHAST @ TRACKTYPE, "TRACKHAST", """ Returns True if track has hits in T stations, False otherwise Functor's call operator expects a track-like object. """) TRACKHASUT = setComposedFunctor( _TRACKHASUT @ TRACKTYPE, "TRACKHASUT", """ Returns True if track has hits in UT detector, False otherwise Functor's call operator expects a track-like object. """) TRACKHASVELO = setComposedFunctor( _TRACKHASVELO @ TRACKTYPE, "TRACKHASVELO", """ Returns True if track has hits in Velo, False otherwise Functor's call operator expects a track-like object. """) TRACKISLONG = Functor( "TRACKISLONG", "Track::IsTrackType<LHCb::Event::Enum::Track::Type::Long>", """Track type is Long Functor's call operator expects a track-like object. """) TRACKISDOWNSTREAM = Functor( "TRACKISDOWNSTREAM", "Track::IsTrackType<LHCb::Event::Enum::Track::Type::Downstream>", """Track type is Downstream Functor's call operator expects a track-like object. """) TRACKISUPSTREAM = Functor( "TRACKISUPSTREAM", "Track::IsTrackType<LHCb::Event::Enum::Track::Type::Upstream>", """Track type is Upstream Functor's call operator expects a track-like object. """) TRACKISTTRACK = Functor( "TRACKISTTRACK", "Track::IsTrackType<LHCb::Event::Enum::Track::Type::Ttrack>", """Track type is Ttrack Functor's call operator expects a track-like object. """) TRACKISVELO = Functor( "TRACKISVELO", "Track::IsTrackType<LHCb::Event::Enum::Track::Type::Velo>", """Track type is Velo Functor's call operator expects a track-like object. """) TRACKISVELOBACKWARD = Functor( "TRACKISVELOBACKWARD", "Track::IsTrackType<LHCb::Event::Enum::Track::Type::VeloBackward>", """Track type is VeloBackward Functor's call operator expects a track-like object. """) TRACKFLAG = Functor( 'TRACKFLAG', "Track::Flag", """Track flag. Functor's call operator expects a track-like object. """) TRACKISINVALID = Functor( "TRACKISINVALID", "Track::HasTrackFlag<LHCb::Event::Enum::Track::Flag::Invalid>", """Track flag contains Invalid Functor's call operator expects a track-like object. """) TRACKISCLONE = Functor( "TRACKISCLONE", "Track::HasTrackFlag<LHCb::Event::Enum::Track::Flag::Clone>", """Track flag contains Clone Functor's call operator expects a track-like object. """) TRACKISSELECTED = Functor( "TRACKISSELECTED", "Track::HasTrackFlag<LHCb::Event::Enum::Track::Flag::Selected>", """Track flag contains Selected Functor's call operator expects a track-like object. """) ### Number of hits on track NHITS = Functor( 'NHITS', "Track::nHits", """Track number of hits. Functor's call operator expects a track-like object. """) NVPHITS = Functor( 'NVPHITS', "Track::nVPHits", """Number of VP hits. Functor's call operator expects a track-like object. """) NUTHITS = Functor( 'NUTHITS', "Track::nUTHits", """Number of UT hits. Functor's call operator expects a track-like object. """) NFTHITS = Functor( 'NFTHITS', "Track::nFTHits", """Number of FT hits. Functor's call operator expects a track-like object. """) NPRVELO3DEXPECT = Functor( 'NPRVELO3DEXPECT', "Track::nPRVelo3DExpect", """Number of expected Velo clusters from VELO 3D pattern recognition. Functor's call operator expects a track-like object. """) ### TRACKHISTORY = CAST_TO_INT @ Functor( 'TRACKHISTORY', "Track::History", """Name of the algorithm that made the track. Functor's call operator expects a track-like object. """) # protoparticles... hrmpf... PPHASRICH = Functor( "PPHASRICH", "Particle::PPHasRich", """ProtoParticle has RICH info Functor's call operator expects a protoparticle. Note: FIXME """) PPHASMUONINFO = Functor( "PPHASMUONINFO", "Particle::PPHasMuonInfo", """ProtoParticle has MUON info Functor's call operator expects a protoparticle. """) # generic ALL = Functor('ALL', "AcceptAll", "Accept everything; always evaluates to 'true'.") NONE = Functor('NONE', "AcceptNone", "Accept nothing; always evaluates to 'false'.") IDENTITY = Functor("IDENTITY", "Identity_t", "Returns the same value.") COLUMN = Functor( "COLUMN", "Column_t", "Returns T('label') when acting on T.", Params=[('ColumnLabel', 'label', str)]) SUM = Functor( 'SUM', "Adapters::Accumulate", """Calculate the [scalar] sum of the given functor value. Functor's call operator expects a composite like object.""", Params=[('Functor', 'The functor to accumulate the return value of.', BoundFunctor)]) MIN = Functor( 'MIN', "Adapters::Minimum", """Calculate the minimum of the given functor value. Functor's call operator expects a composite like object.""", Params=[('Functor', 'The functor to find the minimum return value of.', BoundFunctor)]) MAX = Functor( 'MAX', "Adapters::Maximum", """Calculate the maximum of the given functor value. Functor's call operator expects a composite like object.""", Params=[('Functor', 'The functor to find the maximum return value of.', BoundFunctor)]) CHILD = Functor( 'CHILD', "Adapters::Child", """Apply functor on a child. Functor's call operator expects a composite like object.""", Params=[ ('Index', 'The index of the child to apply the functor to (starting from 1).', int), ('Functor', 'The functor to apply on the child.', BoundFunctor), ], AllowMultiplePositionalArguments=True) SUBCOMB = Functor( 'SUBCOMB', "Adapters::SubCombination", """Apply functor on a SubCombination. Functor's call operator expects a composite like object.""", Params=[ ('Functor', 'The functor to apply on the subcombination.', BoundFunctor), ], TemplateParams=[( 'Indices', 'Tuple of indices to build the subcombination from (starting from 1).', template_list_arg_formatter)]) MASSWITHHYPOTHESES = Functor( 'MASSWITHHYPOTHESES', 'Composite::MassWithHypotheses', """Invariant mass of a combined particle given child mass hypotheses. Functor's call operator expects a composite like object.""", Params=[('Masses', 'Masses of the children', tuple)]) MASS = Functor( 'MASS', 'Composite::Mass', """Get the particle (composite or basic) mass. Functor's call operator expects a particle-like object.""") COMB_MASS = setComposedFunctor( MASS @ (FOURMOMENTUM @ FORWARDARG0 + FOURMOMENTUM @ FORWARDARG1), "COMB_MASS", """ Evaluates the invariant mass of the sum of two 4-vectors. Binary functor: Functor's call operator expects two particle-like objects Example: >>> import Functors as F >>> import Functors.math as fmath >>> from Functors.tests.categories import dummy_data_particle_range >>> from GaudiKernel.SystemOfUnits import MeV >>> from PyConf.Algorithms import WeightedRelTableAlg >>> alg = WeightedRelTableAlg( >>> InputCandidates = dummy_data_particle_range, >>> ReferenceParticles = dummy_data_particle_range, >>> Cut = fmath.in_range(500*MeV, F.COMB_MASS, 1000*MeV) >>> alg.OutputRelations DataHandle('/Event/WeightedRelTableAlg/OutputRelations') """) _MTDOCACHI2 = Functor( '_MTDOCACHI2', "Composite::MotherTrajectoryDistanceOfClosestApproachChi2", """Compute the significance of the distance of closest approach between mother and child.""", Params=[('Child', 'Index [starting from 1] of the first child to consider.', int)])
[docs]def MTDOCACHI2(Child: int, Vertices: DataHandle): """ Compute the significance of the distance of closest approach between mother and child. Functor's call operator expects a composite like object Args: Child: the index number (int) of the first child to consider Vertices: DataHandle of the primary vertices """ return _MTDOCACHI2(Child).bind(TES(Vertices), FORWARDARGS)
SDOCA = Functor( 'SDOCA', "Combination::SDistanceOfClosestApproach", """Compute the distance of closest approach between two 'states'.""", Params=[('Child1', 'Index [starting from 1] of the first child to consider.', int), ('Child2', 'Index [starting from 1] of the second child to consider.', int)], AllowMultiplePositionalArguments=True) DOCA = Functor( 'DOCA', "Combination::DistanceOfClosestApproach", """Compute the distance of closest approach between two track-like objects which may need transport over longer distances.""", Params=[('Child1', 'Index [starting from 1] of the first child to consider.', int), ('Child2', 'Index [starting from 1] of the second child to consider.', int)], AllowMultiplePositionalArguments=True) SDOCACHI2 = Functor( 'SDOCACHI2', "Combination::SDistanceOfClosestApproachChi2", """Compute the significance of the distance of closest approach between two 'states'.""", Params=[('Child1', 'Index [starting from 1] of the first child to consider.', int), ('Child2', 'Index [starting from 1] of the second child to consider.', int)], AllowMultiplePositionalArguments=True) DOCACHI2 = Functor( 'DOCACHI2', "Combination::DistanceOfClosestApproachChi2", """Compute the significance of the distance of closest approach between two track-like object which may need transport.""", Params=[('Child1', 'Index [starting from 1] of the first child to consider.', int), ('Child2', 'Index [starting from 1] of the second child to consider.', int)], AllowMultiplePositionalArguments=True) MAXSDOCA = Functor( 'MAXSDOCA', "Combination::MaxSDistanceOfClosestApproach", """Compute the maximum pairwise distance of closest approach between members of a combination.""", Params=[], AllowMultiplePositionalArguments=True) MAXDOCA = Functor( 'MAXDOCA', "Combination::MaxDistanceOfClosestApproach", "Compute the maximum pairwise distance of closest approach between members of a combination using IDistanceCalculator.", Params=[], AllowMultiplePositionalArguments=True) MAXSDOCACHI2 = Functor( 'MAXSDOCACHI2', "Combination::MaxSDistanceOfClosestApproachChi2", "Compute the maximum pairwise significance of the distance of closest approach between members of a combination." ) MAXDOCACHI2 = Functor( 'MAXDOCACHI2', "Combination::MaxDistanceOfClosestApproachChi2", "Compute the maximum pairwise significance of the distance of closest approach, computed using an IDistanceCalculator implementation, between members of a combination." ) MAXSDOCACUT = Functor( 'MAXSDOCACUT', "Combination::MaxSDistanceOfClosestApproachCut", """Cut on the the distance of closest approach between two 'states'.""", Params=[('thresh', 'Threshold for cut', float)]) MAXDOCACUT = Functor( 'MAXDOCACUT', "Combination::MaxDistanceOfClosestApproachCut", """Cut on the the distance of closest approach between two track-like objects which may need transport.""", Params=[('thresh', 'Threshold for cut', float)]) MAXSDOCACHI2CUT = Functor( 'MAXSDOCACHI2CUT', "Combination::MaxSDistanceOfClosestApproachChi2Cut", """Cut on the significance of the distance of closest approach between two 'states'.""", Params=[('thresh', 'Threshold for cut', float)]) MAXDOCACHI2CUT = Functor( 'MAXDOCACHI2CUT', "Combination::MaxDistanceOfClosestApproachChi2Cut", """Cut on the significance of the distance of closest approach between two track-like object which may need transport.""", Params=[('thresh', 'Threshold for cut', float)]) ALV = Functor( 'ALV', "Combination::CosAngleBetweenDecayProducts", """Compute the cosine value of angle between two decay products.""", Params=[('Child1', 'Index [starting from 1] of the first child to consider.', int), ('Child2', 'Index [starting from 1] of the second child to consider.', int)], AllowMultiplePositionalArguments=True) CHARGE = Functor("CHARGE", "Combination::Charge", "Compute the charge") _PID_MU = Functor('_PID_MU', "Track::PIDmu", "CombDLLmu.") _PID_PI = Functor('_PID_PI', "Track::PIDpi", "CombDLLpi.") _PID_K = Functor('_PID_K', "Track::PIDk", "CombDLLk.") _PID_P = Functor('_PID_P', "Track::PIDp", "CombDLLp.") _PID_E = Functor('_PID_E', "Track::PIDe", "CombDLLe.") PID_MU = setComposedFunctor( VALUE_OR(NaN) @ _PID_MU, "PID_MU", """ Gives measure of the muon mass hypothesis relative to the pion hypotesis. It is actually DLL(mu-pi). Likelihood information is produced by each subsistem. General information on PID could be found at the following `TWiki page <https://twiki.cern.ch/twiki/bin/view/LHCbPhysics/ChargedPID>`_ """) PID_PI = setComposedFunctor( VALUE_OR(NaN) @ _PID_PI, "PID_PI", """ CombDLLpi. Should be peaked at zero. General information on PID could be found at the following `TWiki page <https://twiki.cern.ch/twiki/bin/view/LHCbPhysics/ChargedPID>`_ """) PID_K = setComposedFunctor( VALUE_OR(NaN) @ _PID_K, "PID_K", """ Gives measure of the kaon mass hypothesis relative to the pion hypotesis. It is actually DLL(K-pi). Likelihood information is produced by RICH detectors. General information on PID could be found at the following `TWiki page <https://twiki.cern.ch/twiki/bin/view/LHCbPhysics/ChargedPID>`_ """) PID_P = setComposedFunctor( VALUE_OR(NaN) @ _PID_P, "PID_P", """ Gives measure of the proton mass hypothesis relative to the pion hypotesis. It is actually DLL(p-pi). Likelihood information is produced by RICH detectors. General information on PID could be found at the following `TWiki page <https://twiki.cern.ch/twiki/bin/view/LHCbPhysics/ChargedPID>`_ """) PID_E = setComposedFunctor( VALUE_OR(NaN) @ _PID_E, "PID_E", """ Gives measure of the electron mass hypothesis relative to the pion hypotesis. It is actually DLL(e-pi). Likelihood information is produced by each subsistem. General information on PID could be found at the following `TWiki page <https://twiki.cern.ch/twiki/bin/view/LHCbPhysics/ChargedPID>`_ """) _PROBNN_D = Functor('_PROBNN_D', "Track::PROBNN_D_t", "PROBNN_D.") _PROBNN_E = Functor('_PROBNN_E', "Track::PROBNN_E_t", "PROBNN_E.") _PROBNN_GHOST = Functor('_PROBNN_GHOST', "Track::PROBNN_GHOST_t", "PROBNN_GHOST.") _PROBNN_K = Functor('_PROBNN_K', "Track::PROBNN_K_t", "PROBNN_K.") _PROBNN_MU = Functor('_PROBNN_MU', "Track::PROBNN_MU_t", "PROBNN_MU.") _PROBNN_P = Functor('_PROBNN_P', "Track::PROBNN_P_t", "PROBNN_P.") _PROBNN_PI = Functor('_PROBNN_PI', "Track::PROBNN_PI_t", "PROBNN_PI.") PROBNN_D = setComposedFunctor( VALUE_OR(NaN) @ _PROBNN_D, "PROBNN_D", """ MVA technique to establish deuterium mass hypothesis which keep in consideration the correlation between detector systems and includes tracking information. General information on PID could be found at the following `TWiki page <https://twiki.cern.ch/twiki/bin/view/LHCbPhysics/ChargedPID>`_ """) PROBNN_E = setComposedFunctor( VALUE_OR(NaN) @ _PROBNN_E, "PROBNN_E", """ MVA technique to establish electron mass hypothesis which keep in consideration the correlation between detector systems and includes tracking information. General information on PID could be found at the following `TWiki page <https://twiki.cern.ch/twiki/bin/view/LHCbPhysics/ChargedPID>`_ """) PROBNN_GHOST = setComposedFunctor( VALUE_OR(NaN) @ _PROBNN_GHOST, "PROBNN_GHOST", """ MVA technique to establish ghost tracks hypothesis which keep in consideration the correlation between detector systems and includes tracking information. General information on PID could be found at the following `TWiki page <https://twiki.cern.ch/twiki/bin/view/LHCbPhysics/ChargedPID>`_ """) PROBNN_K = setComposedFunctor( VALUE_OR(NaN) @ _PROBNN_K, "PROBNN_K", """ MVA technique to establish kaon mass hypothesis which keep in consideration the correlation between detector systems and includes tracking information. General information on PID could be found at the following `TWiki page <https://twiki.cern.ch/twiki/bin/view/LHCbPhysics/ChargedPID>`_ """) PROBNN_MU = setComposedFunctor( VALUE_OR(NaN) @ _PROBNN_MU, "PROBNN_MU", """ MVA technique to establish muon mass hypothesis which keep in consideration the correlation between detector systems and includes tracking information. General information on PID could be found at the following `TWiki page <https://twiki.cern.ch/twiki/bin/view/LHCbPhysics/ChargedPID>`_ """) PROBNN_P = setComposedFunctor( VALUE_OR(NaN) @ _PROBNN_P, "PROBNN_P", """ MVA technique to establish proton mass hypothesis which keep in consideration the correlation between detector systems and includes tracking information. General information on PID could be found at the following `TWiki page <https://twiki.cern.ch/twiki/bin/view/LHCbPhysics/ChargedPID>`_ """) PROBNN_PI = setComposedFunctor( VALUE_OR(NaN) @ _PROBNN_PI, "PROBNN_PI", """ MVA technique to establish pion mass hypothesis which keep in consideration the correlation between detector systems and includes tracking information. General information on PID could be found at the following `TWiki page <https://twiki.cern.ch/twiki/bin/view/LHCbPhysics/ChargedPID>`_ """) _BPVCORRM = Functor( '_BPVCORRM', 'Composite::CorrectedMass', 'Compute the corrected mass of the composite using the associated [primary] vertex.' ) _BPVCORRMERR = Functor( '_BPVCORRMERR', 'Composite::CorrectedMassError', 'Compute the corrected mass error of the composite using the best PV.')
[docs]def BPVCORRM(Vertices: DataHandle = None): """ Compute the corrected mass of the composite using the :py:func:`~BPV`. Functor's call operator expects a composite like object Args: Vertices: DataHandle of the primary vertices """ return _BPVCORRM.bind(BPV(Vertices), FORWARDARGS)
[docs]def BPVCORRMERR(Vertices: DataHandle = None): """ Compute the corrected mass error of the composite using the :py:func:`~BPV`. Functor's call operator expects a composite like object Args: Vertices: DataHandle of the primary vertices """ return _BPVCORRMERR.bind(BPV(Vertices), FORWARDARGS)
[docs]def BTRACKING_TRACK(HeavyFlavourTrackRelations: DataHandle): """ Returns heavy flavour track object associated to composite. Functor's call operator expects a composite like object Args: HeavyFlavourTrackRelations: DataHandle of relations of composite to heavy flavour track """ _BTRACKING_TRACK = Functor('BTRACKING_TRACK', 'Composite::BTracking::Track', 'Heavy flavour track associated to composite.') return _BTRACKING_TRACK.bind(TES(HeavyFlavourTrackRelations), FORWARDARGS)
[docs]def BTRACKING_NHITS(HeavyFlavourTrackRelations: DataHandle): """ Number of hits on heavy flavour track. Functor's call operator expects a composite like object Args: HeavyFlavourTrackRelations: DataHandle of relations of composite to heavy flavour track """ return NHITS @ BTRACKING_TRACK(HeavyFlavourTrackRelations)
[docs]def BTRACKING_NPRVELO3DEXPECT(HeavyFlavourTrackRelations: DataHandle): """ Number of crossed VELO sensors according to pattern recognition window. Functor's call operator expects a composite like object Args: HeavyFlavourTrackRelations: DataHandle of relations of composite to heavy flavour track """ return NPRVELO3DEXPECT @ BTRACKING_TRACK(HeavyFlavourTrackRelations)
[docs]def BTRACKING_BPVCORRM(HeavyFlavourTrackRelations: DataHandle): """ Compute the corrected mass of the composite using the associated heavy flavour track. Functor's call operator expects a composite like object Args: HeavyFlavourTrackRelations: DataHandle of relations of composite to heavy flavour track """ _BTRACKING_BPVCORRM = Functor( 'BTRACKING_BPVCORRM', 'Composite::BTracking::CorrectedMass', 'Compute the corrected mass of the composite using the associated heavy flavour track.' ) return _BTRACKING_BPVCORRM.bind( TES(HeavyFlavourTrackRelations), FORWARDARGS)
VTX_FDCHI2 = Functor( 'VTX_FDCHI2', 'Composite::FlightDistanceChi2ToVertex', '''Return the flight distance chi2 w.r.t. the given vertex. The first implicit argument type is a vertex.''' )
[docs]def BPVFDCHI2(Vertices: DataHandle = None): """ FDCHI2 with respect to the :py:func:`~BPV` Functor's call operator expects a particle-like object Args: Vertices: DataHandle of the primary vertices """ return VTX_FDCHI2.bind(BPV(Vertices), FORWARDARGS)
VTX_LTIME = Functor( 'VTX_LTIME', 'Composite::Lifetime', '''Return the particle lifetime w.r.t. the given vertex.''')
[docs]def BPVLTIME(Vertices: DataHandle = None): """ Lifetime with respect to the :py:func:`~BPV` Functor's call operator expects a particle-like object Args: Vertices: DataHandle of the primary vertices """ return VTX_LTIME.bind(BPV(Vertices), FORWARDARGS)
VTX_DLS = Functor( 'BPVDLS', 'Composite::ComputeDecayLengthSignificance', '''Return the decay length significance w.r.t. the given vertex.''')
[docs]def BPVDLS(Vertices: DataHandle = None): """ Decay length with respect to the :py:func:`~BPV` Functor's call operator expects a particle-like object Args: Vertices: DataHandle of the primary vertices """ return VTX_DLS.bind(BPV(Vertices), FORWARDARGS)
_RECSUMMARY_INFO = Functor( 'RECSUMMARY_INFO', 'TES::RecSummaryInfo', '''Return information stored in LHCb::RecSummary.DataType''', Params= [('DataType', 'Type of information to be returned (see LHCb::RecSummary::DataTypes in RecSummary.h).', int)])
[docs]def RECSUMMARY_INFO(rec_summary: DataHandle, DataType: Union[str, int]): """ Extracts DataType information from LHCb::RecSummary.DataType Args: rec_summary: DataHandle of the LHCb::RecSummary DataType: Name or enum of datatype as defined in https://gitlab.cern.ch/lhcb/LHCb/-/blob/master/Event/RecEvent/include/Event/RecSummary.h """ # Workaround for cppyy warning with ROOT-10769 # (see https://gitlab.cern.ch:8443/lhcb/LHCb/-/merge_requests/2637) import warnings with warnings.catch_warnings(): warnings.simplefilter("ignore") from cppyy.gbl import LHCb if isinstance(DataType, int): # or maybe check directly for enum type? if DataType == LHCb.RecSummary.TypeUnknown: raise ValueError("RecSummary type unknown") return _RECSUMMARY_INFO(DataType) @ TES(rec_summary) elif isinstance(DataType, str): if LHCb.RecSummary.DataTypesToType( DataType) == LHCb.RecSummary.TypeUnknown: raise ValueError("RecSummary type unknown") return _RECSUMMARY_INFO( LHCb.RecSummary.DataTypesToType(DataType)) @ TES(rec_summary) else: raise TypeError("RECSUMMARY_INFO expects string or enum value")
[docs]def RUNNUMBER(odin: DataHandle): """ Extracts run number from ODIN Functor's call operator expects no input. Args: odin: DataHandle of the odin bank """ return Functor('RUNNUMBER', 'TES::RunNumber', '''Return the run number from ODIN.''') @ TES(odin)
[docs]def EVENTNUMBER(odin: DataHandle): """ Extracts event number from ODIN Functor's call operator expects no input. Args: odin: DataHandle of the odin bank """ return Functor('EVENTNUMBER', 'TES::EventNumber', '''Return the event number from ODIN.''') @ TES(odin)
[docs]def EVENTTYPE(odin: DataHandle): """ Extracts event type from ODIN Functor's call operator expects no input. Args: odin: DataHandle of the odin bank """ return Functor('EVENTTYPE', 'TES::EventType', '''Return the event type from ODIN.''') @ TES(odin)
[docs]def BUNCHCROSSING_ID(odin: DataHandle): """ Extracts bunch crossing id from ODIN Functor's call operator expects no input. Args: odin: DataHandle of the odin bank """ return Functor('BUNCHCROSSING_ID', 'TES::BunchCrossingID', '''Return the bunch crossing ID from ODIN.''') @ TES(odin)
[docs]def BUNCHCROSSING_TYPE(odin: DataHandle): """ Extracts bunch crossing type from ODIN Functor's call operator expects no input. Args: odin: DataHandle of the odin bank """ return Functor('BUNCHCROSSING_TYPE', 'TES::BunchCrossingType', '''Return the bunch crossing type from ODIN.''') @ TES(odin)
[docs]def ODINTCK(odin: DataHandle): """ Extracts ODIN TCK from ODIN Functor's call operator expects no input. Args: odin: DataHandle of the odin bank """ return Functor( 'ODINTCK', 'TES::OdinTCK', '''Return the trigger configuration key from ODIN.''') @ TES(odin)
[docs]def GPSTIME(odin: DataHandle): """ Extracts gps time from ODIN Functor's call operator expects no input. Args: odin: DataHandle of the odin bank """ return Functor('GPSTIME', 'TES::GpsTime', '''Return the GPS time from ODIN.''') @ TES(odin)
[docs]def TCK(DecReports: DataHandle): """ Extracts TCK from selection DecReports Functor's call operator expects no input. Args: DecReports: DataHandle of the DecReports """ _SELECTION_TCK = Functor( 'SELECTION_TCK', 'TES::SelectionTCK', '''Return the trigger configuration key (TCK) from selection DecReports.''' ) return _SELECTION_TCK @ TES(DecReports)
[docs]def DECISION(DecReports: DataHandle, trigger_line_name: str): """ Extract HLT event decision with respect to a given trigger line using selection DecReports Functor's call operator expects no input. Args: trigger_line_name: Name of the trigger line DecReports: DataHandle of the DecReports """ _SELECTION_DECISION = Functor( 'SELECTION_DECISION', "TES::SelectionDecision", "Return the decision of a given trigger line from selection DecReports.", Params=[('Line', "Line name of which the decision is returned.", str)]) return VALUE_OR(False) @ _SELECTION_DECISION(trigger_line_name) @ TES( DecReports)
[docs]def DECREPORTS_FILTER(DecReports: DataHandle, Lines: List[str]): """ Filter events depending on DecReports decision Functor's call operator expects no input. Args: DecReports: DataHandle of the DecReports Lines: List of line names """ _DECREPORTS_FILTER = Functor( '_DECREPORTS_FILTER', "TES::DecReportsFilter", "Filter events depending on DecReports decision", Params= [('Lines', "List of selection line names of which at least one must be accepted.", list)]) return _DECREPORTS_FILTER(Lines) @ TES(DecReports)
[docs]def DECREPORTS_RE_FILTER(DecReports: DataHandle, Regex: str): """ Filter events depending on DecReports decision Functor's call operator expects no input. Args: DecReports: DataHandle of the DecReports Regex: regex to apply to line names """ _DECREPORTS_RE_FILTER = Functor( '_DECREPORTS_RE_FILTER', "TES::DecReportsRegExFilter", "Filter events depending on DecReports decision", Params= [('Regex', "Regex which selects line names of which at least one must be accepted.", str)]) return _DECREPORTS_RE_FILTER(Regex) @ TES(DecReports)
# Examples: Ex_TimesTwo = Functor('TIMESTWO', 'Examples::TimesTwo', ''' calculate the double ''') Ex_PlusN = Functor( 'PLUSN', 'Examples::PlusN', ''' Add user specified value(int) ''', Params=[('n', 'value to add to input', int)]) Ex_GreaterThan = Functor( 'GREATERTHAN', 'Examples::GreaterThan', ''' value greater than v? ''', Params=[('v', 'reference value', float)]) Ex_TBL = Functor('TBL', 'Examples::ThorBeatsLoki', ''' ... ''') def mva_input_formatter(*, is_config: bool): from Functors.grammar import python_to_cpp_str def _mva_input_formatter(dictionary): if not is_config: mva_inputs = [] # Data dependencies inputs = [] for key, val in list(dictionary.items()): assert type(key) == str key_code = python_to_cpp_str(key) val_code = python_to_cpp_str(val) mva_inputs.append('MVAInput( ' + key_code + ', ' + val_code + ' )') inputs += val.data_dependencies() return ', '.join(mva_inputs), inputs else: items = [] for key, val in list(dictionary.items()): key_code = python_to_cpp_str(key) val_code = python_to_cpp_str(val) items.append('{ ' + key_code + ', ' + val_code + ' }') return '{' + ', '.join(items) + '}', [] return _mva_input_formatter def mva_impl_formatter(config): return 'Sel::' + config MVA = Functor( 'MVA', 'MVA', '''Evaluate an MVA.''', Params=[('Config', 'MVA config', dict, mva_input_formatter(is_config=True)), ('Inputs', 'MVA inputs', dict, mva_input_formatter(is_config=False))], TemplateParams=[('MVAType', 'The MVA implementation to use', mva_impl_formatter)]) def comb_locations_formatter(locations): from Functors.grammar import python_to_cpp_str expressions, inputs = [], [], [] for loc in locations: # The functor framework is unable to introspect type requirements of # composites, e.g. 'list-of-DataHandle', only 'list'. We enforce the # list-of-DataHandle type requirement of the COMB functor here instead if not isinstance(loc, DataHandle): raise TypeError( "COMB Functor only accepts DataHandle but received: " + str(loc) + " of type " + str(type(loc))) code = python_to_cpp_str(loc) expressions.append(code) inputs.append(loc) return ', '.join(expressions), inputs def comb_types_formatter(type_tuple): return ', '.join([x[0] for x in type_tuple]) GET_ALL_BASICS = Functor( 'GET_ALL_BASICS', 'Adapters::BasicsFromCompositeV1', """Returns all basic particles. Functor's call operator expects a composite like object. Note: If the functor is applied to a basic particle, it will throw an exception.""", ) GET_ALL_DESCENDANTS = Functor( 'GET_ALL_DESCENDANTS', 'Adapters::DescendantsFromCompositeV1', """Returns all descendants. The descendants include intermediate (composite) and final (basic) states. Functor's call operator expects a composite like object. Note: If the functor is applied to a basic particle, it will throw an exception.""", ) GET_GENERATION = Functor( 'GET_GENERATION', "Adapters::GenerationFromCompositeV1", """Returns all descendants belonging to a given generation. Functor's call operator expects a composite like object. Note: If the functor is applied to a basic particle, it will throw an exception. """, Params= [('Generation', 'The generation of the children. Generation 1 are direct children, Generation 2 are grandchildren and so on.', int)]) GET_CHILDREN = setComposedFunctor( GET_GENERATION(Generation=1), "GET_CHILDREN", """Get the first generation of descendants (see :py:func:`~GET_GENERATION` for definition). Functor's call operator expects a composite like object.""") GET_GRANDCHILDREN = setComposedFunctor( GET_GENERATION(Generation=2), "GET_GRANDCHILDREN", """Get the second generation of descendants (see :py:func:`~GET_GENERATION` for definition). Functor's call operator expects a composite like object.""") COMB_FROM_COMP = Functor( 'COMB_FROM_COMP', 'Adapters::CombinationFromComposite', """Re-constructs a 'combination' object from a 'composite' object and returns the result of applying the given functor to that 'combination' object. Functor's call operator expects a composite like object.""", Params=[('Functor', "The functor to apply to the 'combination' object.", BoundFunctor)])
[docs]def COMB(Functor: BoundFunctor, ChildContainers: Union[DataHandle, List[DataHandle]]) -> BoundFunctor: """Re-constructs a 'combination' object from a 'composite' object and returns the result of applying the given functor to that 'combination' object. Functor's call operator expects a composite like object. Args: Functor: The functor to apply to the constructed combination ChildContainers: Datahandles of child containers """ return COMB_FROM_COMP(Functor).bind(FORWARDARGS, TES(ChildContainers))
POD = Functor( 'POD', 'Adapters::ConvertToPOD', 'Try to convert an object representing a scalar number into a plain C++ type. For example, convert SIMDWrapper::scalar::float_v to float.', Params=[('Functor', 'The functor to convert the return value of.', BoundFunctor)]) PARTICLE_ID = Functor('PARTICLE_ID', 'Simulation::Particle_Id', "Particle ID of a Particle or MCParticle.") OBJECT_KEY = Functor('OBJECT_KEY', 'TES::ObjectKey', "Key of the KeyedObject.") RELATIONS = Functor( 'RELATIONS', 'Common::Relations', "Given a relation table, return the set of relations contained") TO = Functor('TO', 'Common::To', "Given a relation, return the TO side") WEIGHT = Functor('WEIGHT', 'Common::Weight', "Given a relation, return the WEIGHT side")
[docs]def MAP_INPUT(Functor: BoundFunctor, Relations: DataHandle) -> BoundFunctor: """Map the input object to the related object (via relations table) and apply functor to it. Args: Functor: The functor to apply to the particle Relations: Datahandle of the relations table """ return Functor @ MAP_TO_RELATED(Relations)
_BKGCAT = Functor('_BKGCAT', 'Simulation::Category', '''Background category of composite particle.''')
[docs]def BKGCAT(Relations: DataHandle) -> BoundFunctor: """Background category of composite particle. Args: Relations: DataHandle with the relations table Note: If no relations are present, value of -1 is returned To understand the meaning of the background categories, please have a look at the following `TWiki page <https://twiki.cern.ch/twiki/bin/view/LHCb/TupleToolMCBackgroundInfo>`_ """ return VALUE_OR(-1) @ MAP_INPUT(Functor=_BKGCAT, Relations=Relations)
[docs]def MAP_INPUT_ARRAY(Functor: BoundFunctor, Relations: DataHandle) -> BoundFunctor: """Create a map with the relations between the input candidate and a vector of output particles. Args: Functor: The functor to apply to the particle """ return MAP(Functor @ TO) @ RELATIONS.bind(TES(Relations), FORWARDARGS)
[docs]def MAP_INPUT_SIZE(Relations: DataHandle) -> BoundFunctor: """Return the size of mapped object Args: Relations: Datahandle of the relations table """ return SIZE_OF @ RELATIONS.bind(TES(Relations), FORWARDARGS)
[docs]def MAP_WEIGHT(Relations: DataHandle) -> BoundFunctor: """Map the input object to the weights of related objects via relations table. Args: Relations: Datahandle of the relations table """ return MAP(WEIGHT) @ RELATIONS.bind(TES(Relations), FORWARDARGS)
SUM_RANGE = Functor('SUM_RANGE', 'Functional::Sum', 'Return the sum of a range of values') REVERSE_RANGE = Functor('REVERSE_RANGE', 'Functional::Reverse', 'Return the reversed range')
[docs]def SUMCONE(Functor: BoundFunctor, Relations: DataHandle) -> BoundFunctor: """Evaluates the sum of the results of the application of the functor to each particle on the TO side of the table Args: Functor: The functor to apply to all the related particles Relations: DataHandle with the relation table Returns: The sum of the mapped functor """ return SUM_RANGE @ MAP_INPUT_ARRAY(Functor=Functor, Relations=Relations)
[docs]def MINCONE(Functor: BoundFunctor, Relations: DataHandle) -> BoundFunctor: """Evaluates the minimum element of the results of the application of the functor to each particle on the TO side of the table Args: Functor: The functor to apply to all the related particles Relations: DataHandle with the relation table Returns: The min of the mapped functor """ return MIN_ELEMENT @ MAP_INPUT_ARRAY(Functor=Functor, Relations=Relations)
[docs]def MAXCONE(Functor: BoundFunctor, Relations: DataHandle) -> BoundFunctor: """Evaluates the maximum element of the results of the application of the functor to each particle on the TO side of the table Args: Functor: The functor to apply to all the related particles Relations: DataHandle with the relation table Returns: The max of the mapped functor """ return MAX_ELEMENT @ MAP_INPUT_ARRAY(Functor=Functor, Relations=Relations)
[docs]def ASYM(Functor: BoundFunctor, Relations: DataHandle) -> BoundFunctor: """Evaluates the asymmetry value between the application of the functor on the reference particle and the sum of the results of the application of the functor to each related particle Args: Functor: The functor to apply to all the particles in the TO side of the table Relations: DataHandle with the relation table Returns: The value of the asymmetry, defined as (x-SUMCONE(x))/(x+SUMCONE(x)), with x as Functor """ return ( Functor - VALUE_OR(0.) @ SUMCONE(Functor=Functor, Relations=Relations) ) / ( Functor + VALUE_OR(0.) @ SUMCONE(Functor=Functor, Relations=Relations))
_MC_MOTHER = Functor('_MC_MOTHER', "Simulation::MC::Mother", "Retrieve the parent MCParticle.")
[docs]def SMALLEST_DELTACHI2(Relations: DataHandle) -> BoundFunctor: """Evaluates the smallest delta chi2, defined as the absolute difference of the chi2 of the related particle and the reference particle given a relation table Args: Relations: DataHandle to the relation table that maps a "reference" particle to several "related" particles. Returns: The value of the smallest delta chi2 """ VCHI2_EXTRA = CHI2 @ TO @ FORWARDARG0 VCHI2_REF = CHI2 @ FORWARDARG1 DELTACHI2 = ABS @ (VCHI2_EXTRA - VCHI2_REF) return MIN_ELEMENT @ MAP(DELTACHI2).bind( RELATIONS.bind(TES(Relations), FORWARDARGS), FORWARDARGS)
[docs]def PARTICLE_PROPERTY_WITH_SMALLEST_DELTACHI2( Functor: BoundFunctor, Relations: DataHandle) -> BoundFunctor: """Evaluates the particle property express by the functor of the related particle with the smallest delta chi2, defined as the absolute difference of the chi2 of the related particle and the reference one given a relation table Args: Functor: BoundFunctor to apply to the related particle in the relation table giving the smallest delta chi2 Relations: DataHandle with the relation table Returns: The particle property of the "related" particle with the smallest delta chi2 """ VCHI2_EXTRA = CHI2 @ TO @ FORWARDARG0 VCHI2_REF = CHI2 @ FORWARDARG1 DELTACHI2 = ABS @ (VCHI2_EXTRA - VCHI2_REF) return Functor @ TO @ ENTRY_WITH_MIN_REL_VALUE_OF(DELTACHI2).bind( RELATIONS.bind(TES(Relations), FORWARDARGS), FORWARDARGS)
[docs]def MC_MOTHER(Generation: int, Functor: BoundFunctor): """Apply functor on mother. Functor's call operator expects a MCParticle. Args: Generation (int): The generation of the mother. Generation 1 is simply Mother, Generation 2 is Grandmother and so on. Functor (BoundFunctor): The functor to apply on the mother. Returns: BoundFunctor: Composite functor that apply certain functor on the mother of an MCParticle. """ if Generation < 1: raise ValueError("Wrong index. Indexing for Mother starts at 1") result = Functor for idx in range(Generation): result = result @ _MC_MOTHER return result
_MC_ALLPVS = Functor("_MCH_ALLPVS", "Simulation::MCHeader::AllPVs", "Get all MC primary vertices from MC Header.")
[docs]def MC_ALLPVS(mc_header: DataHandle): """Return all MC primary vertices from MC Header Args: mc_header (DataHandle): The MC header Returns: all MC primary vertices """ return _MC_ALLPVS.bind(TES(mc_header))
_MC_EVTTIME = Functor("_MCH_EVTTIME", "Simulation::MCHeader::AllPVs", "Return event time from MC Header.")
[docs]def MC_EVTTIME(mc_header: DataHandle): """Return event time from MC Header Args: mc_header (DataHandle): The MC header Returns: event time from MC Header """ return _MC_EVTTIME.bind(TES(mc_header))
_MC_EVTNUMBER = Functor("_MCH_EVTNUMBER", "Simulation::MCHeader::AllPVs", "Return event number from MC Header.")
[docs]def MC_EVTNUMBER(mc_header: DataHandle): """Return event number from MC Header Args: mc_header (DataHandle): The MC header Returns: event number from MC Header """ return _MC_EVTNUMBER.bind(TES(mc_header))
MC_FIRST_LONGLIVED_ANCESTOR = Functor( "MC_FIRST_LONGLIVED_ANCESTOR", "Simulation::MC::FirstLongLivedAncestor", """Get the first longlived ancestor. Functor's call operator expects a MCParticle.""", Params=[('MinLifetime', 'minimum lifetime of long-lived particles (ns)', float)])
[docs]def MC_ISPROMPT(max_lifetime=1e-7 * SystemOfUnits.ns): """Determine whenever a decay originates from prompt charm based on the true lifetime of its ancestors. Functor's call operator expects a MCParticle. Args: max_lifetime (float): maximum lifetime of short-lived particles (ns). Defaults to 1e-7 ns. """ return ~(HAS_VALUE @ MC_FIRST_LONGLIVED_ANCESTOR(max_lifetime))
MC_ORIGINFLAG = Functor("MC_ORIGINFLAG", "Simulation::MC::OriginFlag", "Get the true origin type of a tagging MCParticle.") MC_ORIGINVERTEX = Functor("MC_ORIGINVERTEX", "Simulation::MC::OriginVertex", "Get the origin vertex of a MCParticle.") MC_PRIMARYVERTEX = Functor("MC_PRIMARYVERTEX", "Simulation::MC::PrimaryVertex", "Get the primary vertex of a MCParticle.") ORIGIN_VX = setComposedFunctor( X_COORDINATE @ POSITION @ MC_ORIGINVERTEX, 'ORIGIN_VX', 'Get the x position of the origin vertex of a MCParticle.') ORIGIN_VY = setComposedFunctor( Y_COORDINATE @ POSITION @ MC_ORIGINVERTEX, 'ORIGIN_VY', 'Get the y position of the origin vertex of a MCParticle.') ORIGIN_VZ = setComposedFunctor( Z_COORDINATE @ POSITION @ MC_ORIGINVERTEX, 'ORIGIN_VZ', 'Get the z position of the origin vertex of a MCParticle.') _MC_LIFETIME = Functor("_MC_LIFETIME", "Simulation::MC::LifeTime", "Get the lifetime of a MCParticle.") MC_LIFETIME = setComposedFunctor( VALUE_OR(NaN) @ _MC_LIFETIME, 'MC_LIFETIME', 'Get the lifetime of a MCParticle.') MC_VTX_TIME = Functor("MC_VTX_TIME", "Simulation::MCVertex::Time", "Get the time of a MCVertex.") _MC_VTX_TYPE = Functor("_MC_VTX_TYPE", "Simulation::MCVertex::Type", "Get the type of a MCVertex.") MC_PV_VX = setComposedFunctor( X_COORDINATE @ POSITION @ MC_PRIMARYVERTEX, 'MC_PV_VX', 'Get the (true) x position of the primary vertex of a MCParticle.') MC_PV_VY = setComposedFunctor( Y_COORDINATE @ POSITION @ MC_PRIMARYVERTEX, 'MC_PV_VY', 'Get the (true) y position of the primary vertex of a MCParticle.') MC_PV_VZ = setComposedFunctor( Z_COORDINATE @ POSITION @ MC_PRIMARYVERTEX, 'MC_PV_VZ', 'Get the (true) z position of the primary vertex of a MCParticle.') MC_VTX_TYPE = setComposedFunctor( CAST_TO_INT @ _MC_VTX_TYPE, 'MC_VTX_TYPE', ''' Get the type code of a MCVertex, the type code is defined as following: | Type | Code | | ----------------------- | ---- | | Unknown | 0 | | ppCollision | 1 | | DecayVertex | 2 | | OscillatedAndDecay | 3 | | StringFragmentation | 4 | | HadronicInteraction | 100 | | Bremsstrahlung | 101 | | PairProduction | 102 | | Compton | 103 | | DeltaRay | 104 | | PhotoElectric | 105 | | Annihilation | 106 | | RICHPhotoElectric | 107 | | Cerenkov | 108 | | RichHpdBackScat | 109 | | GenericInteraction | 110 | | LHCHalo | 200 | | MuonBackground | 300 | | MuonBackgroundFlat | 301 | | MuonBackgroundSpillover | 302 | | WorldLimit | 400 | | KinematicLimit | 401 | ''') MC_VTX_ISDECAY = Functor("MC_VTX_ISDECAY", "Simulation::MCVertex::IsDecay", "Returns true if the MCVertex is a primary vertex.") MC_VTX_ISPRIMARY = Functor("MC_VTX_ISPRIMARY", "Simulation::MCVertex::IsPrimary", "Returns true if the MCVertex is a decay vertex.") MC_VTX_PRODUCTS = Functor("MC_VTX_PRODUCTS", "Simulation::MCVertex::Products", "Get all decay products of a MCVertex.") IS_PHOTON = Functor( 'IS_PHOTON', "Neutral::IsPhoton_t", """Gamma/Pi0 separation variable (neutral) Functor's call operator expects an LHCb::Particle or ProtoParticle. Note: Functor will return -1000 if protoparticle doesn't have a NeutralPID object.""" ) IS_NOT_H = Functor( 'IS_NOT_H', "Neutral::IsNotH_t", """MLP-based neutralID - anti-hadron ID Functor's call operator expects an LHCb::Particle or ProtoParticle. Note: Functor will return -1000 if protoparticle doesn't have a NeutralPID object.""" ) CALO_NEUTRAL_SHOWER_SHAPE = Functor( 'CALO_NEUTRAL_SHOWER_SHAPE', "Neutral::ShowerShape_t", """CaloID estimator: 2nd order moment of the cluster. Return the square of the width of the shower/cluster in the transverse plane Functor's call operator expects an LHCb::Particle or ProtoParticle. Note: Functor will return -1000 if protoparticle doesn't have a NeutralPID object.""" ) CALO_NEUTRAL_1TO9_ENERGY_RATIO = Functor( 'CALO_NEUTRAL_1TO9_ENERGY_RATIO', "Neutral::NeutralE19_t", """Fraction of highest E cell (seed) to 9 (3x3) cells forming the cluster. Functor's call operator expects an LHCb::Particle or ProtoParticle. Note: Functor will return -1000 if protoparticle doesn't have a NeutralPID object.""" ) CALO_NEUTRAL_4TO9_ENERGY_RATIO = Functor( 'CALO_NEUTRAL_4TO9_ENERGY_RATIO', "Neutral::NeutralE49_t", """Fraction of highest 2x2 cell (seed) to 9 (3x3) cells forming the cluster. Functor's call operator expects an LHCb::Particle or ProtoParticle. Note: Functor will return -1000 if protoparticle doesn't have a NeutralPID object.""" ) CALO_NEUTRAL_ID = Functor( 'CALO_NEUTRAL_ID', "Neutral::NeutralID_t", """Retrieve bitwise information (32bits) of all CALO neutral seed CellIDs. 0 is invalid/unavailable (see Detector/Calo/include/Detector/Calo/CaloCellID.h) Functor's call operator expects an LHCb::Particle or ProtoParticle.""") CALO_NEUTRAL_ECAL_ENERGY = Functor( 'CALO_NEUTRAL_ECAL_ENERGY', "Neutral::NeutralEcal_t", """Retrieve the ECAL cluster energy associated to the neutral CaloHypo. Functor's call operator expects an LHCb::Particle or ProtoParticle. Note: Functor will return -1000 if protoparticle doesn't have a NeutralPID object.""" ) CALO_NEUTRAL_HCAL2ECAL_ENERGY_RATIO = Functor( 'CALO_NEUTRAL_HCAL2ECAL_ENERGY_RATIO', "Neutral::NeutralHcal2Ecal_t", """Retrieve the HCAL/ECAL energy ratio associated to the neutral CaloHypo, usually used to compute neutral PID. Functor's call operator expects an LHCb::Particle or ProtoParticle. Note: Functor will return -1000 if protoparticle doesn't have a NeutralPID object.""" ) CALO_CLUSTER_MASS = Functor( 'CALO_CLUSTER_MASS', "Neutral::ClusterMass_t", """Retrieve the CALO cluster mass obtained from MergedPi0Alg. Functor's call operator expects an LHCb::Particle or ProtoParticle. Note: Functor will return -1000 if protoparticle doesn't have a NeutralPID object.""" ) INT_CALO_NUM_SATURATED_CELLS = Functor( 'CALO_NUM_SATURATED_CELLS', "Neutral::Saturation_t", """Retrieve the number of saturated cells. Functor's call operator expects LHCb::Particle or ProtoParticle. Note: Since the return is an int, it is necessary to add a custom invalid_value through F.VALUE_OR(invalid_value) @.... Can be done manually in each usage or with below functor CALO_NUM_SATURATED_CELLS.""" ) CALO_NUM_SATURATED_CELLS = VALUE_OR(-1000) @ INT_CALO_NUM_SATURATED_CELLS PARTICLE_PROPERTY = Functor( 'PARTICLE_PROPERTY', 'Particle::ParticlePropertyUser', """Get the particle properties of the specific ID (string representation) Functor's call operator expects no input""", Params=[('particle_name', 'ID to check', str)])
[docs]def IS_ID(particle_name: str): ''' Check if particle ID matches the specific ID (string representation, e.g. IS_ID("pi+") ). For reference have a look at :py:func:`~PARTICLE_PROPERTY` It expect a particle-like object as input Args: particle_name: string representation of the particle ID ''' return (PARTICLE_ID @ PARTICLE_PROPERTY(particle_name) == PARTICLE_ID)
[docs]def IS_ABS_ID(particle_name: str): ''' Check if particle ABSID matches the specific abs(ID) (string representation). Both are compared by the absolute values, e.g. IS_ABS_ID("pi+") is equivalent to IS_ABS_ID("pi-") For reference have a look at :py:func:`~PARTICLE_PROPERTY` It expects a particle-like object as input Args: particle_name: string representation of the particle ID ''' return (ABS @ PARTICLE_ID @ PARTICLE_PROPERTY(particle_name) == ABS
[docs] @ PARTICLE_ID)
def PDG_MASS(particle_name: str): ''' Get the PDG mass given the specific ID (string representation), e.g. PDG_MASS("pi+") For reference have a look at :py:func:`~PARTICLE_PROPERTY` It does not expects input Args: particle_name: string representation of the particle ID ''' return MASS @ PARTICLE_PROPERTY(particle_name)
[docs]def SIGNED_DELTA_MASS(particle_name: str): ''' Get the signed difference between the reconstructed and the PDG mass (for reference see :py:func:`~PDG_MASS`) It expects a particle-like object as input. Args: particle_name: string representation of the particle ID ''' return MASS - PDG_MASS(particle_name)
[docs]def ABS_DELTA_MASS(particle_name: str): ''' Get the absolute value of the difference between the reconstructed and the PDG mass (for reference see :py:func:`~PDG_MASS`), e.g. ABS_DELTA_MASS("J/psi(1S)") < 10.*MeV It expects a particle-like object as input. Args: particle_name: string representation of the particle ID ''' return ABS @ SIGNED_DELTA_MASS(particle_name)
MAP = Functor( 'MAP', "Functional::Map", '''Map a functor over a range''', Params=[('Functor', 'The functor to map over a range.', BoundFunctor)]) MAP_ANY_OF = Functor( 'MAP_ANY_OF', "Functional::MapAnyOf", '''Map a predicate over range, early stopping if one value is true''', Params=[('Functor', 'The predicate functor to map over a range.', BoundFunctor)]) MAP_ALL_OF = Functor( 'MAP_ALL_OF', "Functional::MapAllOf", '''Map a predicate over range, early stopping if one value is false''', Params=[('Functor', 'The predicate functor to map over a range.', BoundFunctor)]) FRONT = Functor('FRONT', "Functional::Front", "Front element of range") BACK = Functor('BACK', "Functional::Back", "Back element of range") MIN_ELEMENT = Functor('MIN_ELEMENT', "Functional::Min", "Miniumum element of range") MAX_ELEMENT = Functor('MAX_ELEMENT', "Functional::Max", "Maximum element of range") ENTRY_WITH_MIN_REL_VALUE_OF = Functor( 'ENTRY_WITH_MIN_REL_VALUE_OF', 'Functional::EntryWithMinRelatedValueOf', "Return an entry in the list which corresponds to the minimum value of the functor. If X is the original list and F(X) is the result of the functor F, this returns element x for which F(X) is a minimum i.e. x = argmin F(X)", Params=[('Functor', 'The functor to apply for the evaluation of the min.', BoundFunctor)]) ENTRY_WITH_MAX_REL_VALUE_OF = Functor( 'ENTRY_WITH_MAX_REL_VALUE_OF', 'Functional::EntryWithMaxRelatedValueOf', "Return an entry in the list which corresponds to the maximum value of the functor. If X is the original list and F(X) is the result of the functor F, this returns element x for which F(X) is a maximum i.e. x = argmax F(X)", Params=[('Functor', 'The functor to apply for the evaluation of the max.', BoundFunctor)]) IP = Functor( 'IP', "Common::ImpactParameter", "Calculate IP between vertex and state position. The first implicit argument type is a three-vector position." ) _REQUIRE_CLOSE = Functor( '_REQUIRE_CLOSE', "Common::RequireClose", "Check if the output of two functors that return floating point" "values are close to each other within some absolute difference" "and/or relative difference. The condition imposed is \"( F1 == F2 ) || ( &#124;F1 - F2&#124; < max( AbsDiff, RelDiff * ( &#124;F1&#124; + &#124;F2&#124; ) )\"", Params=[('AbsDiff', "The absolute difference between two numbers", float), ('RelDiff', "The relative difference between two numbers", float)])
[docs]def REQUIRE_CLOSE(F1, F2, AbsDiff: float = 1e-34, RelDiff: float = 1e-8): """ Check if the output of two functors that return floating point values are close to each other within some absolute difference and/or relative difference The condition imposed is "( F1 == F2 ) || ( &#124;F1 - F2&#124; < max( AbsDiff, RelDiff * ( &#124;F1&#124; + &#124;F2&#124; ) ) )" Args: F1: The first functor F2: The second functor AbsDiff: The absolute difference RelDiff: The relative difference Note: The functor's call operator expects two inputs. These inputs are the restuls of the two functors F1 and F2. Example: >>> import Functors as F >>> F.REQUIRE_CLOSE(F.PT, 1000.) ('Functors::bind( ::Functors::Common::RequireClose( /* The absolute difference between two numbers */ 1e-34f, /* The relative difference between two numbers */ 1e-08f ), Functors::chain( ::Functors::Common::Rho_Coordinate{}, ::Functors::Track::ThreeMomentum{} ), 1000.0f )', '_REQUIRE_CLOSE(AbsDiff=1e-34, RelDiff=1e-08).bind( ( RHO_COORDINATE @ THREEMOMENTUM ), 1000.0 )') >>> F.REQUIRE_CLOSE(F.MASS, F.PDG_MASS("J/psi(1S)")) ('Functors::bind( ::Functors::Common::RequireClose( /* The absolute difference between two numbers */ 1e-34f, /* The relative difference between two numbers */ 1e-08f ), ::Functors::Composite::Mass{}, Functors::chain( ::Functors::Composite::Mass{}, ::Functors::Particle::ParticlePropertyUser( /* ID to check */ std::string{"J/psi(1S)"} ) ) )', '_REQUIRE_CLOSE(AbsDiff=1e-34, RelDiff=1e-08).bind( MASS, ( MASS @ PARTICLE_PROPERTY(particle_name=J/psi(1S)) ) )') """ return _REQUIRE_CLOSE(AbsDiff=AbsDiff, RelDiff=RelDiff).bind(F1, F2)
IPCHI2 = Functor( 'IPCHI2', "Common::ImpactParameterChi2", "Calculate IP Chi2 between vertex and state position. The first implicit argument type is a vertex." ) _BPVIPCHI2 = Functor( '_BPVIPCHI2', "Common::ImpactParameterChi2ToVertex", "Calculate IP Chi2 w.r.t. best vertex. (Uses BPV relation if available)") OWNPVX = setComposedFunctor( X_COORDINATE @ OWNPV_POS, 'OWNPVX', "X-coordinate of the PV associated to the particle") OWNPVY = setComposedFunctor( Y_COORDINATE @ OWNPV_POS, 'OWNPVY', "Y-coordinate of the PV associated to the particle") OWNPVZ = setComposedFunctor( Z_COORDINATE @ OWNPV_POS, 'OWNPVZ', "Z-coordinate of the PV associated to the particle") OWNPVVDX = setComposedFunctor( END_VX - OWNPVX, 'OWNPVVDX', "Distance along the x-axis between the endvertex and the PV associated to a particle" ) OWNPVVDY = setComposedFunctor( END_VY - OWNPVY, 'OWNPVVDY', "Distance along the y-axis between the endvertex and the PV associated to a particle" ) OWNPVVDZ = setComposedFunctor( END_VZ - OWNPVZ, 'OWNPVVDZ', "Distance along the z-axis between the endvertex and the PV associated to a particle" ) OWNPVFDVEC = setComposedFunctor( ENDVERTEX_POS - OWNPV_POS, 'OWNPVFDVEC', "Three-vector distance between the endvertex position and the position of the PV associated to a particle" ) OWNPVDIRA = setComposedFunctor( NORMEDDOT.bind(THREEMOMENTUM, OWNPVFDVEC), 'OWNPVDIRA', "Direction angle between the three-momentum of a particle and its :py:func:`~OWNPVFDVEC`" ) OWNPVVDRHO = setComposedFunctor(RHO_COORDINATE @ OWNPVFDVEC, 'OWNPVVDRHO', "Rho-coordinate of :py:func:`~OWNPVFDVEC`") OWNPVFD = setComposedFunctor( MAGNITUDE @ OWNPVFDVEC, 'OWNPVFD', "Distance between the endvertex position and the position of the PV associated to a particle" ) OWNPVFDIR = setComposedFunctor(UNITVECTOR @ OWNPVFDVEC, 'OWNPVFDIR', "Unity vector of :py:func:`~OWNPVFDVEC`") OWNPVETA = setComposedFunctor(ETA_COORDINATE @ OWNPVFDVEC, 'OWNPVETA', "Eta-coordinate of :py:func:`~OWNPVFDVEC`") OWNPVFDCHI2 = setComposedFunctor( VTX_FDCHI2.bind(OWNPV, FORWARDARGS), 'OWNPVFDCHI2', "Flight distance chi2 with respect to the :py:func:`~OWNPV`") OWNPVLTIME = setComposedFunctor( VTX_LTIME.bind(OWNPV, FORWARDARGS), 'OWNPVLTIME', "Lifetime with respect to the :py:func:`~OWNPV`") OWNPVCORRM = setComposedFunctor( _BPVCORRM.bind(OWNPV, FORWARDARGS), 'OWNPVCORRM', "Corrected mass of the composite using the :py:func:`~OWNPV`") OWNPVCORRMERR = setComposedFunctor( _BPVCORRMERR.bind(OWNPV, FORWARDARGS), 'OWNPVCORRMERR', "Corrected mass error of the composite using the :py:func:`~OWNPV`") OWNPVIP = setComposedFunctor( IP.bind(OWNPV_POS, FORWARDARGS), 'OWNPVIP', "Impact parameter with respect to the :py:func:`~OWNPV`") OWNPVDLS = setComposedFunctor( VTX_DLS.bind(OWNPV, FORWARDARGS), 'OWNPVDLS', "Decay length significance with respect to the :py:func:`~OWNPV`") OWNPVIPCHI2 = setComposedFunctor( IPCHI2.bind(OWNPV, FORWARDARGS), 'OWNPVIPCHI2', "Impact parameter chi2 with respect to the :py:func:`~OWNPV`")
[docs]def BPVIPCHI2(Vertices: DataHandle = None): """Impact parameter Chi2 with respect to the :py:func:`~BPV`. More precisely that means the difference in the chi2 of the PV fit (of the BPV) between including and excluding the object the function is called on. Functor's call expects a particle-like object Args: Vertices: DataHandle of the vertices Note: Will use BPV relation if available. """ return IPCHI2.bind(BPV(Vertices), FORWARDARGS)
[docs]def MINIP(Vertices: DataHandle): """ Miniumum impact parameter with respect to the given vertices. Functor's call expects a particle-like object Args: Vertices: DataHandle of the vertices """ range_of_positions = MAP(TOLINALG @ POSITION) @ TES(Vertices) return MIN_ELEMENT @ MAP(IP).bind(range_of_positions, FORWARDARGS)
[docs]def MINIPCHI2(Vertices: DataHandle): """ Miniumum impact parameter chi2 with respect to the given vertices. Functor's call expects a particle-like object Args: Vertices: DataHandle of the vertices """ return MIN_ELEMENT @ MAP(IPCHI2).bind(TES(Vertices), FORWARDARGS)
[docs]def MINIPCUT(Vertices: DataHandle, IPCut: float): """ Require the minimum impact parameter w.r.t. any of the given Vertices is greater than the threshold IPCut. Functor's call expects a particle-like object Args: Vertices: DataHandle of the vertices IPCut: threshold cut (float) """ range_of_positions = MAP(TOLINALG @ POSITION) @ TES(Vertices) return MAP_ALL_OF(IP > IPCut).bind(range_of_positions, FORWARDARGS)
[docs]def MINIPCHI2CUT(Vertices: DataHandle, IPChi2Cut: float): """ Require the minimum impact parameter chi2 w.r.t. any of the given vertices is greater than the threshold IPChi2Cut. Functor's call expects a particle-like object Args: Vertices: DataHandle of the vertices IPCut: threshold cut (float) """ return MAP_ALL_OF(IPCHI2 > IPChi2Cut).bind(TES(Vertices), FORWARDARGS)
[docs]def BPVIP(Vertices: DataHandle = None): """ Impact parameter with respect to the :py:func:`~BPV`. Functor's call expects a particle-like object Args: Vertices: DataHandle of the vertices """ bpv = BPV_POS(Vertices) return IP.bind(bpv, FORWARDARGS)
[docs]def RPPVIPCHI2(Vertices: DataHandle = None): """ Evaluates the impact parameter chi2 of a particle (related one) w.r.t. the primary vertex of another particle (reference one) Binary functor: Functor's call operator expects two particle-like objects Args: Vertices: DataHandle of the vertices Example: >>> import Functors as F >>> from PyConf.Algorithms import WeightedRelTableAlg >>> from Functors.tests.categories import dummy_data_particle_range, dummy_data_pv_container >>> alg = WeightedRelTableAlg(name="WeightedRelTableAlg_RPPVIPCHI2", InputCandidates = dummy_data_particle_range, ReferenceParticles = dummy_data_particle_range, Cut = F.RPPVIPCHI2(dummy_data_pv_container) > 12) >>> alg.OutputRelations DataHandle('/Event/WeightedRelTableAlg_RPPVIPCHI2/OutputRelations') """ ref_part_pv = BPV(Vertices) @ FORWARDARG0 return IPCHI2.bind(ref_part_pv, FORWARDARG1)
[docs]def ALLPVX(Vertices: DataHandle): """ vector of x-coordinates of all primary vertices Functor's call operator does not require any input. Args: Vertices: DataHandle of the primary vertices """ return MAP(X_COORDINATE @ POSITION) @ TES(Vertices)
[docs]def ALLPVY(Vertices: DataHandle): """ vector of y-coordinates of all primary vertices Functor's call operator does not require any input. Args: Vertices: DataHandle of the primary vertices """ return MAP(Y_COORDINATE @ POSITION) @ TES(Vertices)
[docs]def ALLPVZ(Vertices: DataHandle): """ vector of z-coordinates of all primary vertices Functor's call operator does not require any input. Args: Vertices: DataHandle of the primary vertices """ return MAP(Z_COORDINATE @ POSITION) @ TES(Vertices)
[docs]def ALLPV_IP(Vertices: DataHandle): """ Calculate Impact Parameter with respect to all specified primary vertices. Functor's call operator does not require any input. Args: Vertices (DataHandle): the input primary vertices """ ALL_POS = MAP(TOLINALG @ POSITION) @ TES(Vertices) return MAP(IP).bind(ALL_POS, FORWARDARGS)
[docs]def ALLPV_FD(Vertices: DataHandle): """ Calculate flight distance with respect to all specified primary vertices. Functor's call operator does not require any input. Args: Vertices (DataHandle): the input primary vertices """ MAG_DIST = MAGNITUDE @ ( ENDVERTEX_POS @ FORWARDARG1 - TOLINALG @ POSITION @ FORWARDARG0) return MAP(MAG_DIST).bind(TES(Vertices), FORWARDARGS)
def TaggingDecision(FTags: DataHandle, TaggerName: Union[str, int]): """Flavour tagging decision Functor's call operator expects particle-like input. Args: TypeName: Name of the user-defined tagger type FTags: DataHandle of the flavour tags """ _TAGGING_DECISION = Functor( 'TAGGING_DECISION', "Composite::TaggingDecision", "Return the decision of a given tagging type from all tag results. ", Params=[('TaggerName', "Tagger type of which the decision is returned.", (str, int))]) return VALUE_OR(-99) @ _TAGGING_DECISION(TaggerName).bind( TES(FTags), FORWARDARGS) def TaggingMistag(FTags: DataHandle, TaggerName: Union[str, int]): """Flavour tagging mistag rate Functor's call operator expects particle-like input. Args: TypeName: Name of the user-defined tagger type FTags: DataHandle of the flavour tags """ _TAGGING_MISTAG = Functor( 'TAGGING_MISTAG', "Composite::TaggingMistag", "Return the mistag rate of a given tagging type from all tag results. ", Params=[('TaggerName', "Tagger type of which the mistag rate is returned.", (str, int))]) return VALUE_OR(-99) @ _TAGGING_MISTAG(TaggerName).bind( TES(FTags), FORWARDARGS) def TaggingMVAOutput(FTags: DataHandle, TaggerName: Union[str, int]): """Flavour tagging mva output Functor's call operator expects particle-like input. Args: TypeName: Name of the user-defined tagger type FTags: DataHandle of the flavour tags """ _TAGGING_MVA = Functor( 'TAGGING_MVAOUTPUT', "Composite::TaggingMVAOutput", "Return the mva output of a given tagging type from all tag results. ", Params=[('TaggerName', "Tagger type of which the mva value is returned.", (str, int))]) return VALUE_OR(-99) @ _TAGGING_MVA(TaggerName).bind( TES(FTags), FORWARDARGS)
[docs]def MC_PROPERTY(mc_track_info: DataHandle): """Retrieve the MCProperty object from MCTrackInfo object. Functor's call expects MCParticle Args: mc_track_info: DataHandle of the MC track info """ _MC_PROPERTY = Functor('_MC_PROPERTY', "Simulation::MC::Property", "Retrieve the MCProperty object.") return _MC_PROPERTY.bind(TES(mc_track_info), FORWARDARGS)
MC_TRACKINFO = Functor( 'MC_TRACKINFO', "Simulation::CheckMask", """Has Flag in property Functor's call expects MCParticle""", Params=[('Flag', "The flag", int)]) _MC_RECONSTRUCTIBLE = Functor('_MC_RECONSTRUCTIBLE', "Simulation::MC::ChargeReconstructible", "MC Reconstructible category") MC_RECONSTRUCTIBLE = setComposedFunctor( CAST_TO_INT @ _MC_RECONSTRUCTIBLE, 'MC_RECONSTRUCTIBLE', ''' Get the MC Reconstructible category code: -1: NoClassification 0: OutsideAcceptance 1: NotReconstructible 2: ChargedLong 3: ChargedDownstream 4: ChargedUpstream 5: ChargedTtrack 6: ChargedVelo 50: Neutral ''') MC_RECONSTRUCTED = Functor( 'MC_RECONSTRUCTED', "Track::MC_Reconstructed", """MC Reconstructed category Functor's call expects MCParticle""") PROTOPARTICLE = Functor('PROTOPARTICLE', "Particle::GetProtoParticle", "Get the ProtoParticle from a Particle")
[docs]def TO_VALUE_RELATION_TABLE(Relations: DataHandle, default: float = None) -> BoundFunctor: """Retrieve the 'TO' value of the relation table with protoparticles in the 'FROM' side (see :py:func:`~PROTOPARTICLE` functor). Args: Relations: Datahandle of the relations table default: Default value to use in case the variable doesn't exist """ if default is not None: return VALUE_OR(default) @ TO @ FRONT @ RELATIONS.bind( TES(Relations), FORWARDARGS) @ PROTOPARTICLE return TO @ FRONT @ RELATIONS.bind(TES(Relations), FORWARDARGS) @ PROTOPARTICLE
CLOSESTTOBEAM = setComposedFunctor( STATE_AT("ClosestToBeam"), "CLOSESTTOBEAM", """'Returns the closest-to-beam state of a given track.'""") TRACKSTATE = Functor('TRACKSTATE', "Track::TrackState", """Returns the CTB or first state of a given track.""") # Track momentum at "ClosestToBeam" state TRACK_POSVEC_CLOSESTTOBEAM = setComposedFunctor( POSITION @ CLOSESTTOBEAM @ TRACK, "TRACK_POSVEC_CLOSESTTOBEAM", """Get the position vector of :py:func:`~TRACK` at the closest-to-beam state (see :py:func:`~CLOSESTTOBEAM` for definition). Functor's call operator expects a ChargedBasic""") TRACK_POS_CLOSESTTOBEAM_X = setComposedFunctor( X_COORDINATE @ TRACK_POSVEC_CLOSESTTOBEAM, "TRACK_POS_CLOSESTTOBEAM_X", """Get the X-coordinate of the position vector of a track at the closest-to-beam state (see :py:func:`~CLOSESTTOBEAM` for definition). Functor's call operator expects a ChargedBasic""") TRACK_POS_CLOSESTTOBEAM_Y = setComposedFunctor( Y_COORDINATE @ TRACK_POSVEC_CLOSESTTOBEAM, "TRACK_POS_CLOSESTTOBEAM_Y", """Get the Y-coordinate of the position vector of a track at the closest-to-beam state (see :py:func:`~CLOSESTTOBEAM` for definition). Functor's call operator expects a ChargedBasic""") TRACK_POS_CLOSESTTOBEAM_Z = setComposedFunctor( Z_COORDINATE @ TRACK_POSVEC_CLOSESTTOBEAM, "TRACK_POS_CLOSESTTOBEAM_Z", """Get the Z-coordinate of the position vector of a track at the closest-to-beam state (see :py:func:`~CLOSESTTOBEAM` for definition). Functor's call operator expects a ChargedBasic""") # Track momentum at "ClosestToBeam" state if available # otherwise returns momentum at the "FirstMeasurement" state TRACK_PT = setComposedFunctor( PT @ TRACK, "TRACK_PT", """Get the transverse momentum of a track (see :py:func:`~TRACK` for definition) Functor's call operator expects a ChargedBasic""" ) TRACK_MOMVEC = setComposedFunctor( THREEMOMENTUM @ TRACK, "TRACK_MOMVEC", """Get the 3-vector momentum of a track (see :py:func:`~TRACK` for definition) Functor's call operator expects a ChargedBasic""" ) TRACK_P = setComposedFunctor( P @ TRACK, "TRACK_P", """Get the magnitude of the momentum vector of a track (see :py:func:`~TRACK` for definition) Functor's call operator expects a ChargedBasic""") TRACK_PX = setComposedFunctor( X_COORDINATE @ TRACK_MOMVEC, "TRACK_PX", """Get the X-coordinate of the momentum of a track (see :py:func:`~TRACK_MOMVEC` for definition) Functor's call operator expects a ChargedBasic""") TRACK_PY = setComposedFunctor( Y_COORDINATE @ TRACK_MOMVEC, "TRACK_PY", """Get the Y-coordinate of the momentum of a track (see :py:func:`~TRACK_MOMVEC` for definition) Functor's call operator expects a ChargedBasic""") TRACK_PZ = setComposedFunctor( Z_COORDINATE @ TRACK_MOMVEC, "TRACK_PZ", """Get the Z-coordinate of the momentum of a track (see :py:func:`~TRACK_MOMVEC` for definition) Functor's call operator expects a ChargedBasic""") FIND_DECAY = Functor( 'FIND_DECAY', "Decay::FindDecay", """Use the DecayFinder algorithm to get a list of particles in the reconstructed decay Functor's call expects a particle-like object""", Params=[('DecayDesc', 'Decay descriptor', str)]) FIND_MCDECAY = Functor( 'FIND_MCDECAY', "Decay::FindMCDecay", """Use the MCDecayFinder algorithm to get a list of MCParticles in the decay Functor's call expects MCParticle""", Params=[('MCDecayDesc', 'Monte Carlo decay descriptor', str)])
[docs]def MINTREE(Predicate: Functor, Functor: Functor): """Evaluates the minimal value of the applied functor through a decay tree (see :py:func:`~GET_ALL_DESCENDANTS` for definition) Functor's call operator expects composite particle-like input. Args: Predicate: Predicate to filter the decay tree Functor: Functor to apply """ return MIN_ELEMENT @ MAP(Functor) @ FILTER(Predicate) @ GET_ALL_DESCENDANTS
[docs]def MAXTREE(Predicate: Functor, Functor: Functor): """Evaluates the maximal value of the applied functor through a decay tree (see :py:func:`~GET_ALL_DESCENDANTS` for definition) Functor's call operator expects composite particle-like input. Args: Predicate: Predicate to filter the decay tree Functor: Functor to apply """ return MAX_ELEMENT @ MAP(Functor) @ FILTER(Predicate) @ GET_ALL_DESCENDANTS
[docs]def NINTREE(Predicate: Functor): """Evaluates the number of particles in a decay tree satisfying the predicate (see :py:func:`~GET_ALL_DESCENDANTS` for definition) Functor's call operator expects composite particle-like input. Args: Predicate: Predicate to filter the decay tree """ return SIZE_OF @ FILTER(Predicate) @ GET_ALL_DESCENDANTS
[docs]def INTREE(Predicate: Functor): """Requires there is a particle in a decay tree satisfying the predicate (see :py:func:`~GET_ALL_DESCENDANTS` for definition) Functor's call operator expects composite particle-like input. Args: Predicate: Predicate to filter the decay tree """ return MAP_ANY_OF(Predicate) @ GET_ALL_DESCENDANTS
[docs]def NINGENERATION(Predicate: Functor, Depth: int): """Evaluates the number of particles in a decay tree satisfying the predicate at the given depth (see :py:func:`~GET_GENERATION` for definition) Functor's call operator expects composite particle-like input. Args: Predicate: Predicate to filter the decay tree Depth: Number of the correspondent generation (1-children, 2-grandchildren, ...) """ return SIZE_OF @ FILTER(Predicate) @ GET_GENERATION(Generation=Depth)
[docs]def INGENERATION(Predicate: Functor, Depth: int): """Requires there is a particle in a decay tree satisfying the predicate at the given depth (see :py:func:`~GET_GENERATION` for definition) Functor's call operator expects composite particle-like input. Args: Predicate: Predicate to filter the decay tree Depth: Number of the correspondent generation (1-children, 2-grandchildren, ...) """ return MAP_ANY_OF(Predicate) @ GET_GENERATION(Generation=Depth)
#binary functors on tracks and pvs
[docs]def SHARE_BPV(Vertices: DataHandle): """ Check whenever two particles are sharing the same :py:func:`~BPV` Binary functor: Functor's call operator expects two particle-like objects Args: Vertices: DataHandle of the vertices Example: >>> import Functors as F >>> from Functors.tests.categories import dummy_data_particle_range, dummy_data_pv_container >>> from PyConf.Algorithms import WeightedRelTableAlg >>> alg = WeightedRelTableAlg(name="WeightedRelTableAlg_SHARE_BPV", InputCandidates = dummy_data_particle_range, ReferenceParticles = dummy_data_particle_range, Cut = F.SHARE_BPV(dummy_data_pv_container) ) >>> alg.OutputRelations DataHandle('/Event/WeightedRelTableAlg_SHARE_BPV/OutputRelations') """ return ADDRESSOF @ BPV(Vertices) @ FORWARDARG0 == ADDRESSOF @ BPV( Vertices) @ FORWARDARG1
_TRACK_FROM_PARTICLE = TRACK @ PROTOPARTICLE _REFERENCE_TRACK = _TRACK_FROM_PARTICLE @ FORWARDARG0 _RELATED_TRACK = _TRACK_FROM_PARTICLE @ FORWARDARG1 SHARE_TRACKS = setComposedFunctor((_REFERENCE_TRACK == _RELATED_TRACK), "SHARE_TRACKS", """ Check whenever two particles are sharing the same track Binary functor: Functor's call operator expects two particle-like objects Args: Vertices: DataHandle of the vertices Example: >>> import Functors as F >>> from PyConf.Algorithms import WeightedRelTableAlg >>> from Functors.tests.categories import dummy_data_particle_range, dummy_data_pv_container >>> alg = WeightedRelTableAlg(name='WeightedRelTableAlg_SHARETRACKS', InputCandidates = dummy_data_particle_range, ReferenceParticles = dummy_data_particle_range, Cut = F.SHARE_TRACKS()) >>> alg.OutputRelations DataHandle('/Event/WeightedRelTableAlg_SHARETRACKS/OutputRelations') """) FIND_IN_TREE = setComposedFunctor( MAP_ANY_OF(_REFERENCE_TRACK == _RELATED_TRACK).bind( GET_ALL_BASICS @ FORWARDARG0, FORWARDARG1), "FIND_IN_TREE", """ Check whenever a basic particle (from InputCandidates) is inside a decay tree of a composite one (from ReferenceParticles). Binary functor: Functor's call operator expects two particle-like objects Args: Vertices: DataHandle of the vertices Example: >>> import Functors as F >>> from PyConf.Algorithms import WeightedRelTableAlg >>> from Functors.tests.categories import dummy_data_particle_range, dummy_data_pv_container >>> alg = WeightedRelTableAlg(name='WeightedRelTableAlg_FINDINTREE', InputCandidates = dummy_data_particle_range, ReferenceParticles = dummy_data_particle_range, Cut = F.FIND_IN_TREE()) >>> alg.OutputRelations DataHandle('/Event/WeightedRelTableAlg_FINDINTREE/OutputRelations') """) # brem-wrapper functor and subsequent brem-corrected versions of functors WITH_BREM = Functor( 'WITH_BREM', "Track::Bremsstrahlung", "Gives wrapper around object to use brem-corrected momenta / covariances, no overlap check unless done in composite builder" ) P_WITH_BREM = setComposedFunctor( P @ WITH_BREM, "P_WITH_BREM", """Get the magnitude of the momentum vector of a track with brem correction""" ) PT_WITH_BREM = setComposedFunctor( PT @ WITH_BREM, "PT_WITH_BREM", """Get the transverse momentum of a track with brem correction""") MASS_WITH_BREM = setComposedFunctor( MASS @ WITH_BREM, "MASS_WITH_BREM", """Get invariant mass of a particle with brem correction""") # caluclate the y-z straight line intersection using the slopes and closest to beam or first measurement positions _TRACK_POS_CTB_OR_FM = POSITION @ TRACKSTATE @ TRACK _TRACK_POS_CTB_OR_FM_Y = Y_COORDINATE @ _TRACK_POS_CTB_OR_FM _TRACK_POS_CTB_OR_FM_Z = Z_COORDINATE @ _TRACK_POS_CTB_OR_FM _TWOBODY_YZ_INTERSECTION_C = setComposedFunctor( (VALUE_OR(0) @ _TRACK_POS_CTB_OR_FM_Y) - (TY * (VALUE_OR(0) @ _TRACK_POS_CTB_OR_FM_Z)), "_TWOBODY_YZ_INTERSECTION_C", """y-z straight line y axis intersection""") TWOBODY_YZ_INTERSECTION_Z = setComposedFunctor( (CHILD(2, _TWOBODY_YZ_INTERSECTION_C) - CHILD( 1, _TWOBODY_YZ_INTERSECTION_C)) / (CHILD(1, TY) - CHILD(2, TY)), "TWOBODY_YZ_INTERSECTION_Z", """The z-position of the y-z straight line intersection calculated using the slopes and closest to beam positions. Can be used to help reduce combinatorics before vertex fit if combination mass is unreliable.""" ) TWOBODY_YZ_INTERSECTION_Y = setComposedFunctor( CHILD(1, TY) * TWOBODY_YZ_INTERSECTION_Z + CHILD( 1, _TWOBODY_YZ_INTERSECTION_C), "TWOBODY_YZ_INTERSECTION_Y", """The y-position of the y-z straight line intersection calculated using the slopes and closest to beam positions. Can be used to help reduce combinatorics before vertex fit if combination mass is unreliable.""" ) # define "tilt" as the product of the signs of the slopes,
[docs]def TWOBODY_TILT(axis_str: str): """axis_str should be X or Y, case sensitive""" if axis_str not in ["X", "Y"]: raise TypeError( f"TWOBODY_TILT does not accept {axis_str}, only X or Y accepted (case sensitive). Can be used to help reduce combintaorics before vertex fit if combination mass is unreliable." ) SLOPE_SIGN_AXIS = sign(eval(f"T{axis_str}")) return setComposedFunctor( CHILD(1, SLOPE_SIGN_AXIS) * CHILD(2, SLOPE_SIGN_AXIS), "TWOBODY_TILT", """The product of the signs of slope (TX or TY) for a two-body decay. Can be used to help reduce combintaorics before vertex fit if combination mass is unreliable.""" )
_IS_TIS = Functor( 'IS_TIS', "Particle::IsTis", """Check if the trigger result for a particle is TIS. Functor's call operator expects a "LHCb::detail::TisTosResult_t" object (defined in "ITisTos.h" file).""" ) _IS_TOS = Functor( 'IS_TOS', "Particle::IsTos", """Check if the trigger result for a particle is TOS Functor's call operator expects a "LHCb::detail::TisTosResult_t" object (defined in "ITisTos.h" file).""" )
[docs]def IS_TOS(trigger_line: str, P2TisTosTable: DataHandle): """Check if the trigger result for a particle is TOS for a given trigger line Args: trigger_line: Name of the trigger line P2TisTosTable: DataHandle which is the output of "HltTisTosAlg" algorithm """ return VALUE_OR(False) @ _IS_TOS @ VALUE_FROM_DICT( trigger_line) @ MAP_TO_RELATED(P2TisTosTable)
[docs]def IS_TIS(trigger_line: str, P2TisTosTable: DataHandle): """Check if the trigger result for a particle is TIS for a given trigger line Args: trigger_line: Name of the trigger line P2TisTosTable: DataHandle which is the output of "HltTisTosAlg" algorithm """ return VALUE_OR(False) @ _IS_TIS @ VALUE_FROM_DICT( trigger_line) @ MAP_TO_RELATED(P2TisTosTable)
[docs]def PERR2(): """Returns the uncertainty on the momentum of a particle""" jacobian = THREEMOMENTUM / P return similarity(jacobian, THREE_MOM_COV_MATRIX)
[docs]def NHITSINMUON(dh: DataHandle, station, region): """Size of the container at the given TES location Args: dh: Datahandle of TES location from which container will be retrieved """ _NHITSINMUON = Functor( 'NHITSINMUON', 'TES::NHitsInMuon', '''Return the number of hits in muon system station and region''', Params=[('station', 'Station the number of hits should be counted in', int), ('region', 'Region the number of hits should be counted in', int)]) return _NHITSINMUON(station=station, region=region) @ TES(dh)
DELHCB = Functor('_DELHCB', "Detector::DeLHCb", 'Returns a handle to LHCb::Detector::DeLHCb') FILL_NUMBER = setComposedFunctor( Functor('_FILL_NUMBER', "Detector::FillNumber", "") @ DELHCB, "FILL_NUMBER", "Get the fill number from the LHC conditions.") LHC_ENERGY = setComposedFunctor( Functor('_LHC_ENERGY', "Detector::LHCEnergy", "") @ DELHCB, "LHC_ENERGY", "Get the LHC beam energy.") LHCB_CLOCKPHASE = setComposedFunctor( Functor('_LHCB_CLOCKPHASE', "Detector::LHCbClockPhase", "") @ DELHCB, "LHCB_CLOCKPHASE", "Get the LHCb clock phase from the LHC conditions.")