Relation Tables and Isolation Variables

Example for testing the VertexAndConeIsolation tool and for applying ParticleIsolation and ConeIsolation functorcollection. The job runs over a Spruced sample and retrieves a set of \(B^0 \to K*(892)0 \tau \mu\) candidates. For each candidate the algorithm looks at the TES location which contains the selection of extra particles and creates a ‘one-to-many’ relation map relating all the available tracks to the isolated candidate of the events.

from GaudiKernel.SystemOfUnits import GeV
from PyConf.Algorithms import ThOrParticleSelection
from PyConf.reading import get_particles, get_pvs
import Functors as F
from IsolationTools import VertexAndConeIsolation
from Hlt2Conf.algorithms_thor import ParticleCombiner
from FunTuple import FunctorCollection, FunTuple_Particles as Funtuple
import FunTuple.functorcollections as FC
from DaVinci.algorithms import create_lines_filter
from DaVinci import Options, make_config


def main(options: Options):
    # Set branches
    branches = {
        "B": "[B0 -> ([J/psi(1S) -> tau+ mu-]CC)(K*(892)0 -> K+ pi-)]CC",
        "tau": "[B0 -> ([J/psi(1S) -> ^tau+ mu-]CC)(K*(892)0 -> K+ pi-)]CC",
        "mu": "[B0 -> ([J/psi(1S) -> tau+ ^mu-]CC)(K*(892)0 -> K+ pi-)]CC",
        "Kst": "[B0 -> ([J/psi(1S) -> tau+ mu-]CC)^(K*(892)0 -> K+ pi-)]CC",
    }

    # Helper lambda function get a filtered selection from all the descendants on the base of
    # the absolute id of the particle
    FILTER_TREE = lambda id: F.FILTER(F.IS_ABS_ID(id)) @ F.GET_ALL_DESCENDANTS()

    # list of saved locations
    b2ksttaumu_line = "Hlt2RD_BdToKstTauMu_KstToKPi_TauTo3Pi_OS"
    long_track_iso = "LongTrackIsolation"
    neutral_iso = "NeutralIsolation"

    # Get the selection of B and children candidates
    b2ksttaumu_data = get_particles(f"/Event/HLT2/{b2ksttaumu_line}/Particles")
    b2ksttaumu_kst_data = ThOrParticleSelection(
        InputParticles=b2ksttaumu_data, Functor=FILTER_TREE("K*(892)0")
    ).OutputSelection
    b2ksttaumu_tau_data = ThOrParticleSelection(
        InputParticles=b2ksttaumu_data, Functor=FILTER_TREE("tau+")
    ).OutputSelection
    b2ksttaumu_mu_data = ThOrParticleSelection(
        InputParticles=b2ksttaumu_data, Functor=FILTER_TREE("mu-")
    ).OutputSelection

    # Get the extra particles selected
    b_cciso_data = get_particles(
        f"/Event/HLT2/{b2ksttaumu_line}/B_{long_track_iso}/Particles"
    )
    kst_cciso_data = get_particles(
        f"/Event/HLT2/{b2ksttaumu_line}/Kst_{long_track_iso}/Particles"
    )
    tau_cciso_data = get_particles(
        f"/Event/HLT2/{b2ksttaumu_line}/tau_{long_track_iso}/Particles"
    )
    mu_cciso_data = get_particles(
        f"/Event/HLT2/{b2ksttaumu_line}/mu_{long_track_iso}/Particles"
    )
    b_nciso_data = get_particles(
        f"/Event/HLT2/{b2ksttaumu_line}/B_{neutral_iso}/Particles"
    )
    kst_nciso_data = get_particles(
        f"/Event/HLT2/{b2ksttaumu_line}/Kst_{neutral_iso}/Particles"
    )
    tau_nciso_data = get_particles(
        f"/Event/HLT2/{b2ksttaumu_line}/tau_{neutral_iso}/Particles"
    )
    mu_nciso_data = get_particles(
        f"/Event/HLT2/{b2ksttaumu_line}/mu_{neutral_iso}/Particles"
    )

    variables_all = FunctorCollection({"THOR_P": F.P, "THOR_PT": F.PT})

    ## CONE ISOLATION EXAMPLE: Charged and neutral
    #
    # Create an instance of 'VertexAndConeIsolation' for B charge isolation with dr=0.5
    b_charge_iso = VertexAndConeIsolation(
        name="BIso05",
        reference_particles=b2ksttaumu_data,
        related_particles=b_cciso_data,
        cut=(F.SQRT @ F.DR2 < 0.5),
    )
    # Create an instance of 'VertexAndConeIsolation' for B neutral isolation with dr=1.
    b_neutral_iso = VertexAndConeIsolation(
        name="BIso10",
        reference_particles=b2ksttaumu_data,
        related_particles=b_nciso_data,
        cut=(F.SQRT @ F.DR2 < 1.0),
    )

    # Add charge isolation variables with max dr=0.5 and neutral isolation variables with max dr=1 using ConeIsolation functorcollection
    b_cone_iso_variables = FC.ConeIsolation(
        charged_cone_isolation_alg=b_charge_iso,
        neutral_cone_isolation_alg=b_neutral_iso,
        array_indx_name="B_cone_indx",
    )

    # Create an instance of 'VertexAndConeIsolation' for B charge isolation with dr=0.5
    tau_charge_iso = VertexAndConeIsolation(
        name="TauIso05",
        reference_particles=b2ksttaumu_tau_data,
        related_particles=tau_cciso_data,
        cut=(F.SQRT @ F.DR2 < 0.5),
    )
    # Create an instance of 'VertexAndConeIsolation' for B neutral isolation with dr=1.
    tau_neutral_iso = VertexAndConeIsolation(
        name="TauIso10",
        reference_particles=b2ksttaumu_tau_data,
        related_particles=tau_nciso_data,
        cut=(F.SQRT @ F.DR2 < 1.0),
    )

    # Add charge isolation variables with max dr=0.5 and neutral isolation variables with max dr=1 using ConeIsolation functorcollection
    tau_cone_iso_variables = FC.ConeIsolation(
        charged_cone_isolation_alg=tau_charge_iso,
        neutral_cone_isolation_alg=tau_neutral_iso,
        array_indx_name="Tau_cone_indx",
    )

    # Create an instance of 'VertexAndConeIsolation' for mu charge isolation with dr=0.5
    mu_charge_iso = VertexAndConeIsolation(
        name="MuIso05",
        reference_particles=b2ksttaumu_mu_data,
        related_particles=mu_cciso_data,
        cut=(F.SQRT @ F.DR2 < 0.5),
    )
    # Create an instance of 'VertexAndConeIsolation' for mu neutral isolation with dr=1.
    mu_neutral_iso = VertexAndConeIsolation(
        name="MuIso10",
        reference_particles=b2ksttaumu_mu_data,
        related_particles=mu_nciso_data,
        cut=(F.SQRT @ F.DR2 < 1.0),
    )

    # Add charge isolation variables with max dr=0.5 and neutral isolation variables with max dr=1 using ConeIsolation functorcollection
    mu_cone_iso_variables = FC.ConeIsolation(
        charged_cone_isolation_alg=mu_charge_iso,
        neutral_cone_isolation_alg=mu_neutral_iso,
        array_indx_name="mu_cone_indx",
    )

    # Create an instance of 'VertexAndConeIsolation' for Kst charge isolation with dr=0.5
    kst_charge_iso = VertexAndConeIsolation(
        name="KstIso05",
        reference_particles=b2ksttaumu_kst_data,
        related_particles=kst_cciso_data,
        cut=(F.SQRT @ F.DR2 < 0.5),
    )
    # Create an instance of 'VertexAndConeIsolation' for Kst neutral isolation with dr=1.
    kst_neutral_iso = VertexAndConeIsolation(
        name="KstIso10",
        reference_particles=b2ksttaumu_kst_data,
        related_particles=kst_nciso_data,
        cut=(F.SQRT @ F.DR2 < 1.0),
    )

    # Add charge isolation variables with max dr=0.5 and neutral isolation variables with max dr=1 using ConeIsolation functorcollection
    kst_cone_iso_variables = FC.ConeIsolation(
        charged_cone_isolation_alg=kst_charge_iso,
        neutral_cone_isolation_alg=kst_neutral_iso,
        array_indx_name="Kst_cone_indx",
    )

    pvs = get_pvs()

    # Other examples of different requirements applied for the isolation
    # Change the selection requirement to make different relations
    # Instantiate the Isolation tool with different configurations
    b_fixpv_iso = VertexAndConeIsolation(
        name="BIsoFixPV",
        reference_particles=b2ksttaumu_data,
        related_particles=b_cciso_data,
        cut=(F.SHARE_BPV(pvs) | (F.MINIPCHI2CUT(pvs, 9.0) @ F.FORWARDARG1())),
    )

    b_fix_pv_iso_variables = FC.ParticleIsolation(
        isolation_alg=b_fixpv_iso, array_indx_name="B_FixPV_indx"
    )

    b_mass_constraint_iso = VertexAndConeIsolation(
        name="BIsoMassConstraint",
        reference_particles=b2ksttaumu_data,
        related_particles=b_nciso_data,
        cut=(F.COMB_MASS() < 8 * GeV),
    )

    b_mass_constraint_iso_variables = FC.ParticleIsolation(
        isolation_alg=b_mass_constraint_iso, array_indx_name="B_MassConstraint_indx"
    )

    ## VERTEX ISOLATION EXAMPLE
    #
    # Create candidates adding one extra particle to the composite
    b_vtxiso_onetrack_data = ParticleCombiner(
        [b2ksttaumu_data, b_cciso_data],
        name="One_extra_track_combination",
        DecayDescriptor="[B*+ -> B0 pi+]cc",
        CombinationCut=F.ALL,
        CompositeCut=F.ALL,
    )

    # Create candidates adding two extra particles to the composite
    b_vtxiso_twotracks_data = ParticleCombiner(
        [b2ksttaumu_data, b_cciso_data, b_cciso_data],
        name="Two_extra_tracks_combination",
        DecayDescriptor="[B*0 -> B0 pi+ pi-]cc",
        CombinationCut=F.ALL,
        CompositeCut=F.ALL,
    )

    # Add vertex isolation variables with one and two tracks
    b_vtxiso_onetrack = VertexAndConeIsolation(
        name="OneTrack",
        reference_particles=b2ksttaumu_data,
        related_particles=b_vtxiso_onetrack_data,
        cut=(F.CHI2() @ F.FORWARDARG1() < 9.0),
    )

    b_vtxiso_twotracks = VertexAndConeIsolation(
        name="TwoTracks",
        reference_particles=b2ksttaumu_data,
        related_particles=b_vtxiso_twotracks_data,
        cut=(F.CHI2() @ F.FORWARDARG1() < 15.0),
    )

    b_vtxiso_onetrack_variables = FC.VertexIsolation(isolation_alg=b_vtxiso_onetrack)

    b_vtxiso_twotracks_variables = FC.VertexIsolation(isolation_alg=b_vtxiso_twotracks)

    # Add variables to the branches
    variables = {
        "B": variables_all
        + b_cone_iso_variables
        + b_fix_pv_iso_variables
        + b_mass_constraint_iso_variables
        + b_vtxiso_onetrack_variables
        + b_vtxiso_twotracks_variables,
        "tau": variables_all + tau_cone_iso_variables,
        "mu": variables_all + mu_cone_iso_variables,
        "Kst": variables_all + kst_cone_iso_variables,
    }

    my_filter = create_lines_filter(
        name="HDRFilter_BdToKstTauMu", lines=[f"{b2ksttaumu_line}"]
    )
    my_tuple = Funtuple(
        name="Tuple",
        tuple_name="DecayTree",
        fields=branches,
        variables=variables,
        inputs=b2ksttaumu_data,
    )
    return make_config(options, [my_filter, my_tuple])

To run the example:

lbexec DaVinciExamples.tupling.option_davinci_tupling_relation_isovariables:main $DAVINCIEXAMPLESROOT/example_data/hlt2_b2ksttaumu_opt.yaml

For reference, these are the options of this example

input_files:
- root://eoslhcb.cern.ch//eos/lhcb/wg/dpa/wp3/tests/b_to_ksttaumu_test_isolation.dst
input_manifest_file: root://eoslhcb.cern.ch//eos/lhcb/wg/dpa/wp3/tests/b_to_ksttaumu_test_isolation.tck.json
input_type: ROOT
evt_max: -1
ntuple_file: b_to_ksttaumu_test_isolation.root
print_freq: 20
simulation: true
conddb_tag: sim-20180530-vc-mu100
dddb_tag: dddb-20190223
conditions_version: master
geometry_version: run3/trunk
input_process: Hlt2