diff --git a/DaVinciExamples/python/DaVinciExamples/tupling/example-tupling-basic.py b/DaVinciExamples/python/DaVinciExamples/tupling/example-tupling-basic.py
index 4033edef57ded1ae24dc118267667ff83aa92996..9162310a1f7d0b99e8ec7a1e78acc601fd518218 100644
--- a/DaVinciExamples/python/DaVinciExamples/tupling/example-tupling-basic.py
+++ b/DaVinciExamples/python/DaVinciExamples/tupling/example-tupling-basic.py
@@ -18,13 +18,12 @@ Example of a typical DaVinci job:
 __author__ = "Maurizio Martinelli"
 __date__ = "2021-03-16"
 
-from DaVinci.standard_particles import make_detached_mumu
-from DaVinci import options, run_davinci, DVNode, DVHelper
+from DaVinci import options, run_davinci
+from DaVinci.standard_particles import make_detached_mumu, make_KsDD
 from DaVinci.reco_objects import upfront_reconstruction_from_file as upfront_reconstruction
 import Functors as F
-from FunTuple import ParticleTupleProp, convert_to_parsable_objs
-from PyConf.Algorithms import PrintDecayTree
 from PyConf.Algorithms import FunTuple_Particles as FunTuple
+from FunTuple import ParticleTupleProp, convert_to_parsable_objs
 
 # print control flow and data flow graphs
 options.control_flow_file = 'control_flow.gv'
@@ -41,13 +40,29 @@ options.lumi = True
 
 print(options)
 
-# Prepare the node with the selection
+# selections
 dimuons = make_detached_mumu()
+kshorts = make_KsDD()
+
+
+# Add FUNTuples
+def CreateSimpleTuple(name, tree_name, parsable_objs, loki_preamble, inputs):
+    ftup = FunTuple(
+        name=name,
+        tree_name=tree_name,
+        branch_names_prefix=parsable_objs[0],
+        decay_descriptors=parsable_objs[1],
+        loki_functors=parsable_objs[2][0],
+        loki_functor_branch_names=parsable_objs[2][1],
+        thor_functors=parsable_objs[3][0],
+        thor_functor_branch_names=parsable_objs[3][1],
+        loki_preamble=loki_preamble,
+        input_location=inputs)
+    return ftup
+
 
-# Add a FUNTuple
 #FunTuple: define list of preambles for loki
 loki_preamble = ['TRACK_MAX_PT = MAXTREE(ISBASIC & HASTRACK, PT, -1)']
