Usage of RelationTable algorithm for SLB isolation MVA

This example shows how to build RelationTable of SLB isolation MVA and produce ntuples with info using the tables.


import Functors as F
from PyConf.reading import get_pvs, get_particles
from PyConf.Algorithms import ParticleToParticleWeightedRelTableAlg
from FunTuple import FunctorCollection
from FunTuple import FunTuple_Particles as Funtuple
from DaVinci.algorithms import create_lines_filter
from DaVinci import Options, make_config
from RecoConf.algorithms_thor import ParticleCombiner
from Hlt2Conf.lines.semileptonic.isolationMVA import mva_functor_inclusive
from DaVinciTools import SubstitutePID
from Gaudi.Configuration import INFO


def main(options: Options):

    # Get v2_pvs
    v2_pvs = get_pvs()

    """
    Prepare parent particle B*0 and signal child B*-
    """

    # Get signal child and extra particles
    line = "SpruceSLB_BuToD0ENu_D0ToKPi"
    Bm = get_particles(f"/Event/Spruce/{line}/Particles")
    extra_particles = get_particles(
        f"/Event/Spruce/{line}/{line}_extra_tracks/Particles"
    )

    # Make the signal child B-(-> D0 e-) flightless
    Bstm = SubstitutePID(
        name="PIDSubstitute",
        input_particles=Bm,
        substitutions=["B-{{B*-}}", "B+{{B*+}}"],
        output_level=INFO,
    ).Particles

    # Combine to make flightless parent particle [B*0 -> B*- pi+]cc
    Bst = ParticleCombiner(
        Inputs=[Bstm, extra_particles],
        name="Bst",
        DecayDescriptor="[B*0 -> B*- pi+]cc",
        CombinationCut=F.ALL,
        CompositeCut=F.ALL,
        ParticleCombiner="ParticleVertexFitter",
        PrimaryVertices=v2_pvs,
    )

    """
    Build RelationTables
    """

    # MVA functor in isolation MVA tool
    MVA_functor = mva_functor_inclusive()[0]

    # Build the RelationTable algorithm
    iso_relations_alg = ParticleToParticleWeightedRelTableAlg(
        name="Name_of_alg",
        CompositeSelection=Bst,
        SignalSelection=Bstm,
        MVAFunctor=MVA_functor,
    )

    # Get the RelationTable for signal child
    reltable_b = iso_relations_alg.BOutputRelations

    # Get the RelationTable for parent particle
    reltable_bst = iso_relations_alg.BstOutputRelations

    """
    Prepare the tuple for parent particle
    This part shows how to extract information from RelationTable of parent particle (reltable_bst)
    """

    # Variables for parent particle B*0
    vars_Bst = FunctorCollection()

    B0_Bm_child = F.CHILD(1, F.FORWARDARG0)
    B0_Bm_D0_K_child = F.CHILD(1, F.CHILD(1, F.CHILD(1, F.FORWARDARG0)))
    B0_Bm_D0_pi_child = F.CHILD(1, F.CHILD(1, F.CHILD(2, F.FORWARDARG0)))
    B0_Bm_e_child = F.CHILD(1, F.CHILD(2, F.FORWARDARG0))

    # Define variables extracted from RelationTable
    vars_Bst["MVA[bstrels_indx]"] = F.MAP_WEIGHT(reltable_bst)  # MVA score
    vars_Bst["nrels"] = F.VALUE_OR(0) @ F.MAP_INPUT_SIZE(
        reltable_bst
    )  # Size of RelationTable, in this case, the output is always one
    vars_Bst["Bst_P[bstrels_indx]"] = F.MAP(F.P @ F.FROM) @ F.RELATIONS.bind(
        F.TES(reltable_bst), F.FORWARDARGS
    )  # P of parent particle B*0
    vars_Bst["Bm_P[bstrels_indx]"] = F.MAP(
        F.P @ B0_Bm_child @ F.FROM
    ) @ F.RELATIONS.bind(
        F.TES(reltable_bst), F.FORWARDARGS
    )  # P of signal child B*-
    vars_Bst["Km_P[bstrels_indx]"] = F.MAP(
        F.P @ B0_Bm_D0_K_child @ F.FROM
    ) @ F.RELATIONS.bind(
        F.TES(reltable_bst), F.FORWARDARGS
    )  # P of K+
    vars_Bst["pip_P[bstrels_indx]"] = F.MAP(
        F.P @ B0_Bm_D0_pi_child @ F.FROM
    ) @ F.RELATIONS.bind(
        F.TES(reltable_bst), F.FORWARDARGS
    )  # P of pi-
    vars_Bst["lep_P[bstrels_indx]"] = F.MAP(
        F.P @ B0_Bm_e_child @ F.FROM
    ) @ F.RELATIONS.bind(
        F.TES(reltable_bst), F.FORWARDARGS
    )  # P of e-
    vars_Bst["pi_P[bstrels_indx]"] = F.MAP_INPUT_ARRAY(
        F.P, reltable_bst
    )  # P of extra pion

    # Define fields
    fields_B0 = {}
    fields_B0["B0"] = "[B*0 ->  (B*- ->  ([D0 -> K- pi+]CC) e-)  pi+]CC"

    # Add variables
    variables_B0 = {}
    variables_B0["ALL"] = vars_Bst

    # Define tuple for parent particle
    my_tuple_B0 = Funtuple(
        name="Tuple_B0",
        tuple_name="DecayTree",
        fields=fields_B0,
        variables=variables_B0,
        store_multiple_cand_info=True,
        inputs=Bst,
    )

    """
    Prepare the tuple for signal child, which can be used for MVA ranking
    This part shows how to extract information from RelationTable of signal child (reltable_b)
    """

    # Variables for signal child B*-
    vars_B = FunctorCollection()

    # Define variables extracted from RelationTable
    vars_B["nrels"] = F.VALUE_OR(0) @ F.MAP_INPUT_SIZE(
        reltable_b
    )  # Size of RelationTable, which is the number of signal child - extra pions pairs for each signal child
    vars_B["MVA[brels_indx]"] = F.MAP_WEIGHT(
        reltable_b
    )  # MVA score array for each signal child - extra pions combination
    vars_B["Bm_P[brels_indx]"] = F.MAP(F.P @ F.FROM) @ F.RELATIONS.bind(
        F.TES(reltable_b), F.FORWARDARGS
    )  # P of signal child
    vars_B["pi_P[brels_indx]"] = F.MAP_INPUT_ARRAY(
        F.P, reltable_b
    )  # P of extra pion extracted from the table # P of extra pion

    # Define fields
    fields_Bm = {}
    fields_Bm["Bm"] = "[B*- ->  ([D0 -> K- pi+]CC) e-]CC"

    # Add variables
    variables_Bm = {}
    variables_Bm["ALL"] = vars_B

    # Define tuple
    my_tuple_Bm = Funtuple(
        name="Tuple_Bm",
        tuple_name="DecayTree",
        fields=fields_Bm,
        variables=variables_Bm,
        store_multiple_cand_info=True,
        inputs=Bstm,
    )

    # Define filter
    my_filter = create_lines_filter(name="Filter_name", lines=[line])

    # Define algorithms
    user_algorithms = {}
    user_algorithms["Alg_B0"] = [my_filter, my_tuple_B0]
    user_algorithms["Alg_Bm"] = [my_filter, my_tuple_Bm]

    return make_config(options, user_algorithms)

To run the example:

lbexec DaVinciExamples.tupling.option_davinci_tupling_isoMVA_reltable:main $DAVINCIEXAMPLESROOT/example_data/example_tupling_isoMVA_reltable.yaml

For reference, these are the options of this example

testfiledb_key: davinci_example_isoMVA_reltable_MC
input_process: Spruce
print_freq: 1000
input_raw_format: 0.5