DecayTreeFitter with SubstitutePID

This example shows how to use DecayTreeFitter with SubstitutePID. Two tuples are made. One with the signal mode \(B^0_s \to J/\psi \phi\) and another one with \(B^0 \to J/\psi K^*(892)\) background obtained by sustituting the id of a \(K\) with a \(\pi\).


from Gaudi.Configuration import INFO
from PyConf.reading import get_particles, get_pvs
import Functors as F
from DecayTreeFitter import DecayTreeFitter
from FunTuple import FunTuple_Particles as Funtuple
from FunTuple import FunctorCollection
from DaVinci.algorithms import create_lines_filter
from DaVinci import Options, make_config


def main(options: Options):
    B_Line = "Hlt2B2CC_BsToJpsiPhi_Detached"
    B_Data = get_particles(f"/Event/HLT2/{B_Line}/Particles")

    my_filter = create_lines_filter(name="HDRFilter_Bs2JpsiPhi", lines=[f"{B_Line}"])

    pvs = get_pvs()
    DTF_JpsiPhi = DecayTreeFitter(
        name="DTF_JpsiPhi",
        input_particles=B_Data,
        mass_constraints=["B_s0", "J/psi(1S)"],
        input_pvs=pvs,
        output_level=INFO,
    )

    DTF_JpsiKst = DecayTreeFitter(
        name="DTF_JpsiKst",
        input_particles=B_Data,
        input_pvs=pvs,
        substitutions=[
            "[ B_s0{{B0}} -> (J/psi(1S) -> mu+ mu-) (phi(1020){{K*(892)0}} -> K+  K-{{pi-}}) ]CC"
        ],
        mass_constraints=["B0", "J/psi(1S)"],
        output_level=INFO,
    )

    fields = {
        "Bs": "[ B_s0 -> (J/psi(1S) -> mu+ mu-) (phi(1020) -> K+ K-) ]CC",
        "Jpsi": "[ B_s0 -> ^(J/psi(1S) -> mu+ mu-) (phi(1020) -> K+ K-) ]CC",
        "Phi": "[ B_s0 -> (J/psi(1S) -> mu+ mu-) ^(phi(1020) -> K+ K-) ]CC",
        "MuP": "[ B_s0 -> (J/psi(1S) -> ^mu+ mu-) (phi(1020) -> K+ K-) ]CC",
        "MuM": "[ B_s0 -> (J/psi(1S) -> mu+ ^mu-) (phi(1020) -> K+ K-) ]CC",
        "KP": "[ B_s0 -> (J/psi(1S) -> mu+ mu-) (phi(1020) -> ^K+ K-) ]CC",
        "KM": "[ B_s0 -> (J/psi(1S) -> mu+ mu-) (phi(1020) -> K+ ^K-) ]CC",
    }

    variables_all = FunctorCollection(
        {
            # Original particle
            "ORIGINAL_ID": F.PARTICLE_ID,
            "ORIGINAL_M": F.MASS,
            "ORIGINAL_P": F.P,
            "ORIGINAL_ENERGY": F.ENERGY,
            "ORIGINAL_CHI2DOF": F.CHI2DOF,
            # DTF Bs2JpsiPhi
            "DTF_JpsiPhi_ID": F.VALUE_OR(-1) @ DTF_JpsiPhi(F.PARTICLE_ID),
            "DTF_JpsiPhi_M": DTF_JpsiPhi(F.MASS),
            "DTF_JpsiPhi_P": DTF_JpsiPhi(F.P),
            "DTF_JpsiPhi_ENERGY": DTF_JpsiPhi(F.ENERGY),
            "DTF_JpsiPhi_CHI2DOF": DTF_JpsiPhi(F.CHI2DOF),
            # DTF Bd2JpsiKst
            "DTF_JpsiKst_ID": F.VALUE_OR(-1) @ DTF_JpsiKst(F.PARTICLE_ID),
            "DTF_JpsiKst_M": DTF_JpsiKst(F.MASS),
            "DTF_JpsiKst_P": DTF_JpsiKst(F.P),
            "DTF_JpsiKst_ENERGY": DTF_JpsiKst(F.ENERGY),
            "DTF_JpsiKst_CHI2DOF": DTF_JpsiKst(F.CHI2DOF),
        }
    )

    variables = {"ALL": variables_all}

    # Configure Funtuple algorithm
    tuple_data = Funtuple(
        name="Bs2JpsiPhi_Tuple",
        tuple_name="DecayTree",
        fields=fields,
        variables=variables,
        inputs=B_Data,
    )

    # Run
    algs = {
        "Bs2JpsiPhi": [my_filter, tuple_data],
    }
    return make_config(options, algs)

To run the example:

lbexec DaVinciExamples.tupling.option_davinci_tupling_DTF_substitutePID:main $DAVINCIEXAMPLESROOT/example_data/test_passthrough_thor_lines.yaml

For reference, these are the options of this example

input_files:
- root://eoslhcb.cern.ch//eos/lhcb/wg/dpa/wp3/tests/logs/spruce_bsjpsiphi_passthrough_with_pv_pointer..dst
input_manifest_file: root://eoslhcb.cern.ch//eos/lhcb/wg/dpa/wp3/tests/logs/spruce_bsjpsiphi_passthrough_with_pv_pointer.tck.json
input_type: ROOT
simulation: true
conddb_tag: sim-20180530-vc-md100
dddb_tag: dddb-20180815
conditions_version: master
geometry_version: run3/trunk
histo_file: passthrough_histos.root
ntuple_file: passthrough_tuple.root
input_process: TurboPass
print_freq: 1000
persistreco_version: 0.0
lumi: False
write_fsr: False