diff --git a/D02HH/README.md b/D02HH/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..b7b157c17a275286683249503e547dfaaa6e6d4f
--- /dev/null
+++ b/D02HH/README.md
@@ -0,0 +1,14 @@
+# AnalysisProductions options for $` D^{0}\rightarrow h^+ h^- `$
+
+The options contained in this directory generate the NTuples for the simulation
+of prompt $` D^{\ast+} \rightarrow (D^{0}\rightarrow h^+ h^-) \pi^{+}_{tag} `$
+decays (for both standard and LTUNB triggers),
+with $` h^+ h^- = K^- \pi^+,\; K^+ K^-,\; \pi^+ \pi^-,\; K^+ \pi^- `$.
+
+General features:
+  * `DecayTreeFitter` algorithm applied to the $` D^{\ast+} `$ decay chain
+     w/ the PV constraint, w/ and w/o the $` D^{0} `$ mass constraint;
+  * combination of the RS prompt sample with a `PersistReco` muon to be used
+    as proxy for secondary decays;
+  * momentum scaling of all particles, except the persisted muons of the prompt
+    sample.
diff --git a/D02HH/info.yaml b/D02HH/info.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a40dfdae45a86f4314910f1838bbb6e93067d9c3
--- /dev/null
+++ b/D02HH/info.yaml
@@ -0,0 +1,54 @@
+checks:
+    RSdeltaM:
+        type: range
+        tree_pattern: RS_DT_Tuple/RS_DT
+        expression: B_DTF_Dst_M-B_DTF_D0_M
+        limits:
+            min: 139
+            max: 155
+        n_bins: 100
+    WSdeltaM:
+        type: range
+        tree_pattern: WS_DT_Tuple/WS_DT
+        expression: B_DTF_Dst_M-B_DTF_D0_M
+        limits:
+            min: 139
+            max: 155
+        n_bins: 100
+
+defaults:
+    application: DaVinci/v46r3
+    automatically_configure: yes
+    turbo: yes
+    options:
+        - make_ntuples.py
+    output: CHARM_D02HH_DVNTUPLE.ROOT
+    wg: Charm
+    inform:
+        - aodhan.burke@cern.ch
+
+
+{% for polarity in ["MagDown", "MagUp"] %}
+
+D02HH_2016_{{polarity}}_11774014:
+    checks:
+        - RSdeltaM
+        - WSdeltaM
+    input:
+        bk_query: "/MC/2016/Beam6500GeV-2016-{{polarity}}-Nu1.6-25ns-Pythia8/Sim09l-ReDecay01/Trig0x6139160F/Reco16/Turbo03a/Stripping28r2NoPrescalingFlagged/Turbo03aFiltered/11774014/D02HH.HLTFILTER.MDST"
+
+D02HH_2017_{{polarity}}_11774014:
+    checks:
+        - RSdeltaM
+        - WSdeltaM
+    input:
+        bk_query: "/MC/2017/Beam6500GeV-2017-{{polarity}}-Nu1.6-25ns-Pythia8/Sim09l-ReDecay01/Trig0x62661709/Reco17/Turbo04a-WithTurcal/Stripping29r2NoPrescalingFlagged/Turbo04aFiltered/11774014/D02HH.HLTFILTER.MDST"
+
+D02HH_2018_{{polarity}}_11774014:
+    checks:
+        - RSdeltaM
+        - WSdeltaM
+    input:
+        bk_query: "/MC/2018/Beam6500GeV-2018-{{polarity}}-Nu1.6-25ns-Pythia8/Sim09l-ReDecay01/Trig0x617d18a4/Reco18/Turbo05-WithTurcal/Stripping34NoPrescalingFlagged/Turbo05Filtered/11774014/D02HH.HLTFILTER.MDST"
+
+{% endfor %}
diff --git a/D02HH/make_ntuples.py b/D02HH/make_ntuples.py
new file mode 100644
index 0000000000000000000000000000000000000000..f04177b869c7526ae5afffe7ec0ea20888117d7d
--- /dev/null
+++ b/D02HH/make_ntuples.py
@@ -0,0 +1,473 @@
+
+
+
+
+from copy import copy
+
+from Configurables import (
+        DaVinci,
+        GaudiSequencer,
+        ChargedProtoANNPIDConf,
+        LoKi__Hybrid__Dict2Tuple,
+        LoKi__Hybrid__DictOfFunctors)
+from Configurables import LoKi__Hybrid__DTFDict as DTFDict
+from Configurables import DecayTreeTuple
+from DecayTreeTuple.Configuration import *
+
+from PhysConf.Selections import (AutomaticData, MomentumScaling,
+                                 RebuildSelection, SelectionSequence,
+                                 CombineSelection)
+from PhysConf.Filters import LoKi_Filters
+from StandardParticles import StdAllLooseMuons
+from TeslaTools import TeslaTruthUtils
+
+
+DaVinci().Turbo = True
+if DaVinci().Simulation or DaVinci().DataType == "2015" or DaVinci().DataType == "2016":
+    DaVinci().RootInTES = '/Event/Turbo'
+else:
+    DaVinci().RootInTES = "/Event/Charmtwobody/Turbo"
+
+
+# prompt
+hh_keys = {
+        'KK': 'KmKp',
+        'PP': 'PimPip',
+        'RS': 'KmPip',
+        'WS': 'KpPim'
+}
+# semi-leptonic
+hh_keys_SL = {
+        'KK_SL': 'KmKp',
+        'PP_SL': 'PimPip',
+        'KP_SL': 'KmPip'
+}
+# doubly-tagged
+hh_keys_DT = {
+        'KK_DT' : 'KmKp',
+        'PP_DT' : 'PimPip',
+        'KP_DT' : 'KmPip'
+}
+
+
+hlt2_lines = {
+        '{k}{ltunb}'.format(k=k, ltunb=ltunb):
+        'Hlt2CharmHadDstp2D0Pip_D02{hh}{ltunb}Turbo'.format(hh=hh, ltunb=ltunb)
+        for k, hh in list(hh_keys.items())
+        for ltunb in ['', '_LTUNB']}
+hlt2_lines.update({
+        '{k}'.format(k=k):
+        'Hlt2SLB_B2D0Mu_D02{hh}Turbo'.format(hh=hh)
+        for k, hh in list(hh_keys_SL.items())
+})
+hlt2_lines.update({
+        '{k}'.format(k=k):
+        'Hlt2SLB_B2DstMu_D02{hh}Turbo'.format(hh=hh)
+        for k, hh in list(hh_keys_DT.items())
+})
+
+# https://twiki.cern.ch/twiki/bin/view/LHCb/RefitTracksFromDST#Momentum_Scale_correction
+particles = {k: AutomaticData('{hlt2_line}/Particles'.format(hlt2_line=hlt2_line))
+             for k, hlt2_line in list(hlt2_lines.items())}
+if not DaVinci().Simulation:
+    for k in list(particles.keys()):
+        particles[k] = MomentumScaling(
+                particles[k], Turbo=True, Year=DaVinci().DataType)
+
+# make (D*+ mu) combinations (proxy of secondary decays)
+muons = RebuildSelection(StdAllLooseMuons)
+dst_mu = CombineSelection(
+        'DstMu',
+        inputs=[RebuildSelection(StdAllLooseMuons), particles['RS']],
+        DecayDescriptors=['[B0 -> D*(2010)+ mu-]cc',
+                          '[B0 -> D*(2010)+ mu+]cc'],
+        DaughtersCuts={
+                'D*(2010)+': 'ALL',
+                'D*(2010)-': 'ALL',
+                'mu-': '(PT > 800.0*MeV) & (P > 3.0*GeV) & (TRGHOSTPROB < 0.5) '
+                       '& (TRCHI2DOF < 5.0) & (MIPCHI2DV(PRIMARY) > 4.0)',
+                'mu+': '(PT > 800.0*MeV) & (P > 3.0*GeV) & (TRGHOSTPROB < 0.5) '
+                       '& (TRCHI2DOF < 5.0) & (MIPCHI2DV(PRIMARY) > 4.0)'},
+        CombinationCut='(AM > 2.0*GeV) & (AM < 10.0*GeV)',
+        MotherCut=('(VFASPF(VCHI2/VDOF) < 25) & (BPVDIRA> 0.999) &'
+                   '(M > 3.0*GeV) & (M < 8.0*GeV)')
+)
+if DaVinci().DataType == '2015' or DaVinci().DataType == '2016':
+    dst_mu.InputPrimaryVertices = 'Primary'
+if DaVinci().DataType == '2016' and not DaVinci().Simulation:
+    # https://twiki.cern.ch/twiki/bin/view/LHCb/MakeNTupleFromTurbo#Exact_clones_in_particle_combina
+    dst_mu.CheckOverlapTool = 'LoKi::CheckOverlap'
+dst_mu_sequence = SelectionSequence('DstMuSequence', TopSelection=dst_mu)
+particles['Mu'] = dst_mu_sequence
+
+
+tuple_keys = {k:k for k in list(hlt2_lines.keys()) if 'KP' not in k}
+tuple_keys.update({
+    'Mu': 'Mu',
+    'RS_SL': 'KP_SL',
+    'WS_SL': 'KP_SL',
+    'RS_DT': 'KP_DT',
+    'WS_DT': 'KP_DT'
+})
+
+
+inputs = { k : particles[tuple_keys[k]] for k in tuple_keys.keys() }
+
+
+# https://twiki.cern.ch/twiki/bin/view/LHCb/EnsureProbNNsCalculated
+probnn_sequence = {}
+for k, v in list(hlt2_lines.items()):
+    probnn_sequence[k] = GaudiSequencer('{0}_ProbNNSeq'.format(k))
+    annpid = ChargedProtoANNPIDConf(
+        k + 'ProbNNalg',
+        RecoSequencer=probnn_sequence[k],
+        ProtoParticlesLocation='{0}/Protos'.format(v)
+    )
+
+
+# K- pi+, K+ K-, pi+ pi- are reconstructed only as D0
+# https://gitlab.cern.ch/lhcb/Hlt/blob/2018-patches/Hlt/Hlt2Lines/python/Hlt2Lines
+#   - CharmHad/D02HHLines.py
+#   - SLB/Lines.py
+decay_descriptors = {
+      "KK_LTUNB": "        ${Dst}[D*(2010)+ -> ${D0}([D0]cc -> ${P1}K+  ${P2}K- ) ${sPi}pi+]CC",
+      "PP_LTUNB": "        ${Dst}[D*(2010)+ -> ${D0}([D0]cc -> ${P1}pi+ ${P2}pi-) ${sPi}pi+]CC",
+      "RS_LTUNB": "        ${Dst}[D*(2010)+ -> ${D0}(D0     -> ${P1}K-  ${P2}pi+) ${sPi}pi+]CC",
+      "WS_LTUNB": "        ${Dst}[D*(2010)- -> ${D0}(D0     -> ${P1}K-  ${P2}pi+) ${sPi}pi-]CC",
+      "KK": "              ${Dst}[D*(2010)+ -> ${D0}([D0]cc -> ${P1}K+  ${P2}K- ) ${sPi}pi+]CC",
+      "PP": "              ${Dst}[D*(2010)+ -> ${D0}([D0]cc -> ${P1}pi+ ${P2}pi-) ${sPi}pi+]CC",
+      "RS": "              ${Dst}[D*(2010)+ -> ${D0}(D0     -> ${P1}K-  ${P2}pi+) ${sPi}pi+]CC",
+      "WS": "              ${Dst}[D*(2010)- -> ${D0}(D0     -> ${P1}K-  ${P2}pi+) ${sPi}pi-]CC",
+      "Mu": "   ${B}[Xb -> ${Dst}(D*(2010)+ -> ${D0}(D0     -> ${P1}K-  ${P2}pi+) ${sPi}pi+) ${Mu}[mu-]cc]CC",
+      "KK_SL": "${B}[Xb ->                     ${D0}([D0]cc -> ${P1}K+  ${P2}K- )            ${Mu}mu-    ]CC",
+      "PP_SL": "${B}[Xb ->                     ${D0}([D0]cc -> ${P1}pi+ ${P2}pi-)            ${Mu}mu-    ]CC",
+      "RS_SL": "${B}[Xb ->                     ${D0}(D0     -> ${P1}K-  ${P2}pi+)            ${Mu}mu-    ]CC",
+      "WS_SL": "${B}[Xb ->                     ${D0}(D0     -> ${P1}K-  ${P2}pi+)            ${Mu}mu+    ]CC",
+      "KK_DT": "${B}[Xb -> ${Dst}(D*(2010)+ -> ${D0}([D0]cc -> ${P1}K+  ${P2}K- ) ${sPi}pi+) ${Mu}[mu-]cc]CC",
+      "PP_DT": "${B}[Xb -> ${Dst}(D*(2010)+ -> ${D0}([D0]cc -> ${P1}pi+ ${P2}pi-) ${sPi}pi+) ${Mu}[mu-]cc]CC",
+      "RS_DT": "${B}[Xb -> ${Dst}(D*(2010)+ -> ${D0}(D0     -> ${P1}K-  ${P2}pi+) ${sPi}pi+) ${Mu}[mu-]cc]CC",
+      "WS_DT": "${B}[Xb -> ${Dst}(D*(2010)- -> ${D0}(D0     -> ${P1}K-  ${P2}pi+) ${sPi}pi-) ${Mu}[mu+]cc]CC"
+}
+
+decay_descriptors_mc = {
+      "KK": "                  ${Dst}[D*(2010)+ => ${D0}([D0]cc => ${P1}K+  ${P2}K- ) ${sPi}pi+]CC",
+      "PP": "                  ${Dst}[D*(2010)+ => ${D0}([D0]cc => ${P1}pi+ ${P2}pi-) ${sPi}pi+]CC",
+      "RS": "                  ${Dst}[D*(2010)+ => ${D0}(D0     => ${P1}K-  ${P2}pi+) ${sPi}pi+]CC",
+      "RS_Mu": "   ${B}[Xb --> ${Dst}(D*(2010)+ => ${D0}(D0     => ${P1}K-  ${P2}pi+) ${sPi}pi+) ${Mu}mu- ${Nu}nu_mu~]CC",
+      "B": "${B}[B0]cc"  # to get the B0 decay time
+}
+
+
+def AddDTF(dtt, decay_type, constrain_pv=True, constrain_d0_m=False):
+    # DecayTreeFitter configuration
+    # https://twiki.cern.ch/twiki/bin/view/LHCb/DaVinciTutorial9b
+    name = 'DTF{0}{1}'.format('_PV' if constrain_pv else '',
+                              '_D0M' if constrain_d0_m else '')
+    if decay_type == "P":
+        DictTuple = dtt.Dst.addTupleTool(LoKi__Hybrid__Dict2Tuple, '{}_DictTuple'.format(name))
+    else:
+        DictTuple = dtt.B.addTupleTool(LoKi__Hybrid__Dict2Tuple, '{}_DictTuple'.format(name))
+    DictTuple.addTool(DTFDict, name)
+    DictTuple.Source = 'LoKi::Hybrid::DTFDict/{}'.format(name)
+    DictTuple.NumVar = 61 # reserve enough for DT
+    dtf = getattr(DictTuple, name)
+    dtf.constrainToOriginVertex = constrain_pv
+    if constrain_d0_m:
+        dtf.daughtersToConstrain = ['D0', 'D~0']
+    dtf.addTool(LoKi__Hybrid__DictOfFunctors, 'dict')
+    dtf.Source = 'LoKi::Hybrid::DictOfFunctors/dict'
+
+    variables = {}
+    if decay_type == "P":
+        DTFvars = {
+            "Dst": "{0}",
+            "D0": "CHILD(1, {0})",
+            "P1": "CHILD(1, CHILD(1, {0}))",
+            "P2": "CHILD(1, CHILD(2, {0}))",
+            "sPi": "CHILD(2, {0})",
+        }
+    elif decay_type == "SL":
+        DTFvars = {
+            "B": "{0}",
+            "D0": " CHILD(1, {0})",
+            "P1": "CHILD(1, CHILD(1, {0}))",
+            "P2": "CHILD(1, CHILD(2, {0}))",
+            "Mu": "CHILD(2, {0})",
+        }
+    else:
+        DTFvars = {
+            "B": "{0}",
+            "Dst": "CHILD(1, {0})",
+            "D0": "CHILD(1, CHILD(1, {0}))",
+            "P1": "CHILD(1, CHILD(1, CHILD(1, {0})))",
+            "P2": "CHILD(1, CHILD(1, CHILD(2, {0})))",
+            "sPi": "CHILD(1, CHILD(2, {0}))",
+            "Mu": "CHILD(2, {0})",
+        }
+    for key, string in list(DTFvars.items()):
+        for var in ["M", "PT", "P", "ETA", "PHI"]:
+            variables["{0}_{1}".format(key,var)] = string.format(var)
+
+    dtf.dict.Variables = variables
+
+    # the DTF fit is run once for each of the following variable
+    if decay_type == "P":
+        Loki_DTF = dtt.Dst.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_{0}'.format(name))
+    else:
+        Loki_DTF = dtt.B.addTupleTool('LoKi::Hybrid::TupleTool/LoKi_{0}'.format(name))
+
+    if decay_type != "DT":
+        Loki_DTF.Variables = {
+            "{0}_D0_CTAU".format(name): "DTF_CTAU(1, {0}{1})".format(
+                    True if constrain_pv else False,
+                    ", strings(['D0', 'D~0'])" if constrain_d0_m else ""),
+            "{0}_D0_CTAUERR".format(name): "DTF_CTAUERR( 1, {0}{1})".format(
+                    True if constrain_pv else False,
+                    ", strings(['D0', 'D~0'])" if constrain_d0_m else "")
+        }
+    else:
+        Loki_DTF.Variables = {
+            "{0}_D0_CTAU".format(name): "CHILD(1, DTF_CTAU(1, {0}{1}))".format(
+                    True if constrain_pv else False,
+                    ", strings(['D0', 'D~0'])" if constrain_d0_m else ""),
+            "{0}_D0_CTAUERR".format(name): "CHILD(1, DTF_CTAUERR( 1, {0}{1}))".format(
+                    True if constrain_pv else False,
+                    ", strings(['D0', 'D~0'])" if constrain_d0_m else "")
+        }
+
+    Loki_DTF.Variables.update({
+            "{0}_CHI2".format(name)       :        "DTF_CHI2({0}{1})".format(True if constrain_pv else False, ", strings(['D0', 'D~0'])" if constrain_d0_m else ""),
+            "{0}_NDOF".format(name)       :        "DTF_NDOF({0}{1})".format(True if constrain_pv else False, ", strings(['D0', 'D~0'])" if constrain_d0_m else ""),
+            "{0}_CHI2NDOF".format(name)   :    "DTF_CHI2NDOF({0}{1})".format(True if constrain_pv else False, ", strings(['D0', 'D~0'])" if constrain_d0_m else "")
+    })
+
+    return
+
+
+def SetupMCTools(dtt, is_turbo):
+    dtt.ToolList += ['TupleToolMCTruth', 'TupleToolMCBackgroundInfo']
+    mc_tools = ['MCTupleToolPrompt', 'MCTupleToolKinematic', 'MCTupleToolHierarchy']
+    # https://twiki.cern.ch/twiki/bin/view/LHCb/MakeNTupleFromTurbo#Monte_Carlo_truth
+    relations = TeslaTruthUtils.getRelLocs() + [
+            TeslaTruthUtils.getRelLoc(''),
+            'Relations/Hlt2/Protos/Charged']  # Location of the truth tables for PersistReco objects
+    TeslaTruthUtils.makeTruth(dtt, relations, mc_tools)
+    return
+
+
+# see https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/*/src/*
+tuple_tools = [
+    "TupleToolPropertime",  # DecayTreeTuple
+    "TupleToolEventInfo",   # DecayTreeTupleTrigger
+    "TupleToolBeamSpot",    # DecayTreeTuple
+    "TupleToolPid",         # DecayTreeTuple
+    "TupleToolRecoStats",   # DecayTreeTupleReco
+    "TupleToolMuonPid"]
+
+trigger_list = [
+    "L0B1gasDecision",
+    "L0B2gasDecision",
+    "L0DiEMDecision,lowMultDecision",
+    "L0DiHadron,lowMultDecision",
+    "L0DiMuonDecision",
+    "L0DiMuon,lowMultDecision",
+    "L0ElectronDecision",
+    "L0Electron,lowMultDecision",
+    "L0HadronDecision",
+    "L0JetElDecision",
+    "L0JetPhDecision",
+    "L0MuonDecision",
+    "L0Muon,lowMultDecision",
+    "L0MuonEWDecision",
+    "L0PhotonDecision",
+    "L0Photon,lowMultDecision",
+    "Hlt1TrackMVADecision",
+    "Hlt1TrackMVALooseDecision",
+    "Hlt1TrackMVATightDecision",
+    "Hlt1TwoTrackMVADecision",
+    "Hlt1TwoTrackMVALooseDecision",
+    "Hlt1TwoTrackMVATightDecision",
+    "Hlt1CalibTrackingKPiDecision",
+    "Hlt1CalibTrackingKKDecision",
+    "Hlt1CalibTrackingPiPiDecision"]
+
+trigger_list_SL_DT = [
+    "Hlt1TrackMuonDecision",
+    "Hlt1TrackMuonMVADecision",
+    "Hlt1L0AnyDecision",
+    "Hlt1MBNoBiasDecision",
+    "Hlt2TopoMu2BodyDecision",
+    "Hlt2TopoMu3BodyDecision",
+    "Hlt2TopoMu4BodyDecision",
+    "Hlt2Topo2BodyDecision",
+    "Hlt2Topo3BodyDecision",
+    "Hlt2Topo4BodyDecision",
+    "Hlt2CharmHadInclDst2PiD02HHXBDTDecision",
+    "Hlt2SingleMuonDecision"]
+
+
+
+loki_vars_dst = {
+    "DOCACHI2": "DOCACHI2(1,2)",
+    "DOCA": "DOCA(1,2)"}
+
+loki_vars_d0 = {
+    "DOCACHI2": "DOCACHI2(1,2)",
+    "DOCA": "DOCA(1,2)",
+    "BPVLTIME": "BPVLTIME()"}
+
+loki_var ={
+    "ETA": "ETA",
+    "PHI": "PHI"}
+
+
+def MakeTuple(key):
+    """ Returns a DecayTreeTuple algorithm configured to be run on real data"""
+
+    dtt = DecayTreeTuple("{0}_Tuple".format(key))
+    dtt.TupleName = key
+    dtt.setDescriptorTemplate(decay_descriptors[key])
+    dtt.Inputs = [inputs[key].outputLocation()]
+    if DaVinci().DataType == '2015' or DaVinci().DataType == '2016':
+        dtt.InputPrimaryVertices = 'Primary'
+
+    dtt.ToolList = copy(tuple_tools)
+
+    # path of header files starts with https://gitlab.cern.ch/lhcb/Analysis/blob/master/Phys/*/src
+    dtt.addTupleTool("TupleToolTrackInfo").Verbose = True               # DecayTreeTupleReco
+    dtt.addTupleTool("TupleToolGeometry").Verbose = True                # DecayTreeTuple
+    dtt.addTupleTool("TupleToolKinematic").Verbose = True               # DecayTreeTuple
+    dtt.addTupleTool("TupleToolANNPID").ANNPIDTunes = ["MC15TuneV1"]    # DecayTreeTupleANNPID
+    primTool = dtt.addTupleTool("TupleToolPrimaries")                   # DecayTreeTuple
+    primTool.Verbose = True
+    if DaVinci().DataType == '2015' or DaVinci().DataType == '2016':
+        primTool.InputLocation = 'Primary'
+
+    # trigger global info for the event - DecayTreeTupleTrigger/src/TupleToolTrigger.h
+    global_trigger = dtt.addTupleTool("TupleToolTrigger")
+    global_trigger.VerboseL0 = True
+    global_trigger.VerboseHlt1 = True
+    global_trigger.VerboseHlt2 = True
+    global_trigger.TriggerList = copy(trigger_list)
+
+    # TISTOS - DecayTreeTupleTrigger/src/TupleToolTISTOS.h
+    tis_tos_tool = dtt.addTupleTool("TupleToolTISTOS")
+    tis_tos_tool.VerboseL0 = True
+    tis_tos_tool.VerboseHlt1 = True
+    tis_tos_tool.VerboseHlt2 = True
+    tis_tos_tool.FillHlt2 = True
+    tis_tos_tool.TriggerList = copy(trigger_list)
+
+    LoKi_D0 = dtt.D0.addTupleTool("LoKi::Hybrid::TupleTool/LoKi_D0")
+    LoKi_D0.Variables = loki_vars_d0
+    LoKi_All = dtt.addTupleTool("LoKi::Hybrid::TupleTool/LoKi_ETA_PHI")
+    LoKi_All.Variables = loki_var
+
+    if not ('SL' in key):
+        LoKi_DStar = dtt.Dst.addTupleTool("LoKi::Hybrid::TupleTool/LoKi_DStar")
+        LoKi_DStar.Variables = loki_vars_dst
+
+    # additional info for secondary samples only
+    if key == 'Mu' or ('SL' in key) or ('DT' in key):
+        dtt.B.addTupleTool("TupleToolCorrectedMass")    # DecayTreeTuple/src/TupleToolCorrectedMass.h
+        loki_B = dtt.B.addTupleTool("LoKi::Hybrid::TupleTool/LoKi_B")
+        loki_B.Variables = {"BPVMCORR": "BPVCORRM",
+                            "DOCACHI2": "DOCACHI2(1,2)",
+                            "DOCA": "DOCA(1,2)"}
+
+    if ('SL' in key) or ('DT' in key):
+        global_trigger.TriggerList += trigger_list_SL_DT
+        tis_tos_tool.TriggerList  += trigger_list_SL_DT
+        neutrinoTool = dtt.B.addTupleTool("TupleToolNeutrinoReco")
+        neutrinoTool.Verbose = True
+        neutrinoTool.MotherMass = 5279.63
+    else:
+        if ('TUNB' in key):
+            # add prompt Hlt2 line
+            global_trigger.TriggerList += [ hlt2_lines[key[:2]] + 'Decision' ]
+            tis_tos_tool.TriggerList  += [ hlt2_lines[key[:2]] + 'Decision' ]
+        else:
+            # add LTUNB Hlt2 line
+            if key == 'Mu':
+                global_trigger.TriggerList += [hlt2_lines['RS_LTUNB'] + 'Decision' ]
+                tis_tos_tool.TriggerList  += [hlt2_lines['RS_LTUNB'] + 'Decision' ]
+            else:
+                global_trigger.TriggerList += [hlt2_lines[key+'_LTUNB'] + 'Decision' ]
+                tis_tos_tool.TriggerList  += [hlt2_lines[key+'_LTUNB'] + 'Decision' ]
+
+    type = "P" if 'B' not in list(dtt.Branches.keys()) else ("SL" if "Dst" not in list(dtt.Branches.keys()) else "DT")
+    AddDTF(dtt, type, constrain_pv=False, constrain_d0_m=False)
+    AddDTF(dtt, type, constrain_pv=False, constrain_d0_m=True)
+    AddDTF(dtt, type, constrain_pv=True, constrain_d0_m=False)
+    AddDTF(dtt, type, constrain_pv=True, constrain_d0_m=True)
+
+
+    if DaVinci().Simulation:
+        SetupMCTools(dtt, DaVinci().Turbo)
+
+    return dtt
+
+
+def MakeTupleMC(key):
+    """ Returns a MCDecayTreeTuple algorithm configured to be run on simulated
+        data
+    """
+
+    dtt = MCDecayTreeTuple('{0}_MCTuple'.format(key))
+    dtt.TupleName = key
+    dtt.setDescriptorTemplate(decay_descriptors_mc[key])
+    dtt.ToolList = [
+            "MCTupleToolKinematic",
+            "TupleToolEventInfo"]
+    return dtt
+
+
+tuples = [MakeTuple(key) for key in list(tuple_keys.keys())]
+if DaVinci().Simulation:
+    tuples += [MakeTupleMC(key) for key in decay_descriptors_mc.keys()]
+
+
+def MomentumCorrection(is_mc=False):
+    """
+    Returns the momentum scale correction algorithm for data tracks or the
+    momentum smearing algorithm for MC tracks
+    """
+    if not is_mc:
+        from Configurables import TrackScaleState as SCALE
+        scaler = SCALE('StateScale')
+        return scaler
+    else:
+        from Configurables import TrackSmearState as SMEAR
+        smear = SMEAR('StateSmear')
+        return smear
+    return
+
+
+trigger_filter = LoKi_Filters(
+    HLT1_Code="  HLT_PASS_RE('Hlt1.*TrackMVA.*Decision')"
+              "| HLT_PASS_RE('Hlt1TrackMuon.*Decision')"
+              "| HLT_PASS_RE('Hlt1CalibTracking.*Decision')",
+    HLT2_Code="  HLT_PASS_RE('"+hlt2_lines['KK']+"Decision') "
+              "| HLT_PASS_RE('"+hlt2_lines['PP']+"Decision') "
+              "| HLT_PASS_RE('"+hlt2_lines['RS']+"Decision') "
+              "| HLT_PASS_RE('"+hlt2_lines['WS']+"Decision') "
+              "| HLT_PASS_RE('"+hlt2_lines['KK_LTUNB']+"Decision') "
+              "| HLT_PASS_RE('"+hlt2_lines['PP_LTUNB']+"Decision') "
+              "| HLT_PASS_RE('"+hlt2_lines['RS_LTUNB']+"Decision') "
+              "| HLT_PASS_RE('"+hlt2_lines['WS_LTUNB']+"Decision') "
+              "| HLT_PASS_RE('"+hlt2_lines['KK_SL']+"Decision')"
+              "| HLT_PASS_RE('"+hlt2_lines['PP_SL']+"Decision')"
+              "| HLT_PASS_RE('"+hlt2_lines['KP_SL']+"Decision')"
+              "| HLT_PASS_RE('"+hlt2_lines['KK_DT']+"Decision')"
+              "| HLT_PASS_RE('"+hlt2_lines['PP_DT']+"Decision')"
+              "| HLT_PASS_RE('"+hlt2_lines['KP_DT']+"Decision')"
+    )
+
+
+
+DaVinci().EventPreFilters = trigger_filter.filters('TriggerFilter')
+DaVinci().UserAlgorithms += [v for v in probnn_sequence.values()]
+DaVinci().UserAlgorithms += [MomentumCorrection(DaVinci().Simulation)]
+DaVinci().UserAlgorithms += [p for p in particles.values()]
+DaVinci().UserAlgorithms += [dst_mu_sequence.sequence()]
+DaVinci().UserAlgorithms += tuples