-
 #FunTuple: Jpsi info
 ParticleJpsi = ParticleTupleProp(
     branch_name_prefix="Jpsi",
@@ -74,22 +89,34 @@ ParticleMuPlus = ParticleTupleProp(
     particle_code_thor={'THOR_P': F.P})
 
 #FunTuple: Do not need to do this if a custom gaudi property for ParticleTupleProp is implemented
-parsable_objs = convert_to_parsable_objs([ParticleJpsi, ParticleMuPlus])
-
-#FunTuple: Configure FunTuple algorithm
-ftup = FunTuple(
-    name="DimuonsTuple",
-    tree_name="DecayTree",
-    branch_names_prefix=parsable_objs[0],
-    decay_descriptors=parsable_objs[1],
-    loki_functors=parsable_objs[2][0],
-    loki_functor_branch_names=parsable_objs[2][1],
-    thor_functors=parsable_objs[3][0],
-    thor_functor_branch_names=parsable_objs[3][1],
-    loki_preamble=loki_preamble,
-    input_location=dimuons)
-
-dvh = DVHelper()
-dvh.add_selections_node("Selection1", upfront_reconstruction() + [dimuons])
-dvh.add_tuples_node('Tuple1', [ftup])
-dvh.run(options)
+parsable_objs_dimuons = convert_to_parsable_objs(
+    [ParticleJpsi, ParticleMuPlus])
+ftup_dimuons = CreateSimpleTuple("DimuonsTuple", "DecayTree",
+                                 parsable_objs_dimuons, loki_preamble, dimuons)
+
+ParticleKS = ParticleTupleProp(
+    branch_name_prefix="Ks",
+    decay_descriptor="KS0 -> pi+ pi-",
+    #Dict -> {name:functor}
+    particle_code_loki={
+        'LOKI_P': 'P',
+        'LOKI_PT': 'PT',
+        'LOKI_Muonp_PT': 'CHILD(PT, 1)',
+        'LOKI_Muonm_PT': 'CHILD(PT, 2)',
+        'LOKI_MAXPT': 'TRACK_MAX_PT',
+        'LOKI_N_HIHGPT_TRCKS': 'NINTREE(ISBASIC & HASTRACK & (PT > 1500*MeV))'
+    },
+    particle_code_thor={
+        'THOR_P': F.P,
+        'THOR_PT': F.PT
+    })
+parsable_objs_kshorts = convert_to_parsable_objs([ParticleKS])
+ftup_kshorts = CreateSimpleTuple("KsTuple", "DecayTree", parsable_objs_kshorts,
+                                 loki_preamble, kshorts)
+
+algs = {
+    'DiMuons': upfront_reconstruction() + [dimuons, ftup_dimuons],
+    'KShorts': upfront_reconstruction() + [kshorts, ftup_kshorts]
+}
+
+run_davinci(options, algs)
diff --git a/DaVinciExamples/tests/qmtest/tupling.qms/test_example-tupling-basic.qmt b/DaVinciExamples/tests/qmtest/tupling.qms/test_example-tupling-basic.qmt
index ee15744a622575fd5bc4f65ab07b3a8c67f52563..e96714b4dbd0c6bf35b44a422cfa2e9c8b23e34c 100644
--- a/DaVinciExamples/tests/qmtest/tupling.qms/test_example-tupling-basic.qmt
+++ b/DaVinciExamples/tests/qmtest/tupling.qms/test_example-tupling-basic.qmt
@@ -22,7 +22,7 @@ RFileCnv                               INFO dumping contents of /NTUPLES/FILE1
 TFile: name=DV-example-tupling-basic-ntp.root, title=Gaudi Trees, option=CREATE
 ******************************************************************************
 *Tree    :DecayTree : DecayTree                                              *
-*Entries :        3 : Total =            6907 bytes  File  Size =       2072 *
+*Entries :        3 : Total =            6907 bytes  File  Size =       2065 *
 *        :          : Tree compression factor =   1.00                       *
 ******************************************************************************
 *Br    0 :Jpsi_LOKI_N_HIHGPT_TRCKS : Jpsi_LOKI_N_HIHGPT_TRCKS/D              *
@@ -65,6 +65,43 @@ TFile: name=DV-example-tupling-basic-ntp.root, title=Gaudi Trees, option=CREATE
 *Entries :        3 : Total  Size=        642 bytes  File Size  =        109 *
 *Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.00     *
 *............................................................................*
+******************************************************************************
+*Tree    :DecayTree : DecayTree                                              *
+*Entries :        4 : Total =            5597 bytes  File  Size =       1775 *
+*        :          : Tree compression factor =   1.01                       *
+******************************************************************************
+*Br    0 :Ks_LOKI_N_HIHGPT_TRCKS : Ks_LOKI_N_HIHGPT_TRCKS/D                  *
+*Entries :        4 : Total  Size=        695 bytes  File Size  =        114 *
+*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.11     *
+*............................................................................*
+*Br    1 :Ks_LOKI_PT : Ks_LOKI_PT/D                                          *
+*Entries :        4 : Total  Size=        635 bytes  File Size  =        114 *
+*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.00     *
+*............................................................................*
+*Br    2 :Ks_LOKI_MAXPT : Ks_LOKI_MAXPT/D                                    *
+*Entries :        4 : Total  Size=        650 bytes  File Size  =        117 *
+*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.00     *
+*............................................................................*
+*Br    3 :Ks_LOKI_Muonp_PT : Ks_LOKI_Muonp_PT/D                              *
+*Entries :        4 : Total  Size=        665 bytes  File Size  =        120 *
+*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.00     *
+*............................................................................*
+*Br    4 :Ks_LOKI_Muonm_PT : Ks_LOKI_Muonm_PT/D                              *
+*Entries :        4 : Total  Size=        665 bytes  File Size  =        120 *
+*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.00     *
+*............................................................................*
+*Br    5 :Ks_LOKI_P : Ks_LOKI_P/D                                            *
+*Entries :        4 : Total  Size=        630 bytes  File Size  =        113 *
+*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.00     *
+*............................................................................*
+*Br    6 :Ks_THOR_P : Ks_THOR_P/D                                            *
+*Entries :        4 : Total  Size=        630 bytes  File Size  =        113 *
+*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.00     *
+*............................................................................*
+*Br    7 :Ks_THOR_PT : Ks_THOR_PT/D                                          *
+*Entries :        4 : Total  Size=        635 bytes  File Size  =        114 *
+*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.00     *
+*............................................................................*
 """, stdout, result, causes, signature_offset = 0)
 countErrorLines({"FATAL":0, "ERROR":0})
 
@@ -86,4 +123,4 @@ except:
     raise Exception('Unexpected error while opening file: ')
 <argument name="exit_code"><integer>1</integer></argument>
 </text></argument>
-</extension>
\ No newline at end of file
+</extension>
diff --git a/Phys/DaVinci/python/DaVinci/__init__.py b/Phys/DaVinci/python/DaVinci/__init__.py
index d44ee4dc5806a51bf450b1729e6dacd4d09c30ac..2427da62d9ed115e9ca052886f21b5d366d3305e 100644
--- a/Phys/DaVinci/python/DaVinci/__init__.py
+++ b/Phys/DaVinci/python/DaVinci/__init__.py
@@ -10,6 +10,6 @@
 ###############################################################################
 
 from __future__ import absolute_import
-from .config import options, run_davinci, DVNode, DVHelper
+from .config import options, run_davinci, DVNode
 
-__all__ = ('options', 'run_davinci', 'DVNode', 'DVHelper')
+__all__ = ('options', 'run_davinci', 'DVNode')
diff --git a/Phys/DaVinci/python/DaVinci/config.py b/Phys/DaVinci/python/DaVinci/config.py
index ae2058b14ae572577492338630b22a079f882941..66ff329ea80f265ab8d91bffeddd7d001ba089a5 100644
--- a/Phys/DaVinci/python/DaVinci/config.py
+++ b/Phys/DaVinci/python/DaVinci/config.py
@@ -84,92 +84,30 @@ class DVNode(namedtuple('DVNode', ['node', 'extra_outputs'])):  # noqa
         return self.output_producer is not None
 
 
-class DVHelper():
-    """Class for collecting DV algorithms."""
-
-    def __init__(self):
-        self.selections = []
-        self.user = []
-        self.tuples = []
-        self.writers = []
-
-    def add_node(self, node_name, algs, kind):
-        if hasattr(self, kind):
-            setattr(self, kind,
-                    getattr(self, kind) + [DVNode(node_name, algs)])
-        else:
-            print('the specified note type ({}) is not valid'.format(kind))
-        return
-
-    def add_selections_node(self, node_name, algs):
-        self.add_node(node_name, algs, 'selections')
-        return
-
-    def add_user_node(self, node_name, algs):
-        self.add_node(node_name, algs, 'user')
-        return
-
-    def add_tuples_node(self, node_name, algs):
-        self.add_node(node_name, algs, 'tuples')
-        return
-
-    def add_writers_node(self, node_name, algs):
-        self.add_node(node_name, algs, 'writers')
-        return
-
-    def run(self, options, public_tools=[]):
-        run_davinci(
-            options,
-            selections=self.selections,
-            user=self.user,
-            tuples=self.tuples,
-            writers=self.writers,
-            public_tools=public_tools)
-
-
-def davinci_control_flow(options,
-                         SelectionNodes=[],
-                         UserAlgorithms=[],
-                         TuplesNodes=[],
-                         WritersNodes=[]):
+def davinci_control_flow(options, user_analysis_nodes=[]):
     '''
-    DaVinci control flow is split in a few sections as described in DaVinci/issue#2
+    DaVinci control flow is split in a few sections as described in DaVinci/issue#2 (then simplified)
 
        DaVinci (LAZY_AND)
        *-- LuminosityNode (NONLAZY_OR)
        |   *-- EventAccounting/EventAccount
-       *-- DVSelectionsNode (NONLAZY_OR)
-       |   +-- DVCandidate1Node (LAZY_AND)
-       |   |   *-- PVFilter
-       |   |   *-- ParticlesFilter
-       |   |   *-- Candidate1Combiner
-       |   +-- DVCandidate2Node (LAZY_AND)
-       |   |   *-- PVFilter
-       |   |   *-- ParticlesFilter
-       |   |   *-- Candidate2Combiner
-       *-- DVUserAnalysisNode (NONLAZY_OR)
-       |   *-- PrintHeader
-       |   *-- PrintDecayTree/PrintMyB
-       *-- DVTuplesNode (NONLAZY_OR)
-       |   +-- DVTuple1Node (LAZY_AND)
-       |   |   *-- AlgorithmsForTuple1
-       |   |   *-- Tuple1
-       |   +-- DVTuple2Node (LAZY_AND)
-       |   |   *-- AlgorithmsForTuple2
-       |   |   *-- Tuple2
-       |   +-- DVTuple3Node (LAZY_AND)
-       |   |   *-- AlgorithmsForTuple3
-       |   |   *-- Tuple3
-       *-- DVWriterNode (LAZY_AND)
-           *-- DSTWriter?
-           *-- TuplesWriter
+       *-- UserAnalysisNode (NONLAZY_OR)
+           +-- DVUser1Node (LAZY_AND)
+           |   *-- PVFilter
+           |   *-- ParticlesFilter
+           |   *-- Candidate1Combiner
+           |   *-- AlgorithmsForTuple1
+           |   *-- Tuple1
+           +-- DVUser2Node (LAZY_AND)
+               *-- PVFilter
+               *-- ParticlesFilter
+               *-- Candidate2Combiner
+               *-- AlgorithmsForTuple2
+               *-- Tuple2
 
     The main parts are
         . LuminosityNode
-        . SelectionsNode
         . UserAnalysisNode
-        . TuplesNode
-        . WritersNode
     who are in AND among each other and can accomodate nodes (defined with the class DVNode)
     in OR among themselves.
 
@@ -181,17 +119,14 @@ def davinci_control_flow(options,
     options.finalize()
     dv_top_children = []
     # Setup luminosity
-    LumiNodes = []
+    lumi_nodes = []
     if options.lumi:
-        LumiNodes += [
+        lumi_nodes += [
             DVNode('Lumi', [EventAccounting(name='EventAccount')])
         ]  # this should be modified to reflect LumiAlgsConf (configured separately?)
     ordered_nodes = OrderedDict()
-    ordered_nodes['Luminosity'] = LumiNodes
-    ordered_nodes['Selections'] = SelectionNodes
-    ordered_nodes['UserAlgorithms'] = UserAlgorithms
-    ordered_nodes['Tuples'] = TuplesNodes
-    ordered_nodes['Writers'] = WritersNodes
+    ordered_nodes['Luminosity'] = lumi_nodes
+    ordered_nodes['UserAnalysis'] = user_analysis_nodes
     for k, v in ordered_nodes.items():
         if len(v):
             cnode = CompositeNode(
@@ -208,30 +143,42 @@ def davinci_control_flow(options,
         force_order=True)
 
 
-def run_davinci(options,
-                selections=[],
-                user=[],
-                tuples=[],
-                writers=[],
-                public_tools=[]):
+def prepare_davinci_nodes(user_algs={}):
+    '''
+    This function takes as input a dictionary of user algorithms in the form
+    {
+        'DVNode1' : [<list of algs>],
+        'DVNode2' : [<list of algs>],
+    }
+    and creates the node to send to `davinci_control_flow`.
+    '''
+    dv_nodes = []
+    for k, algs in user_algs.items():
+        #if type(algs) == dict: # it could be extended to add complexity, but it is probably useless. The experienced user has all that's needed.
+        #    dv_nodes += [prepare_davinci_nodes(algs)]
+        #else:
+        if not type(algs) == list:
+            raise ValueError('value not a list of algorithms. quitting.')
+        dv_nodes += [DVNode(k, algs)]
+    return dv_nodes
+
+
+def run_davinci(options, user_algs={}, public_tools=[]):
     '''
     DaVinci application control flow
 
     Args:
         options (ApplicationOptions): holder of application options
-        selections  : list of selections nodes
-        user        : list of user nodes
-        tuples      : list of tuples nodes
-        writers     : list of writers nodes
+        user_algs   : list of user algorithms
         public_tools (list): list of public `Tool` instances to configure
     '''
-    if not len(selections + user + tuples + writers):
+    if not len(user_algs):
         dummy = CompositeNode("EmptyNode", children=[])
         config = configure(options, dummy, public_tools=public_tools)
     else:
         config = configure_input(options)
-        top_dv_node = davinci_control_flow(options, selections, user, tuples,
-                                           writers)
+        dv_nodes = prepare_davinci_nodes(user_algs)
+        top_dv_node = davinci_control_flow(options, dv_nodes)
         config.update(
             configure(options, top_dv_node, public_tools=public_tools))
     return config