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