Making ntuples from Turbo data

This page shows you how to configure DaVinci to process Turbo data.

Note: This pages discusses processing Run 2 (20152018) data. Please see the Moore documentation for processing Run 3 data.

Due to the historical development cycle of the Turbo processing model, the format of Turbo data has changed from 2015 to 2016 and again from 2016 to 2017. Although a stable DaVinci configuration is always a priority for the Turbo developers, some changes are required when analysing datasets from different years.

The sections below are organised per year, and are standalone after reading the introduction.


It is expected that any TupleTool that works on a microDST Stripping output will work with Turbo data.

In what follows, it is assumed that the DecayTreeTuple to be configured has been instantiated as dtt:

from Configurables import DecayTreeTuple
from DecayTreeTuple import Configuration

dtt = DecayTreeTuple(...)

An example HLT2 Turbo line is assumed, available as hlt2_line:

hlt2_line = 'Hlt2CharmHadD02KmPipTurbo'

2015, 2016, 2017, and 2018 data

In general, the latest DaVinci version is recommended, but anything past v44r3 should be sufficient for both collision data and MC.

You must set the following properties on the DaVinci() configurable for both Turbo and TurCal data:

DaVinci().InputType = 'MDST'
DaVinci().RootInTES = '/Event/<stream_name>/Turbo'
DaVinci().Turbo = True

The stream_name is the name of the stream, like CHARMSPEC or LEPTONS, but in lowercase with the first letter capitalised, like Charmspec or Leptons. In 2015, 2016, and Monte Carlo (simulation) the stream_name is always empty, so the RootInTES is just /Event/Turbo.

An example of a full location of Particle objects in 2017 is:


However, input locations to algorithms should be relative to the RootInTES property, e.g. for a DecayTreeTuple:

dtt.Inputs = ['{0}/Particles'.format(hlt2_line)]
# ...
DaVinci().RootInTES = '/Event/Charmspec/Turbo'

Monte Carlo truth

To get Monte Carlo truth information, add TupleToolMCTruth and TupleToolMCBackgroundInfo to the DecayTreeTuple ToolList as usual.

