FunTuple event-by-event primary b- and c-hadrons and their descendants
This script demonstrates how to use the FunTuple_Event framework to create a tuple with information on the MC particles for each event to study and reconstruct the decay of prompt b and c hadrons (ancestors).
from PyConf.reading import get_mc_header
import Functors as F
from FunTuple import FunctorCollection
from FunTuple import FunTuple_Event
from DaVinci import Options, make_config
def main(options: Options):
# get the header and the event variables
mc_header = get_mc_header()
evt_variables = FunctorCollection()
# functors to filter on prompt B and C hadrons
PRODUCTS_WITH_BOTTOM = (
F.FILTER(F.HAS_BOTTOM & F.IS_HADRON @ F.PARTICLE_ID_OBJ) @ F.MC_VTX_PRODUCTS
)
PRODUCTS_WITH_CHARM = (
F.FILTER(F.HAS_CHARM & F.IS_HADRON @ F.PARTICLE_ID_OBJ) @ F.MC_VTX_PRODUCTS
)
# filters functors to get the number of decay prongs
filter_charged_inacc = F.FILTER((F.CHARGE != 0) & (F.ETA > 2) & (F.ETA < 5))
filter_notcharged = F.FILTER(F.CHARGE == 0)
filter_charged = F.FILTER(F.CHARGE != 0)
filter_inacc = F.FILTER((F.ETA > 2) & (F.ETA < 5))
# number of charged descentants in acceptance
# cast the integer to float because SUM_RANGE requires float
num_charged_descentants_inacc = F.SUM_RANGE @ F.MAP(
F.CAST_TO_FLOAT @ F.SIZE_OF @ filter_charged_inacc @ F.GET_ALL_DESCENDANTS
)
# number of decay prongs to reconstruct the vertex
num_decay_prongs = (
F.VALUE_OR(0)
@ (
(num_charged_descentants_inacc @ filter_notcharged)
+ (F.SIZE_OF @ filter_charged)
)
@ filter_inacc
@ F.GET_CHILDREN
)
# distance between the origin vertex and the end vertex
orig_vtx_pos = F.VALUE @ F.TOLINALG @ F.POSITION @ F.MC_ORIGINVERTEX
end_vtx_pos = F.VALUE @ F.TOLINALG @ F.POSITION @ F.ENDVERTEX
decaylength = F.VALUE_OR(0.0) @ F.MAGNITUDE @ (orig_vtx_pos - end_vtx_pos)
# functors for ancestors
f_pid = F.VALUE_OR([0]) @ F.MAP(F.PARTICLE_ID)
f_key = F.VALUE_OR([0]) @ F.MAP(F.OBJECT_KEY)
f_charge = F.VALUE_OR([0]) @ F.MAP(F.CHARGE)
f_nprongs = F.VALUE @ F.MAP(num_decay_prongs)
f_decaylength = F.VALUE @ F.MAP(decaylength)
f_Ndescendants = F.VALUE_OR([0]) @ F.MAP(F.SIZE_OF @ F.GET_ALL_DESCENDANTS)
# functors for descendants
flat_products_key = (
F.VALUE_OR([0]) @ F.FLATTEN @ F.MAP(F.MAP(F.OBJECT_KEY) @ F.GET_ALL_DESCENDANTS)
)
flat_products_pid = (
F.VALUE_OR([0])
@ F.FLATTEN
@ F.MAP(F.MAP(F.PARTICLE_ID) @ F.GET_ALL_DESCENDANTS)
)
flat_products_nprongs = (
F.VALUE @ F.FLATTEN @ F.MAP(F.MAP(num_decay_prongs) @ F.GET_ALL_DESCENDANTS)
)
flat_products_decaylength = (
F.VALUE @ F.FLATTEN @ F.MAP(F.MAP(decaylength) @ F.GET_ALL_DESCENDANTS)
)
flat_products_vtx = (
F.VALUE_OR([-1])
@ F.FLATTEN
@ F.MAP(
F.MAP(F.VALUE_OR(-42) @ F.MC_VTX_TYPE @ F.MC_ORIGINVERTEX)
@ F.GET_ALL_DESCENDANTS
)
)
flat_products_mother_key = (
F.VALUE_OR([0])
@ F.FLATTEN
@ F.MAP(
F.MAP(F.VALUE_OR(-42) @ F.MC_MOTHER(1, F.OBJECT_KEY))
@ F.GET_ALL_DESCENDANTS
)
)
# event variables
evt_up = {
"B_Ancestor_Ndescendants[ba_indx]": F.FLATTEN
@ F.MAP(f_Ndescendants @ PRODUCTS_WITH_BOTTOM)
@ F.MC_ALLPVS(mc_header=mc_header),
"B_Ancestor_PID[ba_indx]": F.FLATTEN
@ F.MAP(f_pid @ PRODUCTS_WITH_BOTTOM)
@ F.MC_ALLPVS(mc_header=mc_header),
"B_Ancestor_KEY[ba_indx]": F.FLATTEN
@ F.MAP(f_key @ PRODUCTS_WITH_BOTTOM)
@ F.MC_ALLPVS(mc_header=mc_header),
"B_Ancestor_NPRONGS[ba_indx]": F.FLATTEN
@ F.MAP(f_nprongs @ PRODUCTS_WITH_BOTTOM)
@ F.MC_ALLPVS(mc_header=mc_header),
"B_Ancestor_DL[ba_indx]": F.FLATTEN
@ F.MAP(f_decaylength @ PRODUCTS_WITH_BOTTOM)
@ F.MC_ALLPVS(mc_header=mc_header),
"B_Ancestor_Q[ba_indx]": F.FLATTEN
@ F.MAP(f_charge @ PRODUCTS_WITH_BOTTOM)
@ F.MC_ALLPVS(mc_header=mc_header),
"B_Children_PID[bc_indx]": F.FLATTEN
@ F.MAP(flat_products_pid @ PRODUCTS_WITH_BOTTOM)
@ F.MC_ALLPVS(mc_header=mc_header),
"B_Children_KEY[bc_indx]": F.FLATTEN
@ F.MAP(flat_products_key @ PRODUCTS_WITH_BOTTOM)
@ F.MC_ALLPVS(mc_header=mc_header),
"B_Children_NPRONGS[bc_indx]": F.FLATTEN
@ F.MAP(flat_products_nprongs @ PRODUCTS_WITH_BOTTOM)
@ F.MC_ALLPVS(mc_header=mc_header),
"B_Children_DL[bc_indx]": F.FLATTEN
@ F.MAP(flat_products_decaylength @ PRODUCTS_WITH_BOTTOM)
@ F.MC_ALLPVS(mc_header=mc_header),
"B_Children_VTX_type[bc_indx]": F.FLATTEN
@ F.MAP(flat_products_vtx @ PRODUCTS_WITH_BOTTOM)
@ F.MC_ALLPVS(mc_header=mc_header),
"B_Children_Mother_KEY[bc_indx]": F.FLATTEN
@ F.MAP(flat_products_mother_key @ PRODUCTS_WITH_BOTTOM)
@ F.MC_ALLPVS(mc_header=mc_header),
"C_Ancestor_Ndescendants[ca_indx]": F.FLATTEN
@ F.MAP(f_Ndescendants @ PRODUCTS_WITH_CHARM)
@ F.MC_ALLPVS(mc_header=mc_header),
"C_Ancestor_PID[ca_indx]": F.FLATTEN
@ F.MAP(f_pid @ PRODUCTS_WITH_CHARM)
@ F.MC_ALLPVS(mc_header=mc_header),
"C_Ancestor_KEY[ca_indx]": F.FLATTEN
@ F.MAP(f_key @ PRODUCTS_WITH_CHARM)
@ F.MC_ALLPVS(mc_header=mc_header),
"C_Ancestor_NPRONGS[ca_indx]": F.FLATTEN
@ F.MAP(f_nprongs @ PRODUCTS_WITH_CHARM)
@ F.MC_ALLPVS(mc_header=mc_header),
"C_Ancestor_DL[ca_indx]": F.FLATTEN
@ F.MAP(f_decaylength @ PRODUCTS_WITH_CHARM)
@ F.MC_ALLPVS(mc_header=mc_header),
"C_Ancestor_Q[ca_indx]": F.FLATTEN
@ F.MAP(f_charge @ PRODUCTS_WITH_CHARM)
@ F.MC_ALLPVS(mc_header=mc_header),
"C_Children_PID[cc_indx]": F.FLATTEN
@ F.MAP(flat_products_pid @ PRODUCTS_WITH_CHARM)
@ F.MC_ALLPVS(mc_header=mc_header),
"C_Children_KEY[cc_indx]": F.FLATTEN
@ F.MAP(flat_products_key @ PRODUCTS_WITH_CHARM)
@ F.MC_ALLPVS(mc_header=mc_header),
"C_Children_NPRONGS[cc_indx]": F.FLATTEN
@ F.MAP(flat_products_nprongs @ PRODUCTS_WITH_CHARM)
@ F.MC_ALLPVS(mc_header=mc_header),
"C_Children_DL[cc_indx]": F.FLATTEN
@ F.MAP(flat_products_decaylength @ PRODUCTS_WITH_CHARM)
@ F.MC_ALLPVS(mc_header=mc_header),
"C_Children_VTX_type[cc_indx]": F.FLATTEN
@ F.MAP(flat_products_vtx @ PRODUCTS_WITH_CHARM)
@ F.MC_ALLPVS(mc_header=mc_header),
"C_Children_Mother_KEY[cc_indx]": F.FLATTEN
@ F.MAP(flat_products_mother_key @ PRODUCTS_WITH_CHARM)
@ F.MC_ALLPVS(mc_header=mc_header),
}
evt_variables.update(evt_up)
# create the tuple
my_tuple = FunTuple_Event(
name="Tuple", tuple_name="EventInfo", variables=evt_variables
)
return make_config(options, [my_tuple])
To run the example:
lbexec DaVinciExamples.tupling.option_davinci_tupling_FunTupleEvent_dfei:main $DAVINCIEXAMPLESROOT/example_data/test_hlt1_trigger_decisions.yaml
For reference, these are the options of this example