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):
# filters functors to get the number of decay prongs
inacc = F.math.in_range(2, F.ETA, 5)
# number of charged descendants in acceptance
num_charged_descendants_inacc = F.SUM_RANGE @ F.MAP(
F.COUNT_IF((F.CHARGE != 0) & inacc) @ F.GET_ALL_DESCENDANTS
)
# number of decay prongs to reconstruct the vertex
num_decay_prongs = (
(num_charged_descendants_inacc @ F.FILTER((F.CHARGE == 0) & inacc))
+ F.COUNT_IF((F.CHARGE != 0) & inacc)
) @ F.GET_CHILDREN
# distance between the origin vertex and the end vertex
orig_vtx_pos = F.TOLINALG @ F.POSITION @ F.MC_ORIGINVERTEX
end_vtx_pos = F.TOLINALG @ F.POSITION @ F.ENDVERTEX
decaylength = F.MAGNITUDE @ (orig_vtx_pos - end_vtx_pos)
# common functors
common_vars = (
("PID", F.PARTICLE_ID),
("KEY", F.OBJECT_KEY),
("NPRONGS", num_decay_prongs),
("DL", decaylength),
)
# functors for ancestors
ancestor_vars = (
(("Ndescendants", F.SIZE_OF @ F.GET_ALL_DESCENDANTS),)
+ common_vars
+ (("Q", F.CHARGE),)
)
# functors for descendants
children_vars = common_vars + (
(
"VTX_type",
F.VALUE @ F.MC_VTX_TYPE @ F.MC_ORIGINVERTEX,
),
(
"Mother_KEY",
F.MAP(F.VALUE @ F.MC_MOTHER(1, F.OBJECT_KEY)),
),
)
vars_ = lambda prefix, index, source, named_vars: {
f"{prefix}_{label}[{index}]": F.FLATTEN
@ F.MAP(F.VALUE @ F.MAP(f) @ source)
@ F.MC_ALLPVS(mc_header=get_mc_header())
for label, f in named_vars
}
# functors to filter on prompt B and C hadrons
ancestors_if = (
lambda pred: F.FILTER(pred & F.IS_HADRON @ F.PARTICLE_ID_OBJ)
@ F.MC_VTX_PRODUCTS
)
# turn list of MC Particle into a single list of all of their descendants
desc = F.FLATTEN @ F.MAP(F.GET_ALL_DESCENDANTS)
evt_variables = FunctorCollection(
vars_("B_Ancestor", "ba_indx", ancestors_if(F.HAS_BOTTOM), ancestor_vars)
| vars_(
"B_Children", "bc_indx", desc @ ancestors_if(F.HAS_BOTTOM), children_vars
)
| vars_("C_Ancestor", "ca_indx", ancestors_if(F.HAS_CHARM), ancestor_vars)
| vars_(
"C_Children", "cc_indx", desc @ ancestors_if(F.HAS_CHARM), children_vars
)
)
# 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