dtt.ToolList += [

Then, add the following to your options:

from TeslaTools import TeslaTruthUtils

relations = TeslaTruthUtils.getRelLocs() + [
    # Location of the truth tables for PersistReco objects
mc_tools = [
      # ...and any other tools you'd like to use
TeslaTruthUtils.makeTruth(dtt, relations, mc_tools)

This is necessary because the MC relations tables for Turbo data are in a non-standard location. The configuration for 2015 data is slightly different.

Note that if you are using the Modern Selection Framework, e.g., TupleSelection, instead of a DecayTreeTuple you will need to pass it as dtt.algorithm() instead to avoid a TypeError:

# DaVinci                   INFO    Append to Main Sequence has been called
Traceback (most recent call last):
  File "/cvmfs/", line 525, in <module>
    exec (o, g, l)
  File "<string>", line 1, in <module>
  File "/workspace/build/GAUDI/GAUDI_v32r1/InstallArea/x86_64-centos7-gcc8-opt/python/GaudiKernel/", line 490, in importOptions
  File "/workspace/build/GAUDI/GAUDI_v32r1/InstallArea/x86_64-centos7-gcc8-opt/python/GaudiKernel/", line 458, in _import_python
  File "/afs/", line 529, in <module>
    TeslaTruthUtils.makeTruth(tup, relations, mc_tools)
  File "/workspace/build/PHYS/PHYS_v26r2/InstallArea/x86_64-centos7-gcc8-opt/python/TeslaTools/", line 80, in makeTruth
  File "/workspace/build/PHYS/PHYS_v26r2/InstallArea/x86_64-centos7-gcc8-opt/python/PhysSelPython/", line 1531, in addTool
  File "/workspace/build/PHYS/PHYS_v26r2/InstallArea/x86_64-centos7-gcc8-opt/python/PhysSelPython/", line 1525, in addTupleTool
  File "/workspace/build/ANALYSIS/ANALYSIS_v21r2/InstallArea/x86_64-centos7-gcc8-opt/python/DecayTreeTuple/", line 68, in addTupleTool
TypeError: You are trying to add a default public tool-configurable to your ntuple: TupleToolMCTruth/TupleToolMCTruth This is dangerous so not allowed with addTTool. Either add it yourself manually, or, better, supply an instance name

LoKi functors

To use LoKi functors that require Monte Carlo truth matching, you similarly need to set the location of the relations tables. When using the mcMatch functor, this location can be passed as the second argument to the functor:

loki_tt = dtt.addTupleTool('LoKi::Hybrid::TupleTool/SomeName')
loki_tt.Preambulo = [
    'from LoKiPhysMC.decorators import *',
    'from LoKiPhysMC.functions import mcMatch'
# Use the (assumed existing) decay descriptor on the DecayTreeTuple to build
# a MC-matching descriptor
# The use of the DecayTreeTuple descriptor and of the '==>' arrow is
# not always valid for every analysis, this is just an example; be careful!
mc_decay_descriptor = dtt.Decay.replace('^', '').replace('->', '==>')
loki_tt.Variables = {
    'mcMatch' : 'switch(mcMatch({0!r}, {1!r}), 1, 0)'.format(mc_decay_descriptor, relations)

Where the relations variable is as defined above.


When an HLT2 line has the PersistReco flag enabled, the full HLT2 reconstruction is available in events where that line fired.

The Track objects are made available at /Event/Turbo/Rec/Track/Best, and the ProtoParticle objects are made available under /Event/Turbo/Rec/ProtoP/Charged. The rest of the reconstruction is under /Event/Turbo/Hlt2. Primary vertices are under /Event/Turbo/Primary as usual, but the associated VELO tracks also exist for PersistReco events.

The family of Std* particles, like StdAllPions, should be rebuilt using the Python Selection framework. The following example shows how one can take the output of a $D^{0} \rightarrow K^{-}\pi^{+}$ Turbo line and combine it with a PersistReco pion:

from PhysSelPython.Selections import (
from StandardParticles import StdAllLooseANNPions

combiner_sel = CombineSelection(
        # The output of the HLT2 line
        # Extra pions
      'D*(2010)+ -> D0 pi+',
      'D*(2010)- -> D0 pi-'
        'pi+': 'PROBNNpi > 0.2'
      'in_range(0, (AM - AM1 - AM2), 170)'
      '(VFASPF(VCHI2PDOF) < 10) &'
      'in_range(0, (M - M1 - M2), 150)'
selseq = SelectionSequence( + 'Sequence',

You can then add the full selection to some sequence with selseq.sequence(), getting the output particle location using sel.outputLocation(). For example:

dtt = DecayTreeTuple(...)
dtt.Inputs = [combiner_sel.outputLocation()]
# ...
DaVinci().UserAlgorithms = [selseq.sequence(), dtt]

Exact clones in particle combinations in 2016 data

Due to some technicalities, you will see exact clones when trying to perform particle combinatorics with 2016 Turbo+PersistReco data. This means that the same underlying Track object is used twice in the same combination, and is an issue because it can create unphysical peaking structures in mass distributions.

As an example, assume your Turbo candidate (the object that fired your HLT2 line) is $J/\psi \to \mu^{+}\mu^{-}$. The HLT2 line has PersistReco enabled, and you want to reconstruct $B^{+} \to J/\psi K^{+}$, taking the $J/\psi$ Turbo candidate and kaons from StdLooseKaons. With the default configuration of CombineParticles, you will end up saving $B^{+}$ candidates where the same track is used for the $\mu^{+}$ and the $K^{+}$, meaning that the 3-momenta of the two particles will be identical.

To avoid this issue, you can configure CombineParticles to perform a more robust overlap check:

my_combiner = CombineParticles(

2015 and 2016 data

If you see errors like this when processing data:

Hlt2PackedDataD...WARNING HltPackedDataDecoder:: No HltPackedData raw bank (the DstData bank) in raw event. Quitting.
LinkHltPersistR...WARNING Gaudi::DataLink:: No valid data is found at '/Event/Hlt2/Vertex/PV3D'
LoKiSvc.REPORT    WARNING The WARNING message is suppressed : 'LoKi::Vertices::SourceDesktop:    No input primary vertices from IDVAlgorithm [myalg]' StatusCode=FAILURE
LoKiSvc.REPORT    WARNING The WARNING message is suppressed : 'LoKi::Vertices::SourceDesktop:    No vertices are selected by 'PRIMARY' [myalg]' StatusCode=FAILURE
LoKiSvc.REPORT      ERROR The   ERROR message is suppressed : 'LoKi::Particles::MinImpParChi2DV:        Empty list of vertices is loaded! [myalg]' StatusCode=FAILURE

then one or more algorithms or tools are trying to access primary vertices directly from the Brunel location, rather than going via the Particle-to-PV relations tables created in HLT2 which point to the Turbo location.

In this case, algorithms and tools must be explicitly configured to pick up the Turbo primary vertices. The Turbo-specific DecayTreeTuple configuration will look like this:

dtt.Inputs = ['{0}/Particles'.format(hlt2_line)]
dtt.InputPrimaryVertices = '/Event/Turbo/Primary'

If your line had PV refitting enabled, and you wish to use the refitted PVs, change InputPrimaryVertices to point to the corresponding location.

Monte Carlo truth

This is similar to the procedure for 2016+ data, but the list of relations locations is specified differently:

relations = [TeslaTruthUtils.getRelLoc(hlt2_line + '/')]

EDIT: in a later production (Sim09i) truth-matching worked with [TeslaTruthUtils.getRelLoc('')] only.


The information on the RelatedInfo can be accessed through e.g. a LoKi functor, but be aware that you have to repeat the full location, without accounting for the RootInTES. In 2017, the related info was not saved correctly, as is described in This JIRA task.

Efficient processing

As for any other DaVinci job, it is recommended that you stop processing an event as soon as possible in order to reduce CPU time. A good way to acheive this with Turbo data is to filter out events that don't contain a positive decision for your trigger(s).

from PhysConf.Filters import LoKi_Filters

trigger_filter = LoKi_Filters(
    # Adjust this regular expression to match whatever set of lines you're
    # interested in studying

DaVinci().EventPreFilters = trigger_filter.filters('TriggerFilter')

This prevents expensive unpacking algorithms running on events where your candidates don't exist. It also prevents warnings like these from occurring:

Hlt2PackedDataD...WARNING HltPackedDataDecoder:: No HltPackedData raw bank (the DstData bank) in raw event. Quitting

If you see these warnings when using an event prefilter on Turbo lines, something is likely wrong with the input data.

Edit | Attach | Watch | Print version | History: r28 < r27 < r26 < r25 < r24 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r28 - 2021-08-30 - AlexPearce
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    LHCb All webs login

This site is powered by the TWiki collaboration platform Powered by PerlCopyright & 2008-2022 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
or Ideas, requests, problems regarding TWiki? use Discourse or Send feedback