MC Truth of unreconstructed particles
This example reads an HLT2 simulated sample and creates an ntuple with truth information about unreconstructed particles
import Functors as F
from FunTuple import FunctorCollection
from FunTuple import FunTuple_Particles as Funtuple
from DaVinci.algorithms import create_lines_filter
from DaVinci import make_config, Options
from DaVinciMCTools import MCTruthAndBkgCat
from PyConf.reading import get_particles
def main(options: Options):
# define fields
fields = {"Lb": "[Lambda_b0 -> (Lambda_c+ -> p+ K- pi+) mu-]CC"}
# get particles to run over
line_name = "Hlt2SLB_LbToLcMuNu_LcToPKPi_Line"
particles = get_particles(f"/Event/HLT2/{line_name}/Particles")
my_filter = create_lines_filter(name="Myfilter", lines=[f"{line_name}"])
# get configured "MCTruthAndBkgCatAlg" algorithm for HLT2 output
MCTRUTH = MCTruthAndBkgCat(particles, name="MCTruthAndBkgCat_info")
# define variables and add them to all fields
#
# In MCDecay case it is possible to use the simplified decay descriptor using
# only the direct products of the parent decay and omitting other descendants
# In this case we're interested into MC information about the unreconstructed neutrino
#
# A returning value of NaN is needed whenever the FIND_MCDECAY functor
# is not able to find any MC particle from the decay, because either none or more
# than one caret is passed to the DecayDescriptor
lc_px = (
F.VALUE_OR(F.NaN)
@ F.PX
@ F.FIND_MCDECAY("[ Lambda_b0 => ^Lambda_c+ mu- nu_mu~ ]CC")
)
mu_px = (
F.VALUE_OR(F.NaN)
@ F.PX
@ F.FIND_MCDECAY("[ Lambda_b0 => Lambda_c+ ^mu- nu_mu~ ]CC")
)
nu_px = (
F.VALUE_OR(F.NaN)
@ F.PX
@ F.FIND_MCDECAY("[ Lambda_b0 => Lambda_c+ mu- ^nu_mu~ ]CC")
)
lc_true_id = (
F.VALUE_OR(-1)
@ F.PARTICLE_ID
@ F.FIND_MCDECAY("[ Lambda_b0 => ^Lambda_c+ mu- nu_mu~ ]CC")
)
mu_true_id = (
F.VALUE_OR(-1)
@ F.PARTICLE_ID
@ F.FIND_MCDECAY("[ Lambda_b0 => Lambda_c+ ^mu- nu_mu~ ]CC")
)
nu_true_id = (
F.VALUE_OR(-1)
@ F.PARTICLE_ID
@ F.FIND_MCDECAY("[ Lambda_b0 => Lambda_c+ mu- ^nu_mu~ ]CC")
)
# A returning value of NaN is needed whenever MCAssocTable is empty
# i.e. has no relations inside
lb_variables = FunctorCollection(
{
"TRUEPX": MCTRUTH(F.PX),
"Lc_TRUEPX": F.VALUE_OR(F.NaN) @ MCTRUTH(lc_px),
"Mu_TRUEPX": F.VALUE_OR(F.NaN) @ MCTRUTH(mu_px),
"NuMu_TRUEPX": F.VALUE_OR(F.NaN) @ MCTRUTH(nu_px),
"Lc_TRUEID": F.VALUE_OR(-1) @ MCTRUTH(lc_true_id),
"Mu_TRUEID": F.VALUE_OR(-1) @ MCTRUTH(mu_true_id),
"NuMu_TRUEID": F.VALUE_OR(-1) @ MCTRUTH(nu_true_id),
# The ^ character denotes the particle, which should be treated as mother (first argument) or
# child (second argument), for which the helicity angle should be estimated
# PS: in the case of Lambda_b0, the ^ is not needed as it will be picked by default
# (as head of a decay chain)
"TRUE_COSTHETAH": MCTRUTH(
F.MC_COS_HELICITY_ANGLE(
"[Lambda_b0 -> (Lambda_c+ -> p+ K- pi+) mu-]CC",
"[Lambda_b0 -> (^Lambda_c+ -> p+ K- pi+) mu-]CC",
"[Lambda_b0 -> (Lambda_c+ -> ^p+ K- pi+) mu-]CC",
)
),
"COSTHETAH": F.COS_HELICITY_ANGLE(
"[Lambda_b0 -> (Lambda_c+ -> p+ K- pi+) mu-]CC",
"[Lambda_b0 -> (^Lambda_c+ -> p+ K- pi+) mu-]CC",
"[Lambda_b0 -> (Lambda_c+ -> ^p+ K- pi+) mu-]CC",
),
}
)
variables = {"Lb": lb_variables}
# define tupling algorithm
my_tuple = Funtuple(
name="Tuple",
tuple_name="DecayTree",
fields=fields,
variables=variables,
inputs=particles,
)
return make_config(options, [my_filter, my_tuple])
To run the example:
lbexec DaVinciExamples.tupling.option_davinci_tupling_unreconstructed_info:main $DAVINCIEXAMPLESROOT/example_data/Upgrade_LbToLcmunu.yaml
For reference, these are the options of this example
testfiledb_key: upgrade_LbToLcmunu
input_manifest_file: root://eoslhcb.cern.ch//eos/lhcb/wg/dpa/wp3/tests/Upgrade_LbToLcmunu.tck.json
input_raw_format: 0.5
ntuple_file: 'mytuple.root'
print_freq: 1
input_process: Hlt2
input_stream: default
evt_max: 7
persistreco_version: 0.0
lumi: False
write_fsr: False