4. Trigger and Event Information

To help users, there are pre-defined functor collections (Tuple-tool like objects for Run1/2 veterans) that you can import and inspect. Here we import a pre-defined FunctorCollection Kinematics via a module import. One can call print(help(Kinematics)) (you have to press q to exit after calling) to check the usage and their arguments. Functors that have data dependency will naturally induce data dependency on the functor collections.

To see what functor collections are available see FunTuple.functorcollections

The pre-defined FunctorCollections SelectionInfo and EventInfo are imported:

  • SelectionInfo: Contains functors related to storing Hlt1, Hlt2 or Sprucing trigger line decision and Trigger Configuration Key (TCK).

  • EventInfo: Contains functors related to storing event information BUNCHCROSSING_ID, etc. Note that RUNNUMBER and EVENTNUMBER are stored by default in FunTuple.

For further information one can call help with print(help(EventInfo)) or print(help(SelectionInfo)) (you have to press q to exit after calling)

With EventInfo one gets event information like RUNNUMBER and EVENTNUMBER. These are stored in LHCb::ODIN C++ object which the ThOr functors take as input (like PVs in Example7), and load into TES using get_odin. The attribute extra_info is False by default. When set to True one gets info on bunchcrossing id, ODIN TCK, GPS Time, etc.

SelectionInfo provides selection line decision and HlT2 TCK. These decisions are stored in LHCb::HltDecReports object, which the ThOr functors take as input (like PVs in Example7) and load into TES using get_decreports. The function get_decreports takes as input:

  • selection_type: Type of selection Hlt2 or Spruce

  • line_names: list of line decision in this instance HLT2 line. Should return True for all since we are using the output of this line.

The Hlt1 decisions can be stored in similar way to Hlt2 and Spruce (see for example option_trigger_decisions in DaVinciExamples folder). For details, one can also refer to this talk that shows how to persist Hlt1 decisions, since one needs to add few options to the Moore script.

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

# To help users, there are pre-defined functor collections (Tuple-tool like objects for Run1/2 veterans) that you can import and inspect.
# Here we import a pre-defined FunctorCollection "Kinematics" via a module import.
# One can call "print(help(Kinematics))" (you have to press "q" to exit after calling) to check the usage and their arguments.
# Functors that have data dependency will naturally induce data dependency on the functor collections.
#
# To see what functor collections are available see: https://gitlab.cern.ch/lhcb/Analysis/-/blob/master/Phys/FunTuple/python/FunTuple/functorcollections.py
import FunTuple.functorcollections as FC


def main(options: Options):
    # Define a dictionary of "field name" -> "decay descriptor component".
    fields = {"Bs": "B_s0 -> (J/psi(1S) -> mu+ mu-) (phi(1020) ->K+ K-)"}

    # Inspect what's in the collection by printing
    kin = FC.Kinematics()
    print(kin)

    # Define new collection
    coll = FunctorCollection({"ID": F.PARTICLE_ID})

    # Add to existing collections (can also subtract two collections)
    kin += coll

    # Remove from collections
    kin.pop(["PX", "PT", "PZ", "PY", "ENERGY"])
    print(kin)

    # Can also obtain a pure dictionary from collections via
    # - kin.functor_dict (Contains both LoKi and ThOr)
    # - kin.get_thor_functors()
    # - kin.get_loki_functors()
    print(kin.functor_dict)
    print(kin.get_thor_functors())
    # empty dictionary since we have no LoKi functors in the collection
    print(kin.get_loki_functors())

    # The two other pre-defined FunctorCollections SelectionInfo and EventInfo have been imported above
    # - SelectionInfo: Contains functors related to storing Hlt1, Hlt2 or Sprucing trigger line decision and Trigger Configuration Key (TCK).
    # - EventInfo: Contains functors related to storing event information BUNCHCROSSING_ID, etc. Note the RUNNUMBER and EVENTNUMBER
    #   are stored by default in FunTuple.
    #
    # As before you can call help with "print(help(EventInfo))" or "print(help(SelectionInfo))" (you have to press "q" to exit after calling)

    # Get event information like RUNNUMBER, EVENTNUMBER.
    # These are stored in "LHCb::ODIN" C++ object which the ThOr functors take as input (like PVs in Example7), load it onto TES using "get_odin".
    # The attribute extra_info is False by default, if set to "True" you get info on
    # bunchcrossing id, ODIN TCK, GPS Time, etc
    evtinfo = FC.EventInfo()
    print(evtinfo)

    # Get selection line decision and HlT2 TCK.
    # These decisions are stored in "LHCb::HltDecReports" object, which the ThOr functors take as input (like PVs in Example7), load it onto TES using "get_decreports".
    # The function "get_decreports" takes as input:
    #  - selection_type: Type of selection "Hlt2" or "Spruce"
    #  - line_names: list of line decision in this instance HLT2 line. Should return True for all since we are using the output of this line.
    #
    # The `Hlt1` decisions can be stored in similar way to `Hlt2` and `Spruce`
    # (see example `option_trigger_decisions` in `DaVinciExamples` folder).
    # For details, can also refer to the [talk](https://indico.cern.ch/event/1164051/#5-accessing-hlt1-decisions-usi)
    # (The talk mentions that to persist Hlt1 decisions, one needs to add few options to the Moore script).
    selection_type = (
        "Hlt2"  # User defined and will be used as prefix for TBranch in the root file
    )
    turbo_line = "Hlt2B2CC_BsToJpsiPhi_Detached"
    turbo_line2 = "Hlt2B2CC_BuToJpsiKplus_JpsiToMuMu_Prompt"
    line_names = [f"{turbo_line}Decision", f"{turbo_line2}"]
    selinfo = FC.SelectionInfo(selection_type=selection_type, trigger_lines=line_names)
    print(selinfo)

    # Define variables dictionary "field name" -> Collections of functor
    variables = {"ALL": kin}

    # Load data from dst onto a TES
    input_data = get_particles(f"/Event/HLT2/{turbo_line}/Particles")

    # Add a filter
    my_filter = create_lines_filter("HDRFilter_SeeNoEvil", lines=[f"{turbo_line}"])

    # Define instance of FunTuple
    mytuple = Funtuple(
        "TDirectoryName",
        "TTreeName",
        fields=fields,
        variables=variables,
        event_variables=evtinfo + selinfo,
        inputs=input_data,
    )

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

To run the example:

lbexec DaVinciTutorials.tutorial3_ThOrfunctors: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