1. Special Functors Fields

This tutorial shows how to add the same functors to all the fields in FunTuple by using the special field ALL. It can be split in few steps:

  1. Definition of a dictionary of {"field name" : "decay descriptor component"}.

  • For particle properties, names, etc checkout ParticleTable.txt that can be obtained via command

    $DVPATH/run dump_ParticleProperties -t Upgrade | tee ParticleTable.txt
    
  • For decay descriptor info see for example LoKiNewDecayFinders If your decay is self-tagged (which is the most common case) then you will need “[<decay-descriptor>]CC”

  1. Define a collection of functors called FunctorCollection, which takes dictionary of “variable name” -> “ThOr” functor (Can also be a “LoKi” functor see next tutorial). For more info on ThOr see the ThOr functors page For list of ThOr functors see the ThOr functors reference In this example a functor collection is added to “ALL” fields (Bs, Jpsi, Phi, etc)

  2. Define functors to be added only to Bs and Jpsi fields

  3. Use the “ALL” special field name

  4. Inspect the string representation of ThOr Functor. This string representation is converted to a C++ object using gcc or FunctorCache

  5. Finally there are the definition of the TES location, of a filter and the FunTuple instance.

import Functors as F
from DaVinci import Options, make_config
from DaVinci.algorithms import create_lines_filter
from PyConf.reading import get_particles
from FunTuple import FunctorCollection
from FunTuple import FunTuple_Particles as Funtuple


def main(options: Options):
    # Define a dictionary of "field name" -> "decay descriptor component".
    # - For particle properties, names, etc checkout "ParticleTable.txt"
    #   that can be obtained via command "$DVPATH/run dump_ParticleProperties -t Upgrade | tee ParticleTable.txt".
    # - For decay descriptor info see for example https://twiki.cern.ch/twiki/bin/view/LHCb/FAQ/LoKiNewDecayFinders
    #   If your decay is self-tagged (which is the most common case) then you will need "[<decay-descriptor>]CC"
    fields = {
        "Bs": "B_s0 -> (J/psi(1S) -> mu+ mu-) (phi(1020) ->K+ K-)",
        "Jpsi": "B_s0 -> ^(J/psi(1S) -> mu+ mu-) (phi(1020) ->K+ K-)",
        "Phi": "B_s0 ->  (J/psi(1S) -> mu+ mu-) ^(phi(1020) ->K+ K-)",
        "Mup": "B_s0 ->  (J/psi(1S) ->^mu+ mu-) (phi(1020) ->K+ K-)",
        "Mum": "B_s0 ->  (J/psi(1S) -> mu+ ^mu-) (phi(1020) ->K+ K-)",
        "Kp": "B_s0 ->  (J/psi(1S) -> mu+ mu-) (phi(1020) ->^K+ K-)",
        "Km": "B_s0 ->  (J/psi(1S) -> mu+ mu-) (phi(1020) ->K+ ^K-)",
    }

    # Define a collection of functors called FunctorCollection, which takes dictionary of "variable name" -> "ThOr" functor
    # (Can also be a "LoKi" functor see next tutorial).
    # For more info on ThOr see https://lhcbdoc.web.cern.ch/lhcbdoc/moore/master/selection/thor_functors.html#functor-cache
    # For list of ThOr functors see https://lhcbdoc.web.cern.ch/lhcbdoc/moore/master/selection/thor_functors_reference.html
    # Here we define functor collection to be added to "ALL" fields (Bs, Jpsi, Phi, etc)
    all_vars = FunctorCollection(
        {
            "THOR_P": F.P,  # ThOr momentum functor
            "ID": F.PARTICLE_ID,  # Refer to "ParticleTable.txt" for particle ID (see above on how to get this file)
        }
    )

    # Define functors to be added only to Bs and Jpsi fields
    bs_jpsi_fun = FunctorCollection({"PT_THOR": F.PT, "PX": F.PX, "PY": F.PY})

    # Define variables dictionary "field name" -> Collections of functor.
    # "ALL" is a special field name that adds PT to all the fields defined above (i.e. Bs,Jpsi,Mup,Mum,Kp,Km)
    variables = {
        "ALL": all_vars,
        "Bs": bs_jpsi_fun,
        "Jpsi": bs_jpsi_fun,
    }

    # Inspect string representation of ThOr Functor
    # This string representation is converted to C++ object
    # using gcc or FunctorCache see https://lhcbdoc.web.cern.ch/lhcbdoc/moore/master/selection/thor_functors.html#functors-in-a-selection-framework
    print(F.PT.code())
    # print(F.PT.headers())
    print(F.PT.code_repr())

    # Define the TES location (see previous example for explanation)
    turbo_line = "Hlt2B2CC_BsToJpsiPhi_Detached"
    input_data = get_particles(f"/Event/HLT2/{turbo_line}/Particles")

    # Define a filter (see previous example for explanation)
    my_filter = create_lines_filter("HDRFilter_SeeNoEvil", lines=[f"{turbo_line}"])

    # Define instance of FunTuple
    mytuple = Funtuple(
        "TDirectoryName",
        "TTreeName",
        # dictionary of particle : decay descriptor
        fields=fields,
        # dictionary of particle : variables to insert in TTree
        variables=variables,
        inputs=input_data,
    )

    config = make_config(options, [my_filter, mytuple])
    return config

To run the example:

lbexec DaVinciTutorials.tutorial1_functors_specialfield:main $DAVINCITUTORIALSROOT/options.yaml

For reference, these are the options of this example

input_files:
   - 'root://eoslhcb.cern.ch//eos/lhcb/wg/dpa/wp3/tests/hlt2_passthrough_thor_lines.dst'
input_manifest_file: 'root://eoslhcb.cern.ch//eos/lhcb/wg/dpa/wp3/tests/hlt2_passthrough_thor_lines.tck.json'
input_type: ROOT
evt_max: 100
ntuple_file: davinci_ntuple.root
input_process: TurboPass
print_freq: 1
simulation: True
lumi: False
conddb_tag: sim-20180530-vc-md100
dddb_tag: dddb-20180815
conditions_version: master
geometry_version: run3/trunk
persistreco_version: 0.0