diff --git a/CODEOWNERS b/CODEOWNERS
index 52ef01f81b29ff231ecc03f99ad9466c210f698b..c6ab02544717e959f859936a051d6c15ce17b63f 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -85,6 +85,7 @@
 /Hlt/Hlt2Conf/ @mvesteri @poluekt
 # B2CC
 /Hlt/Hlt2Conf/python/Hlt2Conf/lines/Bs2JpsiPhi.py @egovorko
+/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/ @peilian @jiew @zhshen @gmeier @valukash
 # B2OC lines
 /Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_open_charm/ @abertoli @shunan
 /Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_open_charm/bbaryon*.py @abertoli @shunan @sblusk
diff --git a/Hlt/Hlt1Conf/python/Hlt1Conf/lines/track_mva.py b/Hlt/Hlt1Conf/python/Hlt1Conf/lines/track_mva.py
index b225dea3c726368a367da557e863c8f3ece11e07..d65b2894ddcf06dc82b2fdb51ba41e8de1b17681 100644
--- a/Hlt/Hlt1Conf/python/Hlt1Conf/lines/track_mva.py
+++ b/Hlt/Hlt1Conf/python/Hlt1Conf/lines/track_mva.py
@@ -93,8 +93,8 @@ def two_track_mva_line(name='Hlt1TwoTrackMVALine',
         """Helper for applying 'Combination' cuts to a composite."""
         return COMB(
             Functor=functor,
-            ChildContainers=[children],
-            ChildContainerTypes=[(children.type, 'SelKernel/TrackZips.h')])
+            ChildContainers=(children, ),
+            ChildContainerTypes=((children.type, 'SelKernel/TrackZips.h'), ))
 
     # See gaudi/Gaudi#117 for discussion of the expansion of ${PARAMFILESROOT}
     VertexCut = ((CHI2DOF < 10.) & (BPVDIRA(pvs) > 0) & (BPVCORRM(
diff --git a/Hlt/Hlt1Conf/tests/options/allen_hlt1_dst_input.py b/Hlt/Hlt1Conf/tests/options/allen_hlt1_dst_input.py
new file mode 100644
index 0000000000000000000000000000000000000000..4821b94177f26fc341cd02a6867ef0f8bfa791e8
--- /dev/null
+++ b/Hlt/Hlt1Conf/tests/options/allen_hlt1_dst_input.py
@@ -0,0 +1,17 @@
+###############################################################################
+# (c) Copyright 2019 CERN for the benefit of the LHCb Collaboration           #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+"""Read a DST file created by the `hlt1_dst_output.py` options."""
+from Moore import options
+
+options.input_files = ['test_allen_hlt1_persistence_dst_write.dst']
+options.input_type = 'ROOT'
+options.evt_max = -1
+options.tck = 0x11300000
diff --git a/Hlt/Hlt1Conf/tests/options/allen_hlt1_dst_output.py b/Hlt/Hlt1Conf/tests/options/allen_hlt1_dst_output.py
new file mode 100644
index 0000000000000000000000000000000000000000..e4b7c3dc8e553355051a54dbb1769973380b522d
--- /dev/null
+++ b/Hlt/Hlt1Conf/tests/options/allen_hlt1_dst_output.py
@@ -0,0 +1,16 @@
+###############################################################################
+# (c) Copyright 2019 CERN for the benefit of the LHCb Collaboration           #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+"""Write an HLT1-filtered DST file."""
+from Moore import options
+
+options.output_file = 'test_allen_hlt1_persistence_dst_write.dst'
+options.output_type = 'ROOT'
+options.tck = 0x11300000
diff --git a/Hlt/Hlt1Conf/tests/qmtest/persistency.qms/allen_dst_read.qmt b/Hlt/Hlt1Conf/tests/qmtest/persistency.qms/allen_dst_read.qmt
new file mode 100644
index 0000000000000000000000000000000000000000..298ed08c09b05cfa6084b38568fbc9758bd40368
--- /dev/null
+++ b/Hlt/Hlt1Conf/tests/qmtest/persistency.qms/allen_dst_read.qmt
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE extension  PUBLIC '-//QM/2.3/Extension//EN'  'http://www.codesourcery.com/qm/dtds/2.3/-//qm/2.3/extension//en.dtd'>
+<!--
+    (c) Copyright 2022 CERN for the benefit of the LHCb Collaboration
+
+    This software is distributed under the terms of the GNU General Public
+    Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".
+
+    In applying this licence, CERN does not waive the privileges and immunities
+    granted to it by virtue of its status as an Intergovernmental Organization
+    or submit itself to any jurisdiction.
+-->
+<!--
+Run HLT1 on an HLT1-filtered DST file.
+-->
+<extension class="GaudiTest.GaudiExeTest" kind="test">
+<argument name="prerequisites"><set>
+  <tuple><text>persistency.allen_dst_write</text><enumeral>PASS</enumeral></tuple>
+</set></argument>
+<argument name="program"><text>gaudirun.py</text></argument>
+<argument name="args"><set>
+  <text>$MOOREROOT/tests/options/default_input_and_conds_hlt1.py</text>
+  <text>$HLT1CONFROOT/tests/options/allen_hlt1_dst_input.py</text>
+  <text>$HLT1CONFROOT/options/allen_hlt1_pp_default.py</text>
+</set></argument>
+<argument name="use_temp_dir"><enumeral>true</enumeral></argument>
+<argument name="validator"><text>
+
+
+import re
+
+# Check that:
+#   1. We selected the same number of events by the TrackMVA line as in the previous job
+
+pattern = re.compile(r'\s+\|\*"Selected by Hlt1TrackMVADecision"\s+\|\s+(\d+)\s+\|\s+(\d+)')
+nread = nselected = -1
+for line in stdout.split('\n'):
+    m = re.match(pattern, line)
+    if m:
+        nread, nselected = map(int, m.groups())
+        break
+else:
+    causes.append('could not parse event statistics from stdout')
+
+nread_writing = nselected_writing = -1
+with open('test_hlt1_persistence_allen_dst_write.stdout') as f_ref:
+   for line in stdout.split('\n'):                
+       m = re.match(pattern, line)
+       if m:
+          nread_writing, nselected_writing = map(int, m.groups())
+          break
+   else:
+       causes.append('could not parse event statistics from writer stdout')
+
+if nselected != nselected_writing:
+    causes.append('did not read the same number of events as written out')
+
+</text></argument>
+</extension>
diff --git a/Hlt/Hlt1Conf/tests/qmtest/persistency.qms/allen_dst_write.qmt b/Hlt/Hlt1Conf/tests/qmtest/persistency.qms/allen_dst_write.qmt
new file mode 100644
index 0000000000000000000000000000000000000000..9de0e45457bd2b0e2fc0d873a163c288907c39cb
--- /dev/null
+++ b/Hlt/Hlt1Conf/tests/qmtest/persistency.qms/allen_dst_write.qmt
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE extension  PUBLIC '-//QM/2.3/Extension//EN'  'http://www.codesourcery.com/qm/dtds/2.3/-//qm/2.3/extension//en.dtd'>
+<!--
+    (c) Copyright 2000-2022 CERN for the benefit of the LHCb Collaboration
+
+    This software is distributed under the terms of the GNU General Public
+    Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".
+
+    In applying this licence, CERN does not waive the privileges and immunities
+    granted to it by virtue of its status as an Intergovernmental Organization
+    or submit itself to any jurisdiction.
+-->
+<!--
+Run HLT1 and save an DST file.
+-->
+<extension class="GaudiTest.GaudiExeTest" kind="test">
+<argument name="program"><text>gaudirun.py</text></argument>
+<argument name="args"><set>
+  <text>$MOOREROOT/tests/options/default_input_and_conds_hlt1.py</text>
+  <text>$HLT1CONFROOT/tests/options/allen_hlt1_dst_output.py</text>
+  <text>$HLT1CONFROOT/options/allen_hlt1_pp_default.py</text>
+</set></argument>
+<argument name="use_temp_dir"><enumeral>true</enumeral></argument>
+<argument name="validator"><text>
+
+
+import re
+
+
+# Check that:
+#   1. We read at least two events
+#   2. We make a positive decision with the TrackMVA line on at least one event
+#   3. We make a negative decision with the TrackMVA line on at least one event
+#   4. We make a positive decision with the TwoTrackMVA line on at least one event
+#   5. We make a negative decision with the TwoTrackMVA line on at least one event
+
+pattern = re.compile(r'\s+\|\*"Selected by Hlt1TrackMVADecision"\s+\|\s+(\d+)\s+\|\s+(\d+)')
+nread = nselected = -1
+for line in stdout.split('\n'):
+    m = re.match(pattern, line)
+    if m:
+        nread, nselected = map(int, m.groups())
+        break
+else:
+    causes.append('could not parse event statistics from stdout')
+
+if nread &lt; 2:
+    causes.append('expected at least two events to be processed')
+
+if nselected &lt; 1:
+    causes.append('expected at least one event to be selected by TrackMVALine')
+
+if nselected == nread:
+    causes.append('expected at least one event to be filtered out by TrackMVALine')
+
+pattern = re.compile(r'\s+\|\*"Selected by Hlt1TwoTrackMVADecision"\s+\|\s+(\d+)\s+\|\s+(\d+)')
+nread = nselected = -1
+for line in stdout.split('\n'):
+    m = re.match(pattern, line)
+    if m:
+        nread, nselected = map(int, m.groups())
+        break
+else:
+    causes.append('could not parse event statistics from stdout')
+
+if nread &lt; 2:
+    causes.append('expected at least two events to be processed')
+
+if nselected &lt; 1:
+    causes.append('expected at least one event to be selected by TwoTrackMVA line')
+
+if nselected == nread:
+    causes.append('expected at least one event to be filtered out by TwoTrackMVA line')
+
+
+# Write out the log file so that we can compare the number of
+# selected events here with the number of events processed by
+# a second HLT1 job that uses the output file as input
+with open('test_hlt1_persistence_allen_dst_write.stdout', 'w') as f:
+    f.write(stdout)
+
+</text></argument>
+</extension>
diff --git a/Hlt/Hlt2Conf/options/bandq/hlt2_bandq_test.py b/Hlt/Hlt2Conf/options/bandq/hlt2_bandq_test.py
index b6e730fda3d53b2b17ca0c09e9029e75ce0a0dfc..ff1444255c63c9a97dbc27772879f3b5cc824261 100644
--- a/Hlt/Hlt2Conf/options/bandq/hlt2_bandq_test.py
+++ b/Hlt/Hlt2Conf/options/bandq/hlt2_bandq_test.py
@@ -1,5 +1,5 @@
 ###############################################################################
-# (c) Copyright 2019 CERN for the benefit of the LHCb Collaboration           #
+# (c) Copyright 2019-2021 CERN for the benefit of the LHCb Collaboration      #
 #                                                                             #
 # This software is distributed under the terms of the GNU General Public      #
 # Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
@@ -31,20 +31,20 @@ from Hlt2Conf.lines.bandq import all_lines
 # before HLT1: /MC/Upgrade/Beam7000GeV-Upgrade-MagDown-Nu7.6-25ns-Pythia8/Sim09c-Up02/Reco-Up01/<evtNumber>/LDST
 # after HLT1: /MC/Upgrade/Beam7000GeV-Upgrade-MagDown-Nu7.6-25ns-Pythia8/Sim09c-Up02/Reco-Up01/Trig0x52000000/<evtNumber>/LDST
 
-simVersion = 'Sim09c-Up02/Reco-Up01'
+simVersion = 'Sim10-Up08/Digi15-Up04'
 trigVersion = '/'
 
-hlt1filtered = True
+hlt1filtered = False
 
 if hlt1filtered:
     trigVersion = '/Trig0x52000000'
 
 # a list of available samples for testing
-#decay_descriptor = '30000000' # MinBias
+decay_descriptor = '30000000'  # MinBias
 #decay_descriptor = '11114101' # B0 -> K0S mu+ mu-
 #decay_descriptor = '11140400' # B0 -> J/psi omega
 #decay_descriptor = '11142401' # B0 -> J/psi p0
-decay_descriptor = '12143001'  # B+ -> J/psi K+
+#decay_descriptor = '12143001'  # B+ -> J/psi K+
 #decay_descriptor = '12245021' # B+ -> J/psi K+ pi- pi+
 #decay_descriptor = '13144011' # Bs --> Jpsi phi
 #decay_descriptor = '15144001' # Lb -> J/psi p K
@@ -61,20 +61,28 @@ importOptions('/eos/lhcb/wg/BandQ/trigger/Upgrade/MC_samples/%s/simcondTag.py'
 importOptions('/eos/lhcb/wg/BandQ/trigger/Upgrade/MC_samples/%s/ftDecoding.py'
               % simVersion)
 
-options.input_type = 'ROOT'
-options.input_raw_format = 4.3  # from Brunel output
+
+def make_lines():
+    return [builder() for builder in all_lines.values()]
+
 
 # set the options
-options.evt_max = 1000
+evtMax = 1000
+options.evt_max = evtMax
+options.print_freq = evtMax * 0.1
 options.simulation = True
 options.data_type = 'Upgrade'
-options.output_file = f'hlt2_BandQ_{simVersion}_{decay_descriptor}.dst'
+filename = f'hlt2_BandQ_{simVersion.replace("/","-")}_{decay_descriptor}.dst'
+options.output_file = filename
 options.output_type = 'ROOT'
+options.input_type = 'ROOT'
+#options.input_raw_format = 4.3  # from Brunel output
 
-
-def make_lines():
-    return [builder() for builder in all_lines.values()]
-
-
+options.input_raw_format = 0.3  # xdigi or mdf
+#if format is XDIGI or MDF, we need to run the reco
+from RecoConf.reconstruction_objects import reconstruction
 public_tools = [stateProvider_with_simplified_geom()]
-run_moore(options, make_lines, public_tools)
+
+with reconstruction.bind(from_file=False):
+    run_moore(options, make_lines, public_tools)
+#run_moore(options, make_lines, public_tools)
diff --git a/Hlt/Hlt2Conf/options/examples/b_to_charmonia/hlt2_b2cc.py b/Hlt/Hlt2Conf/options/examples/b_to_charmonia/hlt2_b2cc.py
index f1d6bf9ccf070a64c630a82c68ad60cb412f5f9d..f184ed660963b88f0f5d1a2b626c7212f387dfea 100644
--- a/Hlt/Hlt2Conf/options/examples/b_to_charmonia/hlt2_b2cc.py
+++ b/Hlt/Hlt2Conf/options/examples/b_to_charmonia/hlt2_b2cc.py
@@ -85,3 +85,9 @@ public_tools = [stateProvider_with_simplified_geom()]
 with reconstruction.bind(from_file=True):
     config = run_moore(options, make_lines, public_tools)
 dump_hlt2_configuration(config, "hlt2_b2cc_example.tck.json")
+### To enable Fastest reconstruction in HLT2, comment out above three lines and uncomment belows
+#from RecoConf.hlt2_global_reco import reconstruction as hlt2_reconstruction, make_fastest_reconstruction
+#with reconstruction.bind(from_file=False),\
+# hlt2_reconstruction.bind(make_reconstruction=make_fastest_reconstruction):
+# run_moore(options, make_lines, public_tools)
+#dump_hlt2_configuration(config, "hlt2_b2cc_example.tck.json")
diff --git a/Hlt/Hlt2Conf/options/hlt2_check_output.py b/Hlt/Hlt2Conf/options/hlt2_check_output.py
index 73af40b147dc11572a307a511f5697a6ff1a242d..41f29706c80c1597058ca6214e3734576e922c8c 100644
--- a/Hlt/Hlt2Conf/options/hlt2_check_output.py
+++ b/Hlt/Hlt2Conf/options/hlt2_check_output.py
@@ -30,7 +30,7 @@ from Moore.tcks import load_hlt2_configuration
 
 
 def error(msg):
-    print("Hlt2CheckOutput ERROR", error)
+    print("Hlt2CheckOutput ERROR", msg)
 
 
 LHCbApp(
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/__init__.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/__init__.py
index 26290fd37f16172c986b483315fbdd358f776802..63e085dd146d441c826c6f115066eda963073e3e 100644
--- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/__init__.py
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/__init__.py
@@ -16,6 +16,6 @@ from . import spruce_b2cc
 
 # provide "all_lines" for correct registration by the overall HLT2 lines module
 all_lines = {}
-all_lines.update(hlt2_b2cc.hlt2_lines)
+all_lines.update(hlt2_b2cc.all_lines)
 
 sprucing_lines = spruce_b2cc.sprucing_lines
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/b_to_jpsix.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/b_to_jpsix.py
index 1cbad6be18968af4b5b22a7f839d7694d7f91721..e0c7529e0592dcab0fdd8e0ae20e95a88cd4550c 100644
--- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/b_to_jpsix.py
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/b_to_jpsix.py
@@ -8,27 +8,850 @@
 # granted to it by virtue of its status as an Intergovernmental Organization  #
 # or submit itself to any jurisdiction.                                       #
 ###############################################################################
-"""Definition of B -> J/psi X HLT2/Sprucing lines for B2CC.
 """
-from PyConf import configurable
-from Hlt2Conf.standard_particles import make_mass_constrained_jpsi2mumu
-from Hlt2Conf.lines.b_to_charmonia.builders import b_builder
+Definition of Bu/Bd/Bs/Lb... meson decays to JpsiX
+Definition of B -> J/psi X HLT2/Sprucing lines for B2CC.
+"""
 from Hlt2Conf.lines.b_to_charmonia.builders import basic_builder
-from Hlt2Conf.lines.bandq.builders.dimuon import make_detached_jpsi
+from Hlt2Conf.lines.b_to_charmonia.builders import special_builder
+from Hlt2Conf.lines.bandq.builders.dimuon import make_detached_jpsi, make_jpsi
+from GaudiKernel.SystemOfUnits import MeV, picosecond
+from Hlt2Conf.standard_particles import make_long_muons
+from Hlt2Conf.algorithms import ParticleContainersMerger
+from Hlt2Conf.algorithms_thor import require_all, ParticleCombiner
+from RecoConf.reconstruction_objects import make_pvs_v2 as make_pvs
+import Functors as F
+from Functors.math import in_range
+
+
+def make_B2JpsiX(particles,
+                 descriptor,
+                 name="B2CC_BToJpsiX_Combiner",
+                 comb_m_min=3600 * MeV,
+                 comb_m_max=6000 * MeV,
+                 vtx_m_min=3600 * MeV,
+                 vtx_m_max=6000 * MeV,
+                 lifetime=None,
+                 dira=-10.0,
+                 max_vtxchi2pdof=10,
+                 max_ipchi2=None,
+                 pvs=make_pvs):
+    """
+    A generic B->Jpsi X decay maker.
+    """
+    combination_code = (in_range(comb_m_min, F.MASS, comb_m_max))
+    vertex_code = require_all(
+        in_range(vtx_m_min, F.MASS, vtx_m_max), (F.BPVDIRA(make_pvs()) > dira),
+        (F.CHI2DOF < max_vtxchi2pdof))
+
+    if lifetime:
+        vertex_code = require_all(vertex_code, F.BPVLTIME(pvs()) > lifetime)
+    if max_ipchi2:
+        vertex_code = require_all(vertex_code, F.BPVIPCHI2(pvs()) < max_ipchi2)
+
+    return ParticleCombiner(
+        name=name,
+        Inputs=particles,
+        DecayDescriptor=descriptor,
+        CombinationCut=combination_code,
+        CompositeCut=vertex_code)
+
+
+def make_Bs2Jpsif0(particles,
+                   descriptor,
+                   name="B2CC_BsToJpsif0_Combiner",
+                   comb_m_min=5100. * MeV,
+                   comb_m_max=5720. * MeV,
+                   vtx_m_min=5150. * MeV,
+                   vtx_m_max=5670. * MeV,
+                   lifetime=0.2 * picosecond,
+                   dira=0.999,
+                   max_vtxchi2pdof=10.,
+                   max_ipchi2=25):
+    """
+    A generic Bs->Jpsi f0 decay maker.
+    """
+    return make_B2JpsiX(
+        particles=particles,
+        descriptor=descriptor,
+        name=name,
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_m_min,
+        vtx_m_max=vtx_m_max,
+        lifetime=lifetime,
+        dira=dira,
+        max_vtxchi2pdof=max_vtxchi2pdof,
+        max_ipchi2=max_ipchi2)
 
 
-@configurable
-def make_BsToJpsiPhi_detachedline(process):
+def make_Bd2JpsieeKshort_detached(
+        particles,
+        descriptor,
+        name="B2CC_BdToJpsieeKshort_Detached_Combiner",
+        comb_m_min=4400 * MeV,
+        comb_m_max=6000 * MeV,
+        vtx_m_min=4400 * MeV,
+        vtx_m_max=6000 * MeV,
+        lifetime=0.1 * picosecond,
+        dira=-10.0,
+        max_vtxchi2pdof=5):
+    """
+    A generic B0->Jpsi(ee) Kshort decay maker.
+    """
+    return make_B2JpsiX(
+        particles=particles,
+        descriptor=descriptor,
+        name=name,
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_m_min,
+        vtx_m_max=vtx_m_max,
+        lifetime=lifetime,
+        dira=dira,
+        max_vtxchi2pdof=max_vtxchi2pdof)
+
+
+def make_Bd2JpsimumuKshort_detached(
+        particles,
+        descriptor,
+        name="B2CC_BdToJpsimumuKshort_Detached_Combiner",
+        comb_m_min=5000 * MeV,
+        comb_m_max=6000 * MeV,
+        vtx_m_min=5000 * MeV,
+        vtx_m_max=6000 * MeV,
+        lifetime=0.2 * picosecond,
+        dira=-10.0,
+        max_vtxchi2pdof=10):
+    """
+    A generic B0->Jpsi(mumu) Kshort decay maker.
+    """
+    return make_B2JpsiX(
+        particles=particles,
+        descriptor=descriptor,
+        name=name,
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_m_min,
+        vtx_m_max=vtx_m_max,
+        lifetime=lifetime,
+        dira=dira,
+        max_vtxchi2pdof=max_vtxchi2pdof)
+
+
+### Define function for each line
+def make_BsToJpsiPhi_detached_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
 
     phi = basic_builder.make_selected_phi()
-    jpsi = make_mass_constrained_jpsi2mumu()
+    jpsi = basic_builder.make_selected_jpsi2mumu()
+
+    if process == 'spruce':
+        jpsi = make_detached_jpsi()
+
+    line_alg = make_B2JpsiX(
+        name="B2CC_BsToJpsiPhi_Detached_Combiner",
+        particles=[jpsi, phi],
+        descriptor='B_s0 -> J/psi(1S) phi(1020)',
+        comb_m_min=5050 * MeV,
+        comb_m_max=5650 * MeV,
+        vtx_m_min=5150 * MeV,
+        vtx_m_max=5550 * MeV,
+        dira=-10.,
+        lifetime=0.2 * picosecond,
+        max_vtxchi2pdof=20)
+
+    return [jpsi, phi, line_alg]
+
+
+def make_BsToJpsiPhi_extramuonline(process):
     assert process in ['hlt2', 'spruce'
                        ], 'Line must be defined as Hlt2 or Sprucing line!'
 
+    phi = basic_builder.make_selected_phi()
+    jpsi = basic_builder.make_selected_jpsi2mumu()
+    extra_muons = basic_builder.make_muons(pt=1000 * MeV, mipchi2_min=0.)
+
     if process == 'spruce':
         jpsi = make_detached_jpsi()
 
-    line_alg = b_builder.make_Bs2JpsiPhi_detached(
-        particles=[jpsi, phi], descriptors=['B_s0 -> J/psi(1S) phi(1020)'])
+    b = make_B2JpsiX(
+        name="B2CC_BsToJpsiPhi_Detached_Combiner",
+        particles=[jpsi, phi],
+        descriptor='B_s0 -> J/psi(1S) phi(1020)',
+        comb_m_min=5050 * MeV,
+        comb_m_max=5650 * MeV,
+        vtx_m_min=5150 * MeV,
+        vtx_m_max=5550 * MeV,
+        dira=-10,
+        lifetime=0.1 * picosecond,
+        max_vtxchi2pdof=20)
+
+    line_alg = special_builder.make_X2BsLep(
+        particles=[b, extra_muons], descriptor='[system -> B_s0 mu+]cc')
+
+    return [jpsi, phi, extra_muons, b, line_alg]
+
+
+def make_BsToJpsiPhi_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+
+    phi = basic_builder.make_selected_phi()
+    jpsi = basic_builder.make_selected_jpsi2mumu()
+    if process == 'spruce':
+        jpsi = make_jpsi()
+
+    line_alg = make_B2JpsiX(
+        name="B2CC_BsToJpsiPhi_Prompt_Combiner",
+        particles=[jpsi, phi],
+        descriptor='B_s0 -> J/psi(1S) phi(1020)',
+        comb_m_min=5050 * MeV,
+        comb_m_max=5650 * MeV,
+        vtx_m_min=5150 * MeV,
+        vtx_m_max=5550 * MeV,
+        dira=-10,
+        max_vtxchi2pdof=20)
+
+    return [jpsi, phi, line_alg]
+
+
+def make_BsToJpsieePhi_detached_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+
+    phi = basic_builder.make_selected_phi_bs2jpsieephi()
+    jpsi = basic_builder.make_selected_jpsi2ee(mipchi2_e=0)
+    jpsi_ws = basic_builder.make_selected_jpsi2ee_wrongsign(mipchi2_e=0)
+    jpsi_merge = ParticleContainersMerger([jpsi, jpsi_ws],
+                                          name="B2CC_Jpsi2EE_MergeContainer")
+
+    b2jpsieephi = make_B2JpsiX(
+        name="B2CC_BsToJpsieePhi_Detached_Combiner",
+        particles=[jpsi_merge, phi],
+        descriptor='B_s0 -> J/psi(1S) phi(1020)',
+        comb_m_min=4300 * MeV,
+        comb_m_max=5800 * MeV,
+        vtx_m_min=4300 * MeV,
+        vtx_m_max=5800 * MeV,
+        lifetime=0.3 * picosecond,
+        max_vtxchi2pdof=10)
+
+    return [jpsi_merge, phi, b2jpsieephi]
+
+
+def make_BsToJpsieePhi_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    phi = basic_builder.make_selected_phi_bs2jpsieephi()
+    jpsi = basic_builder.make_selected_jpsi2ee()
+    jpsi_ws = basic_builder.make_selected_jpsi2ee_wrongsign()
+    jpsi_merge = ParticleContainersMerger([jpsi, jpsi_ws],
+                                          name="B2CC_Jpsi2EE_MergeContainer")
+
+    b2jpsieephi = make_B2JpsiX(
+        name="B2CC_BsToJpsieePhi_Prompt_Combiner",
+        particles=[jpsi_merge, phi],
+        descriptor='B_s0 -> J/psi(1S) phi(1020)',
+        comb_m_min=4000 * MeV,
+        comb_m_max=5900 * MeV,
+        vtx_m_min=4000 * MeV,
+        vtx_m_max=5900 * MeV,
+        dira=0.9995,
+        max_vtxchi2pdof=10)
+
+    return [jpsi_merge, phi, b2jpsieephi]
+
+
+def make_BdToJpsieeKstar_detached_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+
+    jpsi = basic_builder.make_selected_jpsi2ee(mipchi2_e=0)
+    jpsi_ws = basic_builder.make_selected_jpsi2ee_wrongsign(mipchi2_e=0)
+    jpsi_merge = ParticleContainersMerger([jpsi, jpsi_ws],
+                                          name="B2CC_Jpsi2EE_MergeContainer")
+
+    kstar = basic_builder.make_selected_kstar2kpi(
+        comb_m_min=826 * MeV,
+        comb_m_max=966 * MeV,
+        vtx_m_min=842 * MeV,
+        vtx_m_max=942 * MeV)
+    #kstar_ws = basic_builder.make_selected_kstar2kpi_wrongsign(
+    #comb_m_min=842 * MeV, comb_m_max=942 * MeV, vtx_m_min=842 * MeV, vtx_m_max=942 * MeV)
+    #kstar_merge = ParticleContainersMerger(
+    #    [kstar, kstar_ws], name="B2CC_Kstar2KPi_MergeContainer")
+
+    b2jpsikstar = make_B2JpsiX(
+        name="B2CC_BdToJpsiEEKstar_Detached_Combiner",
+        particles=[jpsi_merge, kstar],
+        descriptor='[B0 -> J/psi(1S) K*(892)0]cc',
+        comb_m_min=4300 * MeV,
+        comb_m_max=5800 * MeV,
+        vtx_m_min=4300 * MeV,
+        vtx_m_max=5800 * MeV,
+        lifetime=0.3 * picosecond,
+        max_vtxchi2pdof=10)
+
+    return [jpsi_merge, kstar, b2jpsikstar]
+
+
+def make_BdToJpsieeKstar_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+
+    kstar = basic_builder.make_selected_kstar2kpi()
+    kstar_ws = basic_builder.make_selected_kstar2kpi_wrongsign()
+    kstar_merge = ParticleContainersMerger(
+        [kstar, kstar_ws], name="B2CC_Kstar2KPi_MergeContainer")
+
+    jpsi = basic_builder.make_selected_jpsi2ee()
+    jpsi_ws = basic_builder.make_selected_jpsi2ee_wrongsign()
+    jpsi_merge = ParticleContainersMerger([jpsi, jpsi_ws],
+                                          name="B2CC_Jpsi2EE_MergeContainer")
+
+    b2jpsikstar = make_B2JpsiX(
+        name="B2CC_BdToJpsieeKstar_Combiner",
+        particles=[jpsi_merge, kstar_merge],
+        descriptor='[B0 -> J/psi(1S) K*(892)0]cc',
+        comb_m_min=4000 * MeV,
+        comb_m_max=5900 * MeV,
+        vtx_m_min=4000 * MeV,
+        vtx_m_max=5900 * MeV,
+        dira=0.9995,
+        max_vtxchi2pdof=10)
+
+    return [jpsi_merge, kstar_merge, b2jpsikstar]
+
+
+def make_BsToJpsiKstar_line(process,
+                            comb_m_min_jpsi=2916 * MeV,
+                            comb_m_max_jpsi=3276 * MeV,
+                            vtx_m_min_jpsi=3016 * MeV,
+                            vtx_m_max_jpsi=3176 * MeV,
+                            comb_m_min=5100 * MeV,
+                            comb_m_max=5700 * MeV,
+                            vtx_m_min=5150 * MeV,
+                            vtx_m_max=5600 * MeV):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    jpsi = basic_builder.make_selected_jpsi2mumu(
+        comb_m_min=comb_m_min_jpsi,
+        comb_m_max=comb_m_max_jpsi,
+        vtx_m_min=vtx_m_min_jpsi,
+        vtx_m_max=vtx_m_max_jpsi)
+    kstar = basic_builder.make_selected_kstar2kpi_widerange()
+
+    b2jpsikstar = make_B2JpsiX(
+        name="B2CC_BsToJpsiKstar_Combiner",
+        particles=[jpsi, kstar],
+        descriptor='[B_s~0 -> J/psi(1S) K*(892)0]cc',
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_m_min,
+        vtx_m_max=vtx_m_max,
+        lifetime=0.2 * picosecond,
+        dira=0.999,
+        max_vtxchi2pdof=10.)
+
+    return [jpsi, kstar, b2jpsikstar]
+
+
+def make_BsToJpsif0_line(process,
+                         comb_m_min_jpsi=2916 * MeV,
+                         comb_m_max_jpsi=3276 * MeV,
+                         vtx_m_min_jpsi=3016 * MeV,
+                         vtx_m_max_jpsi=3176 * MeV):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    jpsi = basic_builder.make_selected_jpsi2mumu(
+        comb_m_min=comb_m_min_jpsi,
+        comb_m_max=comb_m_max_jpsi,
+        vtx_m_min=vtx_m_min_jpsi,
+        vtx_m_max=vtx_m_max_jpsi)
+    f0 = basic_builder.make_selected_f0()
+
+    b2jpsif0 = make_Bs2Jpsif0(
+        name="B2CC_BsToJpsif0_Combiner",
+        particles=[jpsi, f0],
+        descriptor='B_s0 -> J/psi(1S) f_0(980)')
+
+    return [jpsi, f0, b2jpsif0]
+
+
+def make_BsToJpsif0kaon_line(process,
+                             comb_m_min_jpsi=2916 * MeV,
+                             comb_m_max_jpsi=3276 * MeV,
+                             vtx_m_min_jpsi=3016 * MeV,
+                             vtx_m_max_jpsi=3176 * MeV):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    jpsi = basic_builder.make_selected_jpsi2mumu(
+        comb_m_min=comb_m_min_jpsi,
+        comb_m_max=comb_m_max_jpsi,
+        vtx_m_min=vtx_m_min_jpsi,
+        vtx_m_max=vtx_m_max_jpsi)
+    f0kaon = basic_builder.make_selected_f0kaon()
+
+    b2jpsif0kaon = make_Bs2Jpsif0(
+        name="B2CC_BsToJpsif0KK_Combiner",
+        particles=[jpsi, f0kaon],
+        descriptor='B_s0 -> J/psi(1S) f_0(980)')
+
+    return [jpsi, f0kaon, b2jpsif0kaon]
+
+
+def make_BsToJpsif0ws_line(process,
+                           comb_m_min_jpsi=2916 * MeV,
+                           comb_m_max_jpsi=3276 * MeV,
+                           vtx_m_min_jpsi=3016 * MeV,
+                           vtx_m_max_jpsi=3176 * MeV):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    jpsi = basic_builder.make_selected_jpsi2mumu(
+        comb_m_min=comb_m_min_jpsi,
+        comb_m_max=comb_m_max_jpsi,
+        vtx_m_min=vtx_m_min_jpsi,
+        vtx_m_max=vtx_m_max_jpsi)
+    f0ws = basic_builder.make_selected_f0ws()
+    b2jpsif0ws = make_Bs2Jpsif0(
+        name="B2CC_BsToJpsif0PiPi_WS_Combiner",
+        particles=[jpsi, f0ws],
+        descriptor='B_s0 -> J/psi(1S) f_0(980)')
+
+    return [jpsi, f0ws, b2jpsif0ws]
+
+
+def make_BsToJpsif0Prescaled_line(process,
+                                  am_min_jpsi=2896 * MeV,
+                                  am_max_jpsi=3296 * MeV,
+                                  am_min=5170 * MeV,
+                                  am_max=5470 * MeV,
+                                  lifetime=-5.0 * picosecond,
+                                  dira=-10.0):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    jpsi = basic_builder.make_selected_jpsi2mumu(
+        comb_m_min=am_min_jpsi,
+        comb_m_max=am_max_jpsi,
+        vtx_m_min=am_min_jpsi,
+        vtx_m_max=am_max_jpsi)
+    f0Unbiased = basic_builder.make_selected_f0Unbiased()
+
+    b2jpsif0Prescaled = make_Bs2Jpsif0(
+        name="B2CC_BsToJpsif0_Unbiased_Combiner",
+        particles=[jpsi, f0Unbiased],
+        descriptor='B_s0 -> J/psi(1S) f_0(980)',
+        comb_m_min=am_min,
+        comb_m_max=am_max,
+        vtx_m_min=am_min,
+        vtx_m_max=am_max,
+        lifetime=lifetime,
+        dira=dira)
+
+    return [jpsi, f0Unbiased, b2jpsif0Prescaled]
+
+
+def make_LbToJpsipH_line(process,
+                         comb_m_min_jpsi=2916 * MeV,
+                         comb_m_max_jpsi=3276 * MeV,
+                         vtx_m_min_jpsi=3016 * MeV,
+                         vtx_m_max_jpsi=3176 * MeV,
+                         comb_m_min=5020 * MeV,
+                         comb_m_max=6220 * MeV,
+                         vtx_am_min=5120 * MeV,
+                         vtx_am_max=6120 * MeV):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    jpsi = basic_builder.make_selected_jpsi2mumu(
+        comb_m_min=comb_m_min_jpsi,
+        comb_m_max=comb_m_max_jpsi,
+        vtx_m_min=vtx_m_min_jpsi,
+        vtx_m_max=vtx_m_max_jpsi)
+    lambda0 = basic_builder.make_selected_lambda0()
+
+    Lb2jpsipH = make_Bs2Jpsif0(
+        name="B2CC_LbToJpsipH_Combiner",
+        particles=[jpsi, lambda0],
+        descriptor='[Lambda_b0 -> J/psi(1S) Lambda(1520)0 ]cc',
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_am_min,
+        vtx_m_max=vtx_am_max)
+
+    return [jpsi, lambda0, Lb2jpsipH]
+
+
+def make_BdToJpsieeKshort_LL_detached_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+
+    jpsi = basic_builder.make_selected_jpsi2ee(pid_e=1)
+    kshort_LL = basic_builder.make_ks_LL(bpvvdchi2=5, chi2vx=20)
+
+    b2jpsikshort = make_Bd2JpsieeKshort_detached(
+        name="B2CC_BdToJpsieeKshortLL_Detached_Combiner",
+        particles=[jpsi, kshort_LL],
+        descriptor='[B0 -> J/psi(1S) KS0]cc',
+        lifetime=0.1 * picosecond)
+
+    return [jpsi, kshort_LL, b2jpsikshort]
+
+
+def make_BdToJpsieeKshort_DD_detached_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    jpsi = basic_builder.make_selected_jpsi2ee(pid_e=1)
+    kshort_DD = basic_builder.make_ks_DD(bpvvdchi2=5, chi2vx=20)
+    b2jpsikshort = make_Bd2JpsieeKshort_detached(
+        name="B2CC_BdToJpsieeKshortDD_Detached_Combiner",
+        particles=[jpsi, kshort_DD],
+        descriptor='[B0 -> J/psi(1S) KS0]cc',
+        lifetime=0.1 * picosecond)
+
+    return [jpsi, kshort_DD, b2jpsikshort]
+
+
+def make_BdToJpsieeKshort_LL_tight_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    jpsi = basic_builder.make_selected_jpsi2ee(pid_e=2, mipchi2_e=1)
+    kshort_LL = basic_builder.make_ks_LL(bpvvdchi2=5, chi2vx=20)
+
+    b2jpsikshort = make_Bd2JpsieeKshort_detached(
+        name="B2CC_BdToJpsieeKshortLL_Tight_Combiner",
+        particles=[jpsi, kshort_LL],
+        descriptor='[B0 -> J/psi(1S) KS0]cc',
+        lifetime=None)
+
+    return [jpsi, kshort_LL, b2jpsikshort]
+
+
+def make_BdToJpsieeKshort_DD_tight_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    jpsi = basic_builder.make_selected_jpsi2ee(pid_e=2, mipchi2_e=1)
+    kshort_DD = basic_builder.make_ks_DD(bpvvdchi2=5, chi2vx=20)
+
+    b2jpsikshort = make_Bd2JpsieeKshort_detached(
+        name="B2CC_BdToJpsieeKshortDD_Tight_Combiner",
+        particles=[jpsi, kshort_DD],
+        descriptor='[B0 -> J/psi(1S) KS0]cc',
+        lifetime=None)
+
+    return [jpsi, kshort_DD, b2jpsikshort]
+
+
+def make_BuToJpsieeKplus_detached_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    jpsi = basic_builder.make_selected_jpsi2ee(pid_e=1)
+    kplus = basic_builder.make_kaons(pt=500 * MeV)
+    b2jpsikplus = make_Bd2JpsieeKshort_detached(
+        comb_m_min=4900 * MeV,
+        vtx_m_min=5000 * MeV,
+        lifetime=0.1 * picosecond,
+        particles=[jpsi, kplus],
+        descriptor="[B+ -> J/psi(1S) K+]cc")
+
+    return [jpsi, kplus, b2jpsikplus]
+
+
+def make_BdToJpsimumuKshort_LL_tight_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    muons = basic_builder.filter_muons_loose(
+        particles=make_long_muons(), mu_pidk=20, mu_pidp=20)
+    jpsi = basic_builder.make_selected_jpsi_bd2jpsimumukshort(muons=muons)
+    kshort_LL = basic_builder.make_ks_LL(bpvvdchi2=5, chi2vx=30)
+    b2jpsikshort = make_Bd2JpsimumuKshort_detached(
+        lifetime=None,
+        particles=[jpsi, kshort_LL],
+        descriptor='[B0 -> J/psi(1S) KS0]cc')
+
+    return [jpsi, kshort_LL, b2jpsikshort]
+
+
+def make_BdToJpsimumuKshort_DD_tight_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    muons = basic_builder.filter_muons_loose(
+        particles=make_long_muons(), mu_pidk=20, mu_pidp=20)
+    jpsi = basic_builder.make_selected_jpsi_bd2jpsimumukshort(muons=muons)
+    kshort_DD = basic_builder.make_ks_DD(bpvvdchi2=5, chi2vx=30)
+    b2jpsikshort = make_Bd2JpsimumuKshort_detached(
+        lifetime=None,
+        particles=[jpsi, kshort_DD],
+        descriptor='[B0 -> J/psi(1S) KS0]cc')
+
+    return [jpsi, kshort_DD, b2jpsikshort]
+
+
+def make_BdToJpsimumuKshort_LD_tight_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    muons = basic_builder.filter_muons_loose(
+        particles=make_long_muons(), mu_pidk=20, mu_pidp=20)
+    jpsi = basic_builder.make_selected_jpsi_bd2jpsimumukshort(muons=muons)
+    kshort_LD = basic_builder.make_ks_LD(bpvvdchi2=5, chi2vx=30)
+    b2jpsikshort = make_Bd2JpsimumuKshort_detached(
+        lifetime=None,
+        particles=[jpsi, kshort_LD],
+        descriptor='[B0 -> J/psi(1S) KS0]cc')
+
+    return [jpsi, kshort_LD, b2jpsikshort]
+
+
+def make_BdToJpsimumuKshort_UL_tight_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    muons = basic_builder.filter_muons_loose(
+        particles=make_long_muons(), mu_pidk=20, mu_pidp=20)
+    jpsi = basic_builder.make_selected_jpsi_bd2jpsimumukshort(muons=muons)
+    kshort_UL = basic_builder.make_ks_UL(bpvvdchi2=5, chi2vx=30)
+    b2jpsikshort = make_Bd2JpsimumuKshort_detached(
+        lifetime=None,
+        particles=[jpsi, kshort_UL],
+        descriptor='[B0 -> J/psi(1S) KS0]cc')
+
+    return [jpsi, kshort_UL, b2jpsikshort]
+
+
+def make_BdToJpsimumuKshort_LL_detached_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    muons = basic_builder.filter_muons_loose(
+        particles=make_long_muons(), mu_pidk=20, mu_pidp=20)
+    jpsi = basic_builder.make_selected_jpsi_bd2jpsimumukshort(muons=muons)
+    kshort_LL = basic_builder.make_ks_LL(bpvvdchi2=5, chi2vx=30)
+
+    b2jpsikshort = make_Bd2JpsimumuKshort_detached(
+        lifetime=0.1 * picosecond,
+        particles=[jpsi, kshort_LL],
+        descriptor='[B0 -> J/psi(1S) KS0]cc')
+
+    return [jpsi, kshort_LL, b2jpsikshort]
+
+
+def make_BdToJpsimumuKshort_DD_detached_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    muons = basic_builder.filter_muons_loose(
+        particles=make_long_muons(), mu_pidk=20, mu_pidp=20)
+    jpsi = basic_builder.make_selected_jpsi_bd2jpsimumukshort(muons=muons)
+    kshort_DD = basic_builder.make_ks_DD(bpvvdchi2=5, chi2vx=30)
+
+    b2jpsikshort = make_Bd2JpsimumuKshort_detached(
+        lifetime=0.1 * picosecond,
+        particles=[jpsi, kshort_DD],
+        descriptor='[B0 -> J/psi(1S) KS0]cc')
+
+    return [jpsi, kshort_DD, b2jpsikshort]
+
+
+def make_BdToJpsimumuKshort_LD_detached_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    muons = basic_builder.filter_muons_loose(
+        particles=make_long_muons(), mu_pidk=20, mu_pidp=20)
+    jpsi = basic_builder.make_selected_jpsi_bd2jpsimumukshort(muons=muons)
+    kshort_LD = basic_builder.make_ks_LD(bpvvdchi2=5, chi2vx=30)
+
+    b2jpsikshort = make_Bd2JpsimumuKshort_detached(
+        lifetime=0.1 * picosecond,
+        particles=[jpsi, kshort_LD],
+        descriptor='[B0 -> J/psi(1S) KS0]cc')
+
+    return [jpsi, kshort_LD, b2jpsikshort]
+
+
+def make_BdToJpsimumuKshort_UL_detached_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    muons = basic_builder.filter_muons_loose(
+        particles=make_long_muons(), mu_pidk=20, mu_pidp=20)
+    jpsi = basic_builder.make_selected_jpsi_bd2jpsimumukshort(muons=muons)
+    kshort_UL = basic_builder.make_ks_UL(bpvvdchi2=5, chi2vx=30)
+
+    b2jpsikshort = make_Bd2JpsimumuKshort_detached(
+        lifetime=0.1 * picosecond,
+        particles=[jpsi, kshort_UL],
+        descriptor='[B0 -> J/psi(1S) KS0]cc')
+
+    return [jpsi, kshort_UL, b2jpsikshort]
+
+
+def make_BdTopsitwosmumuKshort_LL_tight_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    muons = basic_builder.filter_muons_loose(
+        particles=make_long_muons(), mu_pidk=20, mu_pidp=20)
+    psi = basic_builder.make_selected_jpsi_bd2jpsimumukshort(
+        psi2S=True, muons=muons)
+    kshort_LL = basic_builder.make_ks_LL(bpvvdchi2=5, chi2vx=30)
+
+    b2psikshort = make_Bd2JpsimumuKshort_detached(
+        lifetime=None,
+        particles=[psi, kshort_LL],
+        descriptor='[B0 -> psi(2S) KS0]cc')
+
+    return [psi, kshort_LL, b2psikshort]
+
+
+def make_BdTopsitwosmumuKshort_DD_tight_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    muons = basic_builder.filter_muons_loose(
+        particles=make_long_muons(), mu_pidk=20, mu_pidp=20)
+    psi = basic_builder.make_selected_jpsi_bd2jpsimumukshort(
+        psi2S=True, muons=muons)
+    kshort_DD = basic_builder.make_ks_DD(bpvvdchi2=5, chi2vx=30)
+
+    b2psikshort = make_Bd2JpsimumuKshort_detached(
+        lifetime=None,
+        particles=[psi, kshort_DD],
+        descriptor='[B0 -> psi(2S) KS0]cc')
+
+    return [psi, kshort_DD, b2psikshort]
+
+
+def make_BdTopsitwosmumuKshort_LL_detached_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    muons = basic_builder.filter_muons_loose(
+        particles=make_long_muons(), mu_pidk=20, mu_pidp=20)
+    psi = basic_builder.make_selected_jpsi_bd2jpsimumukshort(
+        psi2S=True, muons=muons)
+    kshort_LL = basic_builder.make_ks_LL(bpvvdchi2=5, chi2vx=30)
+
+    b2psikshort = make_Bd2JpsimumuKshort_detached(
+        lifetime=0.1 * picosecond,
+        particles=[psi, kshort_LL],
+        descriptor='[B0 -> psi(2S) KS0]cc')
+
+    return [psi, kshort_LL, b2psikshort]
+
+
+def make_BdTopsitwosmumuKshort_DD_detached_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    muons = basic_builder.filter_muons_loose(
+        particles=make_long_muons(), mu_pidk=20, mu_pidp=20)
+    psi = basic_builder.make_selected_jpsi_bd2jpsimumukshort(
+        psi2S=True, muons=muons)
+    kshort_DD = basic_builder.make_ks_DD(bpvvdchi2=5, chi2vx=30)
+
+    b2psikshort = make_Bd2JpsimumuKshort_detached(
+        lifetime=0.1 * picosecond,
+        particles=[psi, kshort_DD],
+        descriptor='[B0 -> psi(2S) KS0]cc')
+
+    return [psi, kshort_DD, b2psikshort]
+
+
+def make_BuToJpsimumuKplus_tight_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    muons = basic_builder.filter_muons_loose(
+        particles=make_long_muons(), mu_pidk=20, mu_pidp=20)
+    jpsi = basic_builder.make_selected_jpsi_bd2jpsimumukshort(muons=muons)
+    kplus = basic_builder.make_kaons(pt=800 * MeV, pid=0, p=4000 * MeV)
+
+    b2jpsikplus = make_Bd2JpsimumuKshort_detached(
+        comb_m_min=5150 * MeV,
+        comb_m_max=5450 * MeV,
+        vtx_m_min=5150 * MeV,
+        vtx_m_max=5450 * MeV,
+        lifetime=None,
+        particles=[jpsi, kplus],
+        descriptor="[B+ -> J/psi(1S) K+]cc")
+
+    return [jpsi, kplus, b2jpsikplus]
+
+
+def make_BuToJpsimumuKplus_detached_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    muons = basic_builder.filter_muons_loose(
+        particles=make_long_muons(), mu_pidk=20, mu_pidp=20)
+    jpsi = basic_builder.make_selected_jpsi_bd2jpsimumukshort(muons=muons)
+    kplus = basic_builder.make_kaons(pt=800 * MeV, pid=-1, p=3000 * MeV)
+    b2jpsikplus = make_Bd2JpsimumuKshort_detached(
+        particles=[jpsi, kplus],
+        descriptor="[B+ -> J/psi(1S) K+]cc",
+        lifetime=0.1 * picosecond,
+        comb_m_min=5150 * MeV,
+        comb_m_max=5450 * MeV,
+        vtx_m_min=5150 * MeV,
+        vtx_m_max=5450 * MeV)
+
+    return [jpsi, kplus, b2jpsikplus]
+
+
+def make_BdToJpsimumuKstar_detached_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    muons = basic_builder.filter_muons_loose(
+        particles=make_long_muons(), pidmu=1, mu_pidk=20, mu_pidp=20)
+    jpsi = basic_builder.make_selected_jpsi_bd2jpsimumukshort(muons=muons)
+    kstar = basic_builder.make_selected_kstar2kpi(
+        comb_m_min=826 * MeV,
+        comb_m_max=966 * MeV,
+        vtx_m_min=826 * MeV,
+        vtx_m_max=966 * MeV,
+        max_vchi2pdof=16,
+        max_docachi2=20.0,
+        pt=500. * MeV,
+        pt_pi=500. * MeV,
+        p_pi=1000. * MeV,
+        tr_chi2pdof_pi=10,
+        pt_k=500. * MeV,
+        p_k=1000. * MeV,
+        tr_chi2pdof_k=10,
+        pid_k=-2,
+        pid_pi=3)
+    b2jpsikstar = make_Bd2JpsimumuKshort_detached(
+        particles=[jpsi, kstar],
+        descriptor='[B0 -> J/psi(1S) K*(892)0]cc',
+        lifetime=0.1 * picosecond,
+        comb_m_min=5150 * MeV,
+        comb_m_max=5450 * MeV,
+        vtx_m_min=5150 * MeV,
+        vtx_m_max=5450 * MeV)
+
+    return [jpsi, kstar, b2jpsikstar]
+
+
+def make_BdToJpsimumuKstar_tight_line(process):
+    assert process in ['hlt2', 'spruce'
+                       ], 'Line must be defined as Hlt2 or Sprucing line!'
+    muons = basic_builder.filter_muons_loose(
+        particles=make_long_muons(), pidmu=1.5, mu_pidk=20, mu_pidp=20)
+    jpsi = basic_builder.make_selected_jpsi_bd2jpsimumukshort(muons=muons)
+    kstar = basic_builder.make_selected_kstar2kpi(
+        comb_m_min=826 * MeV,
+        comb_m_max=966 * MeV,
+        vtx_m_min=826 * MeV,
+        vtx_m_max=966 * MeV,
+        max_vchi2pdof=16,
+        max_docachi2=20.0,
+        pt=500. * MeV,
+        pt_pi=500. * MeV,
+        p_pi=1500. * MeV,
+        tr_chi2pdof_pi=10,
+        pt_k=500. * MeV,
+        p_k=1500. * MeV,
+        tr_chi2pdof_k=10,
+        pid_k=0,
+        pid_pi=0)
+    b2jpsikstar = make_Bd2JpsimumuKshort_detached(
+        particles=[jpsi, kstar],
+        descriptor='[B0 -> J/psi(1S) K*(892)0]cc',
+        lifetime=None,
+        comb_m_min=5150 * MeV,
+        comb_m_max=5450 * MeV,
+        vtx_m_min=5150 * MeV,
+        vtx_m_max=5450 * MeV)
 
-    return line_alg
+    return [jpsi, kstar, b2jpsikstar]
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/builders/b_builder.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/builders/b_builder.py
deleted file mode 100644
index b156472ef860d40675ca04c7e6a66189b938d4db..0000000000000000000000000000000000000000
--- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/builders/b_builder.py
+++ /dev/null
@@ -1,197 +0,0 @@
-###############################################################################
-# (c) Copyright 2019-2021 CERN for the benefit of the LHCb Collaboration      #
-#                                                                             #
-# This software is distributed under the terms of the GNU General Public      #
-# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
-#                                                                             #
-# In applying this licence, CERN does not waive the privileges and immunities #
-# granted to it by virtue of its status as an Intergovernmental Organization  #
-# or submit itself to any jurisdiction.                                       #
-###############################################################################
-"""
-Definition of Bu/Bd/Bs/... meson decays that are shared between many
-B2CC selections, and therefore are defined centrally.
-"""
-from GaudiKernel.SystemOfUnits import MeV, picosecond
-
-from Hlt2Conf.algorithms import require_all, ParticleCombinerWithPVs
-from PyConf import configurable
-from RecoConf.reconstruction_objects import make_pvs
-
-
-@configurable
-def make_B2JpsiX(particles,
-                 descriptors,
-                 name="B2CC_BToJpsiX_Combiner",
-                 am_min=3600 * MeV,
-                 am_max=6000 * MeV,
-                 am_min_vtx=3600 * MeV,
-                 am_max_vtx=6000 * MeV,
-                 lifetime=None,
-                 dira=-10.0,
-                 vtx_chi2pdof=10):
-    """
-    A generic B->Jpsi X decay maker.
-    """
-    combination_code = require_all("in_range({am_min}, AM, {am_max})").format(
-        am_min=am_min, am_max=am_max)
-    vertex_code = require_all(f"in_range({am_min_vtx}, M, {am_max_vtx})",
-                              f"BPVDIRA() > {dira}",
-                              f"VFASPF(VCHI2PDOF) < {vtx_chi2pdof}")
-    if lifetime:
-        vertex_code += f'& (BPVLTIME() > {lifetime})'
-
-    return ParticleCombinerWithPVs(
-        particles=particles,
-        pvs=make_pvs(),
-        DecayDescriptors=descriptors,
-        CombinationCut=combination_code,
-        MotherCut=vertex_code)
-
-
-@configurable
-def make_Bs2JpsiPhi(particles,
-                    descriptors,
-                    name="B2CC_BToJpsiX_Combiner",
-                    am_min=5050 * MeV,
-                    am_max=5650 * MeV,
-                    am_min_vtx=5050 * MeV,
-                    am_max_vtx=5650 * MeV,
-                    vtx_chi2pdof=20):
-    """
-    A generic Bs->Jpsi Phi decay maker.
-    """
-    return make_B2JpsiX(
-        particles=particles,
-        descriptors=descriptors,
-        name=name,
-        am_min=am_min,
-        am_max=am_max,
-        am_min_vtx=am_min_vtx,
-        am_max_vtx=am_max_vtx,
-        vtx_chi2pdof=vtx_chi2pdof)
-
-
-@configurable
-def make_Bs2JpsiPhi_detached(particles,
-                             descriptors,
-                             name="B2CC_BToJpsiX_Combiner",
-                             am_min=5050 * MeV,
-                             am_max=5650 * MeV,
-                             am_min_vtx=5050 * MeV,
-                             am_max_vtx=5650 * MeV,
-                             lifetime=0.3 * picosecond,
-                             vtx_chi2pdof=20):
-    """
-    A generic Bs->Jpsi Phi detached decay maker.
-    """
-    return make_B2JpsiX(
-        particles=particles,
-        descriptors=descriptors,
-        name=name,
-        am_min=am_min,
-        am_max=am_max,
-        am_min_vtx=am_min_vtx,
-        am_max_vtx=am_max_vtx,
-        lifetime=lifetime,
-        vtx_chi2pdof=vtx_chi2pdof)
-
-
-@configurable
-def make_Bs2JpsieePhi_detached(particles,
-                               descriptors,
-                               name="B2CC_BsToJpsieePhi_Detached_Combiner",
-                               am_min=4300 * MeV,
-                               am_max=5800 * MeV,
-                               am_min_vtx=4300 * MeV,
-                               am_max_vtx=5800 * MeV,
-                               lifetime=0.3 * picosecond,
-                               vtx_chi2pdof=10):
-    """
-    A generic Bs->Jpsi(ee) Phi decay maker.
-    """
-    return make_B2JpsiX(
-        particles=particles,
-        descriptors=descriptors,
-        name=name,
-        am_min=am_min,
-        am_max=am_max,
-        am_min_vtx=am_min_vtx,
-        am_max_vtx=am_max_vtx,
-        lifetime=lifetime,
-        vtx_chi2pdof=vtx_chi2pdof)
-
-
-@configurable
-def make_Bs2JpsieePhi(particles,
-                      descriptors,
-                      name="B2CC_BsToJpsieePhi_Combiner",
-                      am_min=4000 * MeV,
-                      am_max=5900 * MeV,
-                      am_min_vtx=4000 * MeV,
-                      am_max_vtx=5900 * MeV,
-                      dira=0.9995,
-                      vtx_chi2pdof=10):
-    """
-    A generic Bs->Jpsi(ee) Phi decay maker.
-    """
-    return make_B2JpsiX(
-        particles=particles,
-        descriptors=descriptors,
-        name=name,
-        am_min=am_min,
-        am_max=am_max,
-        am_min_vtx=am_min_vtx,
-        am_max_vtx=am_max_vtx,
-        dira=dira,
-        vtx_chi2pdof=vtx_chi2pdof)
-
-
-@configurable
-def make_Bd2JpsieeKstar_detached(particles,
-                                 descriptors,
-                                 name="B2CC_BdToJpsieeKstar_Detached_Combiner",
-                                 am_min=4300 * MeV,
-                                 am_max=5800 * MeV,
-                                 am_min_vtx=4300 * MeV,
-                                 am_max_vtx=5800 * MeV,
-                                 lifetime=0.3 * picosecond,
-                                 vtx_chi2pdof=10):
-    """
-    A generic B0->Jpsi(ee) Kstar decay maker.
-    """
-    return make_B2JpsiX(
-        particles=particles,
-        descriptors=descriptors,
-        name=name,
-        am_min=am_min,
-        am_max=am_max,
-        am_min_vtx=am_min_vtx,
-        am_max_vtx=am_max_vtx,
-        lifetime=lifetime,
-        vtx_chi2pdof=vtx_chi2pdof)
-
-
-@configurable
-def make_Bd2JpsieeKstar(particles,
-                        descriptors,
-                        name="B2CC_BdToJpsieeKstar_Combiner",
-                        am_min=4000 * MeV,
-                        am_max=5900 * MeV,
-                        am_min_vtx=4000 * MeV,
-                        am_max_vtx=5900 * MeV,
-                        dira=0.9995,
-                        vtx_chi2pdof=10):
-    """
-    A generic B0->Jpsi(ee) Kstar decay maker.
-    """
-    return make_B2JpsiX(
-        particles=particles,
-        descriptors=descriptors,
-        name=name,
-        am_min=am_min,
-        am_max=am_max,
-        am_min_vtx=am_min_vtx,
-        am_max_vtx=am_max_vtx,
-        dira=dira,
-        vtx_chi2pdof=vtx_chi2pdof)
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/builders/basic_builder.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/builders/basic_builder.py
index af79d42983cb24aa52fc8baac63b955a04f9344f..b0f34473847b0554885b66ebf5c38d34ffed0f9a 100644
--- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/builders/basic_builder.py
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/builders/basic_builder.py
@@ -14,71 +14,134 @@ from __future__ import absolute_import, division, print_function
 
 from GaudiKernel.SystemOfUnits import GeV, MeV
 
-from RecoConf.reconstruction_objects import make_pvs
+from RecoConf.reconstruction_objects import make_pvs_v2 as make_pvs
 
-from Hlt2Conf.algorithms import require_all, ParticleCombinerWithPVs, ParticleFilterWithPVs
-from PyConf import configurable
-from Hlt2Conf.standard_particles import (make_has_rich_long_pions,
-                                         make_has_rich_long_kaons,
-                                         make_long_electrons_no_brem)
+from Hlt2Conf.algorithms_thor import require_all, ParticleCombiner, ParticleFilter
+
+from Hlt2Conf.standard_particles import (
+    make_has_rich_long_pions, make_has_rich_long_kaons, make_ismuon_long_muon,
+    make_long_electrons_no_brem, make_has_rich_long_protons, make_KsLL,
+    make_KsDD, make_KsLD, make_KsUL, make_long_pions_for_V0,
+    make_down_pions_for_V0, make_up_pions_for_V0)
+
+from Hlt2Conf.algorithms import ParticleContainersMerger
+
+import Functors as F
+from Functors.math import in_range
 
 ####################################
 # Track selections                 #
 ####################################
 
 
-@configurable
-def make_selected_particles(make_particles=make_has_rich_long_pions,
-                            pvs=make_pvs,
-                            tr_chi2pdof_max=0,
-                            mipchi2_min=0,
-                            pt_min=250 * MeV,
-                            p_min=2 * GeV,
-                            pid=None):
-
-    code = require_all('PT > {pt_min}', 'P > {p_min}',
-                       'TRCHI2DOF < {tr_chi2pdof_max}',
-                       'MIPCHI2DV(PRIMARY) > {mipchi2_min}').format(
-                           pt_min=pt_min,
-                           p_min=p_min,
-                           tr_chi2pdof_max=tr_chi2pdof_max,
-                           mipchi2_min=mipchi2_min)
+def make_selected_particles(
+        make_particles=make_has_rich_long_pions,
+        make_pvs=make_pvs,
+        tr_chi2pdof_max=99,  ## placeholder to be tightened once it is reliable
+        mipchi2_min=0,
+        pt_min=250 * MeV,
+        p_min=0 * GeV,
+        pid=None,
+        isMuon=None,
+        filterAlg=None,
+        make_zip=False):
+
+    code = require_all(F.PT > pt_min, F.P > p_min, F.CHI2DOF < tr_chi2pdof_max)
+    if mipchi2_min is not None:
+        code = code & (F.MINIPCHI2(make_pvs()) > mipchi2_min)
     if pid is not None:
-        code += ' & ({})'.format(pid)
-    return ParticleFilterWithPVs(make_particles(), pvs(), Code=code)
+        code &= (pid)
+    if isMuon is not None:
+        code &= (isMuon)
+
+    return ParticleFilter(make_particles(), F.FILTER(code))
 
 
-@configurable
-def make_pions(pid=5, tr_chi2pdof_max=0, pt=200 * MeV, p=2 * GeV):
+def make_pions(pid=5,
+               tr_chi2pdof_max=5,
+               pt=200 * MeV,
+               p=1 * GeV,
+               **decay_arguments):
     """Return pions filtered by thresholds common to B2CC decay product selections."""
+
     return make_selected_particles(
         make_particles=make_has_rich_long_pions,
         tr_chi2pdof_max=tr_chi2pdof_max,
         pt_min=pt,
         p_min=p,
-        pid='PIDK < ' + str(pid))
+        pid=(F.PID_K < pid),
+        **decay_arguments)
 
 
-@configurable
-def make_kaons(pid=-3, tr_chi2pdof_max=5, pt=200 * MeV, p=2 * GeV):
+def make_kaons(
+        pid=-3,
+        tr_chi2pdof_max=10,  ##TODO: to be tightened once the variable become more reliable
+        pt=200 * MeV,
+        p=2 * GeV,
+        **decay_arguments):
     """Return kaons filtered by thresholds common to B2CC decay product selections."""
+
     return make_selected_particles(
         make_particles=make_has_rich_long_kaons,
         tr_chi2pdof_max=tr_chi2pdof_max,
         pt_min=pt,
         p_min=p,
-        pid='PIDK > ' + str(pid))
+        pid=(F.PID_K > pid),
+        **decay_arguments)
+
 
+def make_muons(pid=-999,
+               tr_chi2pdof_max=5,
+               pt=500 * MeV,
+               p=0 * GeV,
+               mipchi2_min=0,
+               ismuon=F.ISMUON,
+               **decay_arguments):
+    """Return muons filtered by thresholds common to B2CC decay product selections."""
 
-@configurable
-def make_electrons(pid=-3, tr_chi2pdof_max=3, pt=250 * MeV, mipchi2_min=0):
+    return make_selected_particles(
+        make_particles=make_ismuon_long_muon,
+        tr_chi2pdof_max=tr_chi2pdof_max,
+        mipchi2_min=mipchi2_min,
+        pt_min=pt,
+        p_min=p,
+        pid=(F.PID_MU > pid),
+        isMuon=ismuon,
+        **decay_arguments)
+
+
+def make_electrons(
+        particles=make_long_electrons_no_brem,
+        pid=-999,
+        tr_chi2pdof_max=10,  ## TODO to be tighten (3) once the variable is reliable
+        pt=250 * MeV,
+        mipchi2_min=0,
+        **decay_arguments):
     """Return electrons filtered by thresholds common to B2CC decay product Jpsi->ee selections."""
     return make_selected_particles(
-        make_particles=make_long_electrons_no_brem,
+        make_particles=particles,
         tr_chi2pdof_max=tr_chi2pdof_max,
         pt_min=pt,
         mipchi2_min=mipchi2_min,
-        pid='PIDe > ' + str(pid))
+        pid=(F.PID_E > pid),
+        **decay_arguments)
+
+
+def make_protons(
+        pid_p=0.,
+        delta_pid_pK=-10.,
+        tr_chi2pdof_max=10.,  ##TODO to be tighten once the variable is reliable
+        p_min=0 * MeV,
+        mipchi2_min=4.,
+        **decay_arguments):
+    """Return protons filtered by thresholds common to B2CC decay product selections."""
+    return make_selected_particles(
+        make_particles=make_has_rich_long_protons,
+        tr_chi2pdof_max=tr_chi2pdof_max,
+        p_min=p_min,
+        mipchi2_min=mipchi2_min,
+        pid=((F.PID_P > pid_p) & ((F.PID_P - F.PID_K) > delta_pid_pK)),
+        **decay_arguments)
 
 
 ####################################
@@ -86,283 +149,801 @@ def make_electrons(pid=-3, tr_chi2pdof_max=3, pt=250 * MeV, mipchi2_min=0):
 ####################################
 
 
-@configurable
-def make_selected_phi(name="B2CC_Phi_Filter",
-                      make_pvs=make_pvs,
-                      am_min=980 * MeV,
-                      am_max=1060 * MeV,
-                      pt=500. * MeV,
-                      adoca_chi2=30,
-                      vchi2=10):
+def make_twobody(particles,
+                 descriptor,
+                 comb_m_min,
+                 comb_m_max,
+                 vtx_m_min,
+                 vtx_m_max,
+                 name="B2CC_TwoBody_Combiner",
+                 pt=500. * MeV,
+                 pt_sum=0. * MeV,
+                 max_docachi2=30.,
+                 max_vchi2pdof=10):
     """
     Filter phi candiates for B2CC.  Default cuts refered to Bs2JpsiPhi.
     """
-    kaons = make_kaons(pid=0)
-    descriptors = ['phi(1020) -> K+ K-']
-    combination_code = require_all("in_range({am_min}, AM, {am_max})",
-                                   "ADOCACHI2CUT({adoca_chi2}, '')").format(
-                                       am_min=am_min,
-                                       am_max=am_max,
-                                       adoca_chi2=adoca_chi2)
-
-    vertex_code = require_all("(VFASPF(VCHI2) < {vchi2})", "PT > {pt}").format(
-        vchi2=vchi2, pt=pt)
-
-    return ParticleCombinerWithPVs(
-        particles=[kaons],
-        pvs=make_pvs(),
-        DecayDescriptors=descriptors,
+
+    combination_code = require_all(
+        in_range(comb_m_min, F.MASS, comb_m_max),
+        F.MAXDOCACHI2CUT(max_docachi2),
+        F.SUM(F.PT) > pt_sum)
+
+    ## F.CHI2 = VCHI2/CHI2VX = F.CHI2DOF, tiny difference from LOKI functor, see check: https://indico.cern.ch/event/995287/contributions/4633380/attachments/2354933/4018715/WP3%20JieWu%2020211129.pdf
+    vertex_code = require_all(F.PT > pt, F.CHI2 < max_vchi2pdof,
+                              in_range(vtx_m_min, F.MASS, vtx_m_max))
+
+    return ParticleCombiner(
+        name=name,
+        Inputs=particles,
+        DecayDescriptor=descriptor,
         CombinationCut=combination_code,
-        MotherCut=vertex_code)
-
-
-@configurable
-def make_selected_phi_bs2jpsieephi(make_pvs=make_pvs,
-                                   am_min=990 * MeV,
-                                   am_max=1050 * MeV,
-                                   am_min_vtx=990 * MeV,
-                                   am_max_vtx=1050 * MeV,
-                                   vchi2pdof=4,
-                                   pt=1000. * MeV,
-                                   adoca_chi2=30,
-                                   tr_chi2pdof=1.5,
-                                   pid_k=1,
-                                   pt_k=400. * MeV,
-                                   p_k=4. * GeV):
+        CompositeCut=vertex_code)
+
+
+def make_selected_phi(
+        name="B2CC_Phi2KK_Filter",
+        descriptor='phi(1020) -> K+ K-',
+        comb_m_min=980. * MeV,
+        comb_m_max=1060. * MeV,
+        vtx_m_min=980. * MeV,
+        vtx_m_max=1060. * MeV,
+        pt=500. * MeV,
+        max_docachi2=30.,
+        max_vchi2pdof=25.,
+        tr_chi2pdof_max=10,  ##TODO to be tightened once the variable is more reliable
+        pid_k=0,
+        pt_k=500. * MeV,
+        p_k=2. * GeV):
+
+    kaons = make_kaons(
+        pid=pid_k, tr_chi2pdof_max=tr_chi2pdof_max, pt=pt_k, p=p_k)
+
+    return make_twobody(
+        particles=[kaons, kaons],
+        descriptor=descriptor,
+        name=name,
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_m_min,
+        vtx_m_max=vtx_m_max,
+        pt=pt,
+        max_docachi2=max_docachi2,
+        max_vchi2pdof=max_vchi2pdof)
+
+
+def make_selected_phi_bs2jpsieephi(
+        name="B2CC_Phi2KK_Bs2JpsiEEPhi",
+        descriptor_rs='phi(1020) -> K- K+',
+        descriptor_ws='[phi(1020) -> K- K-]cc',
+        comb_m_min=980. * MeV,
+        comb_m_max=1060. * MeV,
+        vtx_m_min=980. * MeV,
+        vtx_m_max=1060. * MeV,
+        max_vchi2pdof=15,
+        pt=1000. * MeV,
+        max_docachi2=30.,
+        tr_chi2pdof=10,  ##TODO to be tightened once the variable is more reliable
+        pid_k=1,
+        pt_k=400. * MeV,
+        p_k=4. * GeV):
     """
     Filter phi candiates for B2CC.  Default cuts refered to Bs2JpsieePhi.
     """
     kaons = make_kaons(pid=pid_k, tr_chi2pdof_max=tr_chi2pdof, pt=pt_k, p=p_k)
-
-    descriptors = ['phi(1020) -> K- K+', '[phi(1020) -> K+ K+]cc']
-
-    combination_code = require_all("in_range({am_min}, AM, {am_max})",
-                                   "ADOCACHI2CUT({adoca_chi2}, '')").format(
-                                       am_min=am_min,
-                                       am_max=am_max,
-                                       adoca_chi2=adoca_chi2)
-    vertex_code = require_all("in_range({am_min_vtx}, M, {am_max_vtx})",
-                              "VFASPF(VCHI2PDOF) < {vchi2pdof}",
-                              "PT > {pt}").format(
-                                  am_min_vtx=am_min_vtx,
-                                  am_max_vtx=am_max_vtx,
-                                  vchi2pdof=vchi2pdof,
-                                  pt=pt)
-
-    return ParticleCombinerWithPVs(
-        particles=[kaons],
-        pvs=make_pvs(),
-        DecayDescriptors=descriptors,
-        CombinationCut=combination_code,
-        MotherCut=vertex_code)
+    phi2kk = make_twobody(
+        particles=[kaons, kaons],
+        descriptor=descriptor_rs,
+        name=name + "_rightsign",
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_m_min,
+        vtx_m_max=vtx_m_max,
+        pt=pt,
+        max_docachi2=max_docachi2,
+        max_vchi2pdof=max_vchi2pdof)
+    phi2kk_ws = make_twobody(
+        particles=[kaons, kaons],
+        descriptor=descriptor_ws,
+        name=name + "_wrongsize",
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_m_min,
+        vtx_m_max=vtx_m_max,
+        pt=pt,
+        max_docachi2=max_docachi2,
+        max_vchi2pdof=max_vchi2pdof)
+
+    return ParticleContainersMerger([phi2kk, phi2kk_ws], name=name + "_Merge")
+
+
+def make_selected_ks(input_ks, name="B2CC_Ks_Filter", chi2vx=30, bpvvdchi2=9.):
+    '''
+    Filters Kshort candidates for B2CC. Default cuts correspond to VeryLooseKSLL refered to
+    B2OC group
+    '''
+    code = require_all(F.CHI2 < chi2vx)
+    if bpvvdchi2 is not None:
+        code = code & (F.BPVFDCHI2(make_pvs()) > bpvvdchi2)
+    return ParticleFilter(input_ks, F.FILTER(code))
+
+
+def make_ks_LL(make_ks=make_KsLL,
+               pi_pmin=2 * GeV,
+               pi_mipchi2pv=9.,
+               chi2vx=30,
+               bpvvdchi2=5.):
+    '''
+    Builds LL Kshorts, currently corresponding to the Run2
+    StdVeryLooseKSLL.
+    '''
+    return make_selected_ks(
+        input_ks=make_ks(
+            make_selected_particles(
+                make_particles=make_long_pions_for_V0,
+                tr_chi2pdof_max=
+                10,  ##TODO to be tightened once the variable is more reliable
+                pt_min=0 * MeV,
+                p_min=pi_pmin,
+                mipchi2_min=pi_mipchi2pv)),
+        name="B2CC_KsLL_Filter",
+        chi2vx=chi2vx,
+        bpvvdchi2=bpvvdchi2)
+
+
+def make_ks_DD(make_ks=make_KsDD, pi_pmin=2 * GeV, chi2vx=30, bpvvdchi2=5.):
+    '''
+    Builds DD Kshorts, currently corresponding to the Run2
+    StdVeryLooseKSDD.
+    '''
+    return make_selected_ks(
+        input_ks=make_ks(
+            make_selected_particles(
+                make_particles=make_down_pions_for_V0,
+                tr_chi2pdof_max=
+                10,  ##TODO to be tightened once the variable is more reliable
+                pt_min=0 * MeV,
+                p_min=pi_pmin,
+                mipchi2_min=None)),
+        name="B2CC_KsDD_Filter",
+        chi2vx=chi2vx,
+        bpvvdchi2=bpvvdchi2)
+
+
+def make_ks_LD(make_ks=make_KsLD,
+               pi_pmin=2 * GeV,
+               pi_mipchi2pv=4.,
+               chi2vx=30,
+               bpvvdchi2=5.):
+    '''
+    Builds LD Kshorts, currently corresponding to the Run2
+    StdLooseKSDD.
+    '''
+    return make_selected_ks(
+        input_ks=make_ks(
+            pions_down=make_selected_particles(
+                make_particles=make_down_pions_for_V0,
+                tr_chi2pdof_max=
+                10,  ##TODO to be tightened once the variable is more reliable
+                pt_min=0 * MeV,
+                p_min=pi_pmin,
+                mipchi2_min=None),
+            pions_long=make_selected_particles(
+                make_particles=make_long_pions_for_V0,
+                tr_chi2pdof_max=
+                10,  ##TODO to be tightened once the variable is more reliable
+                pt_min=0 * MeV,
+                p_min=pi_pmin,
+                mipchi2_min=pi_mipchi2pv)),
+        name="B2CC_KsLD_Filter",
+        chi2vx=chi2vx,
+        bpvvdchi2=bpvvdchi2)
+
+
+def make_ks_UL(make_ks=make_KsUL,
+               pi_pmin=2 * GeV,
+               pi_u_pmin=1 * GeV,
+               pi_mipchi2pv=4.,
+               chi2vx=30,
+               bpvvdchi2=5.):
+    '''
+    Builds UL Kshorts, currently corresponding to the Run2
+    StdLooseKSDD but with loose pion momentum requirement.
+    '''
+    return make_selected_ks(
+        input_ks=make_ks(
+            pions_long=make_selected_particles(
+                make_particles=make_long_pions_for_V0,
+                tr_chi2pdof_max=
+                10,  ##TODO to be tightened once the variable is more reliable
+                pt_min=0 * MeV,
+                p_min=pi_pmin,
+                mipchi2_min=pi_mipchi2pv),
+            pions_up=make_selected_particles(
+                make_particles=make_up_pions_for_V0,
+                tr_chi2pdof_max=
+                10,  ##TODO to be tightened once the variable is more reliable
+                pt_min=0 * MeV,
+                p_min=pi_u_pmin,
+                mipchi2_min=pi_mipchi2pv)),
+        name="B2CC_KsUL_Filter",
+        chi2vx=chi2vx,
+        bpvvdchi2=bpvvdchi2)
+
+
+def make_selected_jpsi2mumu(
+        name="B2CC_Jpsi2MuMu_Filter",
+        descriptor='J/psi(1S) -> mu+ mu-',
+        comb_m_min=2700. * MeV,
+        comb_m_max=3400. * MeV,
+        vtx_m_min=2950. * MeV,
+        vtx_m_max=3250. * MeV,
+        max_vchi2pdof=16.,
+        pt=500. * MeV,
+        max_docachi2=20.,
+        tr_chi2pdof=15.,  ##TODO to be tightened once the variable is more reliable
+        pt_mu=500. * MeV,
+        p_mu=0 * MeV,
+        pid_mu=-5,
+        mipchi2_mu=0):
+    """
+    Filter jpsi(mumu) candiates for B2CC.  Default cuts refered to Bs2JpsiPhi.
+    """
+    muons = make_muons(
+        pid=pid_mu,
+        tr_chi2pdof_max=tr_chi2pdof,
+        pt=pt_mu,
+        p=p_mu,
+        mipchi2_min=mipchi2_mu)
+
+    return make_twobody(
+        particles=[muons, muons],
+        descriptor=descriptor,
+        name=name,
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_m_min,
+        vtx_m_max=vtx_m_max,
+        pt=pt,
+        max_docachi2=max_docachi2,
+        max_vchi2pdof=max_vchi2pdof)
 
 
-@configurable
-def make_selected_jpsi2ee(make_pvs=make_pvs,
-                          am_min=2200 * MeV,
-                          am_max=3400 * MeV,
-                          am_min_vtx=2200 * MeV,
-                          am_max_vtx=3400 * MeV,
-                          vchi2pdof=4,
+def make_selected_jpsi_bd2jpsimumukshort(muons,
+                                         admass=100 * MeV,
+                                         admass_vtx=100 * MeV,
+                                         max_vchi2pdof=20,
+                                         psi2S=False):
+    """
+    Filter jpsi candiates for B2CC.  Default cuts refered to Bd2JpsimumuKshort.
+    """
+    if psi2S:
+        pname = 'psi(2S)'
+        reference_mass = 3686.1 * MeV
+    else:
+        pname = 'J/psi(1S)'
+        reference_mass = 3096.9 * MeV
+
+    descriptors = "{pname} -> mu- mu+".format(pname=pname)
+
+    combination_code = require_all(
+        in_range(reference_mass - admass, F.MASS, reference_mass + admass))
+    vertex_code = require_all(
+        in_range(reference_mass - admass_vtx, F.MASS,
+                 reference_mass + admass_vtx), F.CHI2DOF < max_vchi2pdof)
+
+    return ParticleCombiner([muons, muons],
+                            DecayDescriptor=descriptors,
+                            CombinationCut=combination_code,
+                            CompositeCut=vertex_code)
+
+
+def filter_muons_loose(particles,
+                       pt_min=500 * MeV,
+                       pidmu=0,
+                       mu_pidk=None,
+                       mu_pidp=None):
+    """Returns loosely preselected muons """
+    code = require_all(F.PID_MU > pidmu,
+                       F.PT > pt_min)  #, F.MAXDOCACUT(docachi2_max_mu))
+    if mu_pidk is not None:
+        code = code & (F.PID_K < mu_pidk)
+    if mu_pidp is not None:
+        code = code & (F.PID_P < mu_pidp)
+    return ParticleFilter(particles, F.FILTER(code))
+
+
+def make_selected_jpsi2ee(name="B2CC_Jpsi2EE_Filter",
+                          descriptor='J/psi(1S) -> e- e+',
+                          comb_m_min=2250. * MeV,
+                          comb_m_max=3400. * MeV,
+                          vtx_m_min=2300. * MeV,
+                          vtx_m_max=3300. * MeV,
+                          max_vchi2pdof=15.,
                           pt=1000. * MeV,
-                          adoca_chi2=30,
-                          tr_chi2pdof=2.,
+                          electron_particles=make_long_electrons_no_brem,
+                          max_docachi2=30.,
+                          tr_chi2pdof=10.,
                           pt_e=500 * MeV,
-                          pid_e=0.5,
-                          mipchi2_e=0):
+                          pid_e=1,
+                          mipchi2_e=None):
     """
     Filter jpsi(ee) candiates for B2CC.  Default cuts refered to Bs2JpsieePhi.
     """
     electrons = make_electrons(
-        pid=pid_e, tr_chi2pdof_max=tr_chi2pdof, pt=pt_e, mipchi2_min=mipchi2_e)
-
-    descriptors = ['J/psi(1S) -> e- e+', '[J/psi(1S) -> e+ e+]cc']
-
-    combination_code = require_all("in_range({am_min}, AM, {am_max})",
-                                   "ADOCACHI2CUT({adoca_chi2}, '')").format(
-                                       am_min=am_min,
-                                       am_max=am_max,
-                                       adoca_chi2=adoca_chi2)
-    vertex_code = require_all("in_range({am_min_vtx}, M, {am_max_vtx})",
-                              "VFASPF(VCHI2PDOF) < {vchi2pdof}",
-                              "PT > {pt}").format(
-                                  am_min_vtx=am_min_vtx,
-                                  am_max_vtx=am_max_vtx,
-                                  vchi2pdof=vchi2pdof,
-                                  pt=pt)
-
-    return ParticleCombinerWithPVs(
-        particles=[electrons],
-        pvs=make_pvs(),
-        DecayDescriptors=descriptors,
-        CombinationCut=combination_code,
-        MotherCut=vertex_code)
-
-
-@configurable
-def make_selected_jpsi2ee_detached(am_min=2200 * MeV,
-                                   am_max=3400 * MeV,
-                                   am_min_vtx=2200 * MeV,
-                                   am_max_vtx=3400 * MeV,
-                                   vchi2pdof=4,
-                                   pt=1000. * MeV,
-                                   adoca_chi2=30,
-                                   tr_chi2pdof=1.5,
-                                   pt_e=500 * MeV,
-                                   pid_e=1,
-                                   mipchi2_e=0):
-    """
-    Filter jpsi(ee) candiates for B2CC, Bd2JpsieeKstar Detached.
-    """
-    return make_selected_jpsi2ee(
-        am_min=am_min,
-        am_max=am_max,
-        am_min_vtx=am_min_vtx,
-        vchi2pdof=vchi2pdof,
+        particles=electron_particles,
+        pid=pid_e,
+        tr_chi2pdof_max=tr_chi2pdof,
+        pt=pt_e,
+        mipchi2_min=mipchi2_e)
+
+    return make_twobody(
+        particles=[electrons, electrons],
+        descriptor=descriptor,
+        name=name,
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_m_min,
+        vtx_m_max=vtx_m_max,
         pt=pt,
-        adoca_chi2=adoca_chi2,
-        tr_chi2pdof=tr_chi2pdof,
-        pt_e=pt_e,
-        pid_e=pid_e,
-        mipchi2_e=mipchi2_e)
-
-
-@configurable
-def make_selected_jpsi_bd2jpsieekstar(am_min=2250 * MeV,
-                                      am_max=3400 * MeV,
-                                      am_min_vtx=2250 * MeV,
-                                      am_max_vtx=3400 * MeV,
-                                      vchi2pdof=4,
-                                      pt=1000. * MeV,
-                                      adoca_chi2=30,
-                                      tr_chi2pdof=1.5,
-                                      pt_e=500 * MeV,
-                                      pid_e=1,
-                                      mipchi2_e=0):
-    """
-    Filter jpsi(ee) candiates for B2CC, Bd2JpsieeKstar.
-    """
-    return make_selected_jpsi2ee(
-        am_min=am_min,
-        am_max=am_max,
-        am_min_vtx=am_min_vtx,
-        vchi2pdof=vchi2pdof,
+        max_docachi2=max_docachi2,
+        max_vchi2pdof=max_vchi2pdof)
+
+
+def make_selected_jpsi2ee_wrongsign(
+        name="B2CC_Jpsi2EE_WrongSign",
+        descriptor='[J/psi(1S) -> e- e-]cc',
+        comb_m_min=2250. * MeV,
+        comb_m_max=3400. * MeV,
+        vtx_m_min=2300. * MeV,
+        vtx_m_max=3300. * MeV,
+        max_vchi2pdof=15.,
+        pt=1000. * MeV,
+        electron_particles=make_long_electrons_no_brem,
+        max_docachi2=30.,
+        tr_chi2pdof=10.,
+        pt_e=500 * MeV,
+        pid_e=1,
+        mipchi2_e=None):
+    """
+    Filter jpsi(ee) wrong sign candiates for background study in B2CC.  Default cuts refered to Bs2JpsieePhi.
+    """
+    electrons = make_electrons(
+        particles=electron_particles,
+        pid=pid_e,
+        tr_chi2pdof_max=tr_chi2pdof,
+        pt=pt_e,
+        mipchi2_min=mipchi2_e)
+
+    return make_twobody(
+        particles=[electrons, electrons],
+        descriptor=descriptor,
+        name=name,
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_m_min,
+        vtx_m_max=vtx_m_max,
         pt=pt,
-        adoca_chi2=adoca_chi2,
-        tr_chi2pdof=tr_chi2pdof,
-        pt_e=pt_e,
-        pid_e=pid_e,
-        mipchi2_e=mipchi2_e)
-
-
-@configurable
-def make_selected_jpsi_bd2jpsieekstar_detached(am_min=2400 * MeV,
-                                               am_max=3400 * MeV,
-                                               am_min_vtx=2400 * MeV,
-                                               am_max_vtx=3400 * MeV,
-                                               vchi2pdof=4,
-                                               pt=1000. * MeV,
-                                               adoca_chi2=30,
-                                               tr_chi2pdof=1.5,
-                                               pt_e=500 * MeV,
-                                               pid_e=1,
-                                               mipchi2_e=0):
-    """
-    Filter jpsi(ee) candiates for B2CC, Bd2JpsieeKstar Detached.
-    """
-    return make_selected_jpsi2ee(
-        am_min=am_min,
-        am_max=am_max,
-        am_min_vtx=am_min_vtx,
-        vchi2pdof=vchi2pdof,
+        max_docachi2=max_docachi2,
+        max_vchi2pdof=max_vchi2pdof)
+
+
+def make_selected_kstar2kpi(
+        name="B2CC_Kstar2KPi_Filter",
+        descriptor='[K*(892)0 -> K+ pi-]cc',
+        comb_m_min=826. * MeV,
+        comb_m_max=966. * MeV,
+        vtx_m_min=842. * MeV,
+        vtx_m_max=926. * MeV,
+        max_vchi2pdof=20,
+        pt=1500. * MeV,
+        max_docachi2=30.,
+        pid_k=1,
+        tr_chi2pdof_k=10,  ##TODO to be tightened once the variable is more reliable
+        pt_k=400. * MeV,
+        p_k=4. * GeV,
+        pid_pi=3,
+        tr_chi2pdof_pi=10,  ##TODO to be tightened once the variable is more reliable
+        pt_pi=300. * MeV,
+        p_pi=3. * GeV):
+    """ 
+    Filter kstar->kpi candiates for B2CC.  Default cuts refered to Bs2JpsieeKstar.
+    """
+
+    kaons = make_kaons(
+        pid=pid_k, tr_chi2pdof_max=tr_chi2pdof_k, pt=pt_k, p=p_k)
+    pions = make_pions(
+        pid=pid_pi, tr_chi2pdof_max=tr_chi2pdof_pi, pt=pt_pi, p=p_pi)
+
+    return make_twobody(
+        particles=[kaons, pions],
+        descriptor=descriptor,
+        name=name,
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_m_min,
+        vtx_m_max=vtx_m_max,
         pt=pt,
-        adoca_chi2=adoca_chi2,
-        tr_chi2pdof=tr_chi2pdof,
-        pt_e=pt_e,
-        pid_e=pid_e,
-        mipchi2_e=mipchi2_e)
-
-
-@configurable
-def make_selected_kstar2kpi(make_pvs=make_pvs,
-                            am_min=792 * MeV,
-                            am_max=992 * MeV,
-                            am_min_vtx=792 * MeV,
-                            am_max_vtx=992 * MeV,
-                            vchi2pdof=4,
-                            pt=1000. * MeV,
-                            adoca_chi2=30,
-                            pid_k=1,
-                            tr_chi2pdof_k=1.5,
-                            pt_k=400. * MeV,
-                            p_k=4. * GeV,
-                            pid_pi=3,
-                            tr_chi2pdof_pi=1.5,
-                            pt_pi=300. * MeV,
-                            p_pi=3. * GeV):
+        max_docachi2=max_docachi2,
+        max_vchi2pdof=max_vchi2pdof)
+
+
+def make_selected_kstar2kpi_wrongsign(
+        name="B2CC_Kstar2KPi_WrongSign",
+        descriptor='[K*(892)0 -> K- pi-]cc',
+        comb_m_min=826. * MeV,
+        comb_m_max=966. * MeV,
+        vtx_m_min=842. * MeV,
+        vtx_m_max=926. * MeV,
+        max_vchi2pdof=20,
+        pt=1500. * MeV,
+        max_docachi2=30.,
+        pid_k=1,
+        tr_chi2pdof_k=10,  ##TODO to be tightened once the variable is more reliable
+        pt_k=400. * MeV,
+        p_k=4. * GeV,
+        pid_pi=3,
+        tr_chi2pdof_pi=10,  ##TODO to be tightened once the variable is more reliable
+        pt_pi=300. * MeV,
+        p_pi=3. * GeV):
     """
-    Filter kstar->kpi candiates for B2CC.  Default cuts refered to Bs2JpsieeKstar.
+    Filter kstar->kpi candiates wrong size for B2CC.  Default cuts refered to Bs2JpsieeKstar.
     """
+
     kaons = make_kaons(
         pid=pid_k, tr_chi2pdof_max=tr_chi2pdof_k, pt=pt_k, p=p_k)
     pions = make_pions(
         pid=pid_pi, tr_chi2pdof_max=tr_chi2pdof_pi, pt=pt_pi, p=p_pi)
 
-    descriptors = ['[K*(892)0 -> pi- K+]cc', '[K*(892)0 -> pi+ K+]cc']
-
-    combination_code = require_all("in_range({am_min}, AM, {am_max})",
-                                   "ADOCACHI2CUT({adoca_chi2}, '')").format(
-                                       am_min=am_min,
-                                       am_max=am_max,
-                                       adoca_chi2=adoca_chi2)
-    vertex_code = require_all("in_range({am_min_vtx}, M, {am_max_vtx})",
-                              "VFASPF(VCHI2PDOF) < {vchi2pdof}",
-                              "PT > {pt}").format(
-                                  am_min_vtx=am_min_vtx,
-                                  am_max_vtx=am_max_vtx,
-                                  vchi2pdof=vchi2pdof,
-                                  pt=pt)
-
-    return ParticleCombinerWithPVs(
-        particles=[pions, kaons],
-        pvs=make_pvs(),
-        DecayDescriptors=descriptors,
-        CombinationCut=combination_code,
-        MotherCut=vertex_code)
-
-
-@configurable
-def make_selected_kstar_bd2jpsieekstar_detached(am_min=842 * MeV,
-                                                am_max=942 * MeV,
-                                                am_min_vtx=842 * MeV,
-                                                am_max_vtx=942 * MeV,
-                                                vchi2pdof=4,
-                                                pt=1000. * MeV,
-                                                adoca_chi2=30,
-                                                pid_pi=3,
-                                                tr_chi2pdof_pi=1.5,
-                                                pt_pi=300. * MeV,
-                                                p_pi=3. * GeV,
-                                                pid_k=1,
-                                                tr_chi2pdof_k=1.5,
-                                                pt_k=400. * MeV,
-                                                p_k=4. * GeV):
-    """
-    Filter kstar->kpi candiates for B2CC.  Default cuts refered to Bd2JpsieeKstar detached.
-    """
-    return make_selected_kstar2kpi(
-        am_min=am_min,
-        am_max=am_max,
-        am_min_vtx=am_min_vtx,
-        am_max_vtx=am_max_vtx,
-        vchi2pdof=vchi2pdof,
+    return make_twobody(
+        particles=[kaons, pions],
+        descriptor=descriptor,
+        name=name,
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_m_min,
+        vtx_m_max=vtx_m_max,
+        pt=pt,
+        max_docachi2=max_docachi2,
+        max_vchi2pdof=max_vchi2pdof)
+
+
+def make_selected_kstar2kpi_widerange(
+        name="B2CC_Kstar2KPi_WideRange_Filter",
+        descriptor='[K*(892)0 -> K+ pi-]cc',
+        comb_m_min=692. * MeV,
+        comb_m_max=1900. * MeV,
+        vtx_m_min=692. * MeV,
+        vtx_m_max=1900. * MeV,
+        pt=0. * MeV,
+        pt_sum=1000. * MeV,
+        max_docachi2=30.,
+        max_vchi2pdof=25.,
+        pid_pi=10.,
+        tr_chi2pdof_max_pi=10.,  ##TODO: to be tightened once the variable become more reliable
+        pt_pi=250. * MeV,
+        mipchi2_min_pi=0.,
+        pid_k=0.,
+        tr_chi2pdof_max_k=10.,  ##TODO: to be tightened once the variable become more reliable
+        pt_k=250. * MeV,
+        mipchi2_min_k=0.):
+    """
+    Filter kstar->kpi candiates for B2CC.  Default cuts refered to Bs2JpsiKstar.
+    """
+    pions = make_pions(
+        pid=pid_pi,
+        tr_chi2pdof_max=tr_chi2pdof_max_pi,
+        pt=pt_pi,
+        mipchi2_min=mipchi2_min_pi)
+    kaons = make_kaons(
+        pid=pid_k,
+        tr_chi2pdof_max=tr_chi2pdof_max_k,
+        pt=pt_k,
+        mipchi2_min=mipchi2_min_k)
+    return make_twobody(
+        particles=[kaons, pions],
+        descriptor=descriptor,
+        name=name,
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_m_min,
+        vtx_m_max=vtx_m_max,
+        pt=pt,
+        pt_sum=pt_sum,
+        max_docachi2=max_docachi2,
+        max_vchi2pdof=max_vchi2pdof)
+
+
+def make_selected_f0(
+        name="B2CC_f0_Filter",
+        descriptor='f_0(980) -> pi+ pi-',
+        comb_m_min=278. * MeV,
+        comb_m_max=2700. * MeV,
+        vtx_m_min=278. * MeV,
+        vtx_m_max=2700. * MeV,
+        pt=0. * MeV,
+        pt_sum=1000. * MeV,
+        maxmax_docachi2=20.,
+        max_vchi2pdof=16.,
+        pid_pi=10.,
+        tr_chi2pdof_max_pi=10.,  ##TODO: to be tightened once the variable become more reliable
+        mipchi2_min_pi=4.,
+        pt_pi=250 * MeV):
+    """
+    Filter f0->pi pi candiates for B2CC. Default cuts refered to Bs2Jpsif0.
+    """
+    pions = make_pions(
+        pid=pid_pi,
+        tr_chi2pdof_max=tr_chi2pdof_max_pi,
+        pt=pt_pi,
+        mipchi2_min=mipchi2_min_pi)
+    return make_twobody(
+        particles=[pions, pions],
+        descriptor=descriptor,
+        name=name,
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_m_min,
+        vtx_m_max=vtx_m_max,
+        pt=pt,
+        pt_sum=pt_sum,
+        max_docachi2=maxmax_docachi2,
+        max_vchi2pdof=max_vchi2pdof)
+
+
+def make_selected_f0kaon(
+        name="B2CC_f0Kaon_Filter",
+        descriptor='f_0(980) -> K+ K-',
+        comb_m_min=986. * MeV,
+        comb_m_max=2700. * MeV,
+        vtx_m_min=986. * MeV,
+        vtx_m_max=2700. * MeV,
+        pt=0. * MeV,
+        pt_sum=1000. * MeV,
+        max_docachi2=20.,
+        max_vchi2pdof=16.,
+        pid_k=0.,
+        tr_chi2pdof_max_k=10.,  ##TODO: to be tightened once the variable become more reliable
+        mipchi2_min_k=4.,
+        pt_k=250. * MeV):
+    """
+    Filter f0->K+ K- candiates for B2CC. Default cuts refered to Bs2Jpsif0Kaon.
+    """
+    kaons = make_kaons(
+        pid=pid_k,
+        tr_chi2pdof_max=tr_chi2pdof_max_k,
+        pt=pt_k,
+        mipchi2_min=mipchi2_min_k)
+    return make_twobody(
+        particles=[kaons, kaons],
+        descriptor=descriptor,
+        name=name,
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_m_min,
+        vtx_m_max=vtx_m_max,
+        pt=pt,
+        pt_sum=pt_sum,
+        max_docachi2=max_docachi2,
+        max_vchi2pdof=max_vchi2pdof)
+
+
+def make_selected_f0ws(
+        name="B2CC_f0ws_Filter",
+        descriptor='[f_0(980) -> pi- pi-]cc',
+        comb_m_min=278. * MeV,
+        comb_m_max=2700. * MeV,
+        vtx_m_min=278. * MeV,
+        vtx_m_max=2700. * MeV,
+        pt=0. * MeV,
+        pt_sum=1000. * MeV,
+        max_docachi2=20.,
+        max_vchi2pdof=16.,
+        pid_pi=10.,
+        tr_chi2pdof_max_pi=10.,  ##TODO: to be tightened once the variable become more reliable
+        mipchi2_min_pi=4.,
+        pt_pi=250. * MeV):
+    """
+    Filter f0->pi+ pi- wrong sign candiates for B2CC. Default cuts refered to Bs2Jpsif0ws.
+    """
+    pions = make_pions(
+        pid=pid_pi,
+        tr_chi2pdof_max=tr_chi2pdof_max_pi,
+        pt=pt_pi,
+        mipchi2_min=mipchi2_min_pi)
+    return make_twobody(
+        particles=[pions, pions],
+        descriptor=descriptor,
+        name=name,
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_m_min,
+        vtx_m_max=vtx_m_max,
+        pt=pt,
+        pt_sum=pt_sum,
+        max_docachi2=max_docachi2,
+        max_vchi2pdof=max_vchi2pdof)
+
+
+def make_selected_f0Unbiased(name='B2CC_f0unbiased_Filter',
+                             name_pions='B2CC_f0unbiased_Filter_Pions',
+                             name_kaons='B2CC_f0unbiased_Filter_Kaons',
+                             descriptor_pions='f_0(980) -> pi+ pi-',
+                             descriptor_kaons='f_0(980) -> K+ K-',
+                             mipchi2_min_pi=0.,
+                             mipchi2_min_k=0.):
+    """
+    Filter f0->pi+ pi- , f0->K+ K- unbiased candiates for B2CC. Default cuts refered to Bs2Jpsif0Unbiased.
+    """
+    f0_to_pipi = make_selected_f0(
+        name=name_pions,
+        descriptor=descriptor_pions,
+        mipchi2_min_pi=mipchi2_min_pi)
+    f0_to_kk = make_selected_f0kaon(
+        name=name_kaons,
+        descriptor=descriptor_kaons,
+        mipchi2_min_k=mipchi2_min_k)
+    return ParticleContainersMerger([f0_to_pipi, f0_to_kk], name=name)
+
+
+def make_selected_lambda0_pk(
+        name="B2CC_Lambda0_pK_Filter",
+        descriptor='[Lambda(1520)0 -> p+ K-]cc',
+        comb_m_min=1430. * MeV,
+        comb_m_max=3100. * MeV,
+        vtx_m_min=1430. * MeV,
+        vtx_m_max=3100. * MeV,
+        pt=0. * MeV,
+        pt_sum=1000. * MeV,
+        max_docachi2=20.,
+        max_vchi2pdof=16.,
+        pid_k=0.,
+        tr_chi2pdof_max_k=10.,  ##TODO: to be tightened once the variable become more reliable
+        pt_k=250. * MeV,
+        mipchi2_min_k=4.):
+    """
+    Filter lambda0 -> p K candiates for B2CC.  Default cuts refered to Lb2JpsipH.
+    """
+    protons = make_protons()
+    kaons = make_kaons(
+        pid=pid_k,
+        tr_chi2pdof_max=tr_chi2pdof_max_k,
+        pt=pt_k,
+        mipchi2_min=mipchi2_min_k)
+    return make_twobody(
+        particles=[protons, kaons],
+        descriptor=descriptor,
+        name=name,
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_m_min,
+        vtx_m_max=vtx_m_max,
         pt=pt,
-        adoca_chi2=adoca_chi2,
-        pid_pi=pid_pi,
-        tr_chi2pdof_pi=tr_chi2pdof_pi,
-        pt_pi=pt_pi,
-        p_pi=p_pi,
-        pid_k=pid_k,
-        tr_chi2pdof_k=tr_chi2pdof_k,
-        pt_k=pt_k,
-        p_k=p_k)
+        pt_sum=pt_sum,
+        max_docachi2=max_docachi2,
+        max_vchi2pdof=max_vchi2pdof)
+
+
+def make_selected_lambda0_pkws(
+        name="B2CC_Lambda0_pKws_Filter",
+        descriptor='[Lambda(1520)0 -> p+ K+]cc',
+        comb_m_min=1430. * MeV,
+        comb_m_max=3100. * MeV,
+        vtx_m_min=1430. * MeV,
+        vtx_m_max=3100. * MeV,
+        pt=0. * MeV,
+        pt_sum=1000. * MeV,
+        max_docachi2=20.,
+        max_vchi2pdof=16.,
+        pid_k=0.,
+        tr_chi2pdof_max_k=10,  ##TODO: to be tightened once the variable become more reliable
+        pt_k=250. * MeV,
+        mipchi2_min_k=4.):
+    """
+    Filter lambda0 -> p K wrong sign candiates for B2CC.  Default cuts refered to Lb2JpsipH.
+    """
+    protons = make_protons()
+    kaons = make_kaons(
+        pid=pid_k,
+        tr_chi2pdof_max=tr_chi2pdof_max_k,
+        pt=pt_k,
+        mipchi2_min=mipchi2_min_k)
+    return make_twobody(
+        particles=[protons, kaons],
+        descriptor=descriptor,
+        name=name,
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_m_min,
+        vtx_m_max=vtx_m_max,
+        pt=pt,
+        pt_sum=pt_sum,
+        max_docachi2=max_docachi2,
+        max_vchi2pdof=max_vchi2pdof)
+
+
+def make_selected_lambda0_ppi(name="B2CC_Lambda0_pPi_Filter",
+                              descriptor='[Lambda(1520)0 -> p+ pi-]cc',
+                              comb_m_min=1077. * MeV,
+                              comb_m_max=3100. * MeV,
+                              vtx_m_min=1077. * MeV,
+                              vtx_m_max=3100. * MeV,
+                              pt=0. * MeV,
+                              pt_sum=1000. * MeV,
+                              max_docachi2=20.,
+                              max_vchi2pdof=16.,
+                              pid_pi=10.,
+                              tr_chi2pdof_max_pi=5.,
+                              pt_pi=250. * MeV,
+                              mipchi2_min_pi=4.):
+    """
+    Filter lambda0 -> p pi candiates for B2CC.  Default cuts refered to Lb2JpsipH.
+    """
+    protons = make_protons()
+    pions = make_pions(
+        pid=pid_pi,
+        tr_chi2pdof_max=tr_chi2pdof_max_pi,
+        pt=pt_pi,
+        mipchi2_min=mipchi2_min_pi)
+    return make_twobody(
+        particles=[protons, pions],
+        descriptor=descriptor,
+        name=name,
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_m_min,
+        vtx_m_max=vtx_m_max,
+        pt=pt,
+        pt_sum=pt_sum,
+        max_docachi2=max_docachi2,
+        max_vchi2pdof=max_vchi2pdof)
+
+
+def make_selected_lambda0_ppiws(name="B2CC_Lambda0_pPiws_Filter",
+                                descriptor='[Lambda(1520)0 -> p+ pi+]cc',
+                                comb_m_min=1077. * MeV,
+                                comb_m_max=3100. * MeV,
+                                vtx_m_min=1077. * MeV,
+                                vtx_m_max=3100. * MeV,
+                                pt=0. * MeV,
+                                pt_sum=1000. * MeV,
+                                max_docachi2=20.,
+                                max_vchi2pdof=16.,
+                                pid_pi=10.,
+                                tr_chi2pdof_max_pi=5.,
+                                pt_pi=250. * MeV,
+                                mipchi2_min_pi=4.):
+    """
+    Filter lambda0 -> p pi wrong sign candiates for B2CC.  Default cuts refered to Lb2JpsipH.
+    """
+    protons = make_protons()
+    pions = make_pions(
+        pid=pid_pi,
+        tr_chi2pdof_max=tr_chi2pdof_max_pi,
+        pt=pt_pi,
+        mipchi2_min=mipchi2_min_pi)
+    return make_twobody(
+        particles=[protons, pions],
+        descriptor=descriptor,
+        name=name,
+        comb_m_min=comb_m_min,
+        comb_m_max=comb_m_max,
+        vtx_m_min=vtx_m_min,
+        vtx_m_max=vtx_m_max,
+        pt=pt,
+        pt_sum=pt_sum,
+        max_docachi2=max_docachi2,
+        max_vchi2pdof=max_vchi2pdof)
+
+
+def make_selected_lambda0(name='B2CC_Lambda0_Filter'):
+    """
+    Filter lambda0 -> p K, lambda0 -> p Pi candiates for B2CC.  Default cuts refered to Lb2JpsipH.
+    """
+    lambda_to_pk = make_selected_lambda0_pk()
+    lambda_to_pkws = make_selected_lambda0_pkws()
+    lambda_to_ppi = make_selected_lambda0_ppi()
+    lambda_to_ppiws = make_selected_lambda0_ppiws()
+    return ParticleContainersMerger(
+        [lambda_to_pk, lambda_to_pkws, lambda_to_ppi, lambda_to_ppiws],
+        name=name)
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/builders/special_builder.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/builders/special_builder.py
new file mode 100644
index 0000000000000000000000000000000000000000..234c7524e0b4303a143898ca0b806543deb9c2ff
--- /dev/null
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/builders/special_builder.py
@@ -0,0 +1,37 @@
+###############################################################################
+# (c) Copyright 2019-2021 CERN for the benefit of the LHCb Collaboration      #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+"""
+Definition of special descriptor for non-default Bs meson decays 
+that can be shared in the B2CC selections, and therefore are defined centrally.
+"""
+from Hlt2Conf.algorithms_thor import ParticleCombiner
+from PyConf import configurable
+from RecoConf.reconstruction_objects import make_pvs_v2
+import Functors as F
+
+
+@configurable
+def make_X2BsLep(particles,
+                 descriptor,
+                 name='B2CC_X2Bsmu_Combiner',
+                 pvs=make_pvs_v2):
+    """
+    A X->BLep decay maker, where X
+    is a dummy particle
+    """
+    combination_code = F.ALL
+    vertex_code = F.ALL
+    return ParticleCombiner(
+        name=name,
+        Inputs=particles,
+        DecayDescriptor=descriptor,
+        CombinationCut=combination_code,
+        CompositeCut=vertex_code)
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/hlt2_b2cc.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/hlt2_b2cc.py
index e3424264da02b22fed8b3e05cd306fd6ff6fc671..60e00b0aad5a0a6a9a5bc468c2084c49bf0c6f15 100644
--- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/hlt2_b2cc.py
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/hlt2_b2cc.py
@@ -14,85 +14,534 @@ from __future__ import absolute_import, division, print_function
 
 from Moore.config import HltLine, register_line_builder
 
-from PyConf import configurable
-from Hlt2Conf.standard_particles import make_mass_constrained_jpsi2mumu
+from Hlt2Conf.standard_particles import make_has_rich_long_pions, make_has_rich_up_pions
 from Hlt2Conf.lines.b_to_charmonia.prefilters import b2cc_prefilters
-from Hlt2Conf.lines.b_to_charmonia.builders import b_builder
-from Hlt2Conf.lines.b_to_charmonia.builders import basic_builder
 from Hlt2Conf.lines.b_to_charmonia import b_to_jpsix
+from RecoConf.reconstruction_objects import make_pvs
+from PyConf.Algorithms import GetFlavourTaggingParticles
 
 PROCESS = 'hlt2'
-hlt2_lines = {}
+all_lines = {}
 
 
-@register_line_builder(hlt2_lines)
-@configurable
+def extra_outputs_for_FlavourTagging(BCandidates):
+
+    pvs = make_pvs()  #version 1 pv
+
+    longTaggingParticles = GetFlavourTaggingParticles(
+        BCandidates=BCandidates,
+        TaggingParticles=make_has_rich_long_pions(),
+        PrimaryVertices=pvs)
+    #TODO: check if upstream track are properly fitted, No fitted upstream in fastest_reco
+    upstreamTaggingParticles = GetFlavourTaggingParticles(
+        BCandidates=BCandidates,
+        TaggingParticles=make_has_rich_up_pions(),
+        PrimaryVertices=pvs)
+    extra_outputs = [('LongTaggingParticles', longTaggingParticles),
+                     ('UpstreamTaggingParticles', upstreamTaggingParticles)]
+
+    return extra_outputs
+
+
+@register_line_builder(all_lines)
 def BsToJpsiPhi_detachedline(name='Hlt2B2CC_BsToJpsiPhi_DetachedLine',
-                             prescale=1):
-    line_alg = b_to_jpsix.make_BsToJpsiPhi_detachedline(process=PROCESS)
+                             prescale=1,
+                             persistreco=False):
+    line_alg = b_to_jpsix.make_BsToJpsiPhi_detached_line(process=PROCESS)
     return HltLine(
-        name=name, prescale=prescale, algs=b2cc_prefilters() + [line_alg])
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
 
+@register_line_builder(all_lines)
+def BsToJpsiPhi_extramuonline(name='Hlt2B2CC_BsToJpsiPhi_ExtraMuonLine',
+                              prescale=1,
+                              persistreco=False):
+    line_alg = b_to_jpsix.make_BsToJpsiPhi_extramuonline(process=PROCESS)
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[4]),
+        persistreco=persistreco)
 
-@register_line_builder(hlt2_lines)
-@configurable
-def BsToJpsiPhi_line(name='Hlt2B2CC_BsToJpsiPhi_Line', prescale=0.1):
-    phi = basic_builder.make_selected_phi()
-    jpsi = make_mass_constrained_jpsi2mumu()
-    b2jpsiphi = b_builder.make_Bs2JpsiPhi(
-        particles=[jpsi, phi], descriptors=['B_s0 -> J/psi(1S) phi(1020)'])
 
+@register_line_builder(all_lines)
+def BsToJpsiPhi_line(name='Hlt2B2CC_BsToJpsiPhi_Line',
+                     prescale=0.1,
+                     persistreco=False):
+    line_alg = b_to_jpsix.make_BsToJpsiPhi_line(process=PROCESS)
     return HltLine(
-        name=name, prescale=prescale, algs=b2cc_prefilters() + [b2jpsiphi])
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        persistreco=persistreco)
 
 
-@register_line_builder(hlt2_lines)
-@configurable
+@register_line_builder(all_lines)
 def BsToJpsieePhi_detached_line(
-        name='Hlt2B2CC_BsToJpsiPhi_JpsiToEE_DetachedLine', prescale=1):
-    phi = basic_builder.make_selected_phi_bs2jpsieephi()
-    jpsi = basic_builder.make_selected_jpsi2ee_detached()
-    b2jpsiphi = b_builder.make_Bs2JpsieePhi_detached(
-        particles=[jpsi, phi], descriptors=['B_s0 -> J/psi(1S) phi(1020)'])
-
+        name='Hlt2B2CC_BsToJpsiPhi_JpsiToEE_DetachedLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BsToJpsieePhi_detached_line(process=PROCESS)
     return HltLine(
-        name=name, prescale=prescale, algs=b2cc_prefilters() + [b2jpsiphi])
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        persistreco=persistreco)
 
 
-@register_line_builder(hlt2_lines)
-@configurable
+@register_line_builder(all_lines)
 def BsToJpsieePhi_line(name='Hlt2B2CC_BsToJpsiPhi_JpsiToEE_Line',
-                       prescale=0.1):
-    phi = basic_builder.make_selected_phi_bs2jpsieephi()
-    jpsi = basic_builder.make_selected_jpsi2ee()
-    b2jpsiphi = b_builder.make_Bs2JpsieePhi(
-        particles=[jpsi, phi], descriptors=['B_s0 -> J/psi(1S) phi(1020)'])
+                       prescale=0.1,
+                       persistreco=False):
 
+    line_alg = b_to_jpsix.make_BsToJpsieePhi_line(process=PROCESS)
     return HltLine(
-        name=name, prescale=prescale, algs=b2cc_prefilters() + [b2jpsiphi])
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        persistreco=persistreco)
 
 
-@register_line_builder(hlt2_lines)
-@configurable
+@register_line_builder(all_lines)
 def BdToJpsieeKstar_detached_line(
-        name='Hlt2B2CC_BdToJpsiKstar_JpsiToEE_DetachedLine', prescale=1):
-    jpsi = basic_builder.make_selected_jpsi_bd2jpsieekstar_detached()
-    kstar = basic_builder.make_selected_kstar_bd2jpsieekstar_detached()
-    b2jpsikstar = b_builder.make_Bd2JpsieeKstar_detached(
-        particles=[jpsi, kstar], descriptors=['[B0 -> J/psi(1S) K*(892)0]cc'])
+        name='Hlt2B2CC_BdToJpsiKstar_JpsiToEE_DetachedLine',
+        prescale=1,
+        persistreco=True):
 
+    line_alg = b_to_jpsix.make_BdToJpsieeKstar_detached_line(process=PROCESS)
     return HltLine(
-        name=name, prescale=prescale, algs=b2cc_prefilters() + [b2jpsikstar])
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        persistreco=persistreco)
 
 
-@register_line_builder(hlt2_lines)
-@configurable
+@register_line_builder(all_lines)
 def BdToJpsieeKstar_line(name='Hlt2B2CC_BdToJpsiKstar_JpsiToEE_Line',
-                         prescale=0.05):
-    kstar = basic_builder.make_selected_kstar2kpi()
-    jpsi = basic_builder.make_selected_jpsi_bd2jpsieekstar()
-    b2jpsikstar = b_builder.make_Bd2JpsieeKstar(
-        particles=[jpsi, kstar], descriptors=['[B0 -> J/psi(1S) K*(892)0]cc'])
+                         prescale=0.05,
+                         persistreco=False):
+
+    line_alg = b_to_jpsix.make_BdToJpsieeKstar_line(process=PROCESS)
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BsToJpsif0_line(name='Hlt2B2CC_BsToJpsif0_Line',
+                    prescale=1,
+                    persistreco=False):
+
+    line_alg = b_to_jpsix.make_BsToJpsif0_line(process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        persistreco=persistreco,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]))
+
+
+@register_line_builder(all_lines)
+def BsToJpsif0kaon_line(name='Hlt2B2CC_BsToJpsif0Kaon_Line',
+                        prescale=1,
+                        persistreco=False):
+
+    line_alg = b_to_jpsix.make_BsToJpsif0kaon_line(process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        persistreco=persistreco,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]))
+
+
+@register_line_builder(all_lines)
+def BsToJpsif0ws_line(name='Hlt2B2CC_BsToJpsif0ws_Line',
+                      prescale=1,
+                      persistreco=False):
+
+    line_alg = b_to_jpsix.make_BsToJpsif0ws_line(process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        persistreco=persistreco,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]))
+
+
+@register_line_builder(all_lines)
+def BsToJpsif0Prescaled_line(name='Hlt2B2CC_BsToJpsif0Prescaled_Line',
+                             prescale=0.03,
+                             persistreco=False):
+
+    line_alg = b_to_jpsix.make_BsToJpsif0Prescaled_line(process=PROCESS)
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BsToJpsikstar_line(name='Hlt2B2CC_BsToJpsiKstar_Line',
+                       prescale=1,
+                       persistreco=False):
+
+    line_alg = b_to_jpsix.make_BsToJpsiKstar_line(process=PROCESS)
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        persistreco=persistreco,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]))
+
+
+@register_line_builder(all_lines)
+def LbToJpsipH_line(name='Hlt2B2CC_LbToJpsipH_Line',
+                    prescale=1,
+                    persistreco=False):
+
+    line_alg = b_to_jpsix.make_LbToJpsipH_line(process=PROCESS)
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BdToJpsieeKshort_LL_detached_line(
+        name='Hlt2B2CC_BdToJpsiKshort_JpsiToEE_LL_DetachedLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BdToJpsieeKshort_LL_detached_line(
+        process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BdToJpsieeKshort_DD_detached_line(
+        name='Hlt2B2CC_BdToJpsiKshort_JpsiToEE_DD_DetachedLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BdToJpsieeKshort_DD_detached_line(
+        process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BdToJpsieeKshort_LL_tight_line(
+        name='Hlt2B2CC_BdToJpsiKshort_JpsiToEE_LL_TightLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BdToJpsieeKshort_LL_tight_line(process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BdToJpsieeKshort_DD_tight_line(
+        name='Hlt2B2CC_BdToJpsiKshort_JpsiToEE_DD_TightLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BdToJpsieeKshort_DD_tight_line(process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BuToJpsieeKplus_detached_line(
+        name='Hlt2B2CC_BuToJpsiKplus_JpsiToEE_DetachedLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BuToJpsieeKplus_detached_line(process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BdToJpsimumuKshort_LL_tight_line(
+        name='Hlt2B2CC_BdToJpsiKshort_JpsiToMuMu_LL_TightLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BdToJpsimumuKshort_LL_tight_line(
+        process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BdToJpsimumuKshort_DD_tight_line(
+        name='Hlt2B2CC_BdToJpsiKshort_JpsiToMuMu_DD_TightLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BdToJpsimumuKshort_DD_tight_line(
+        process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BdToJpsimumuKshort_LD_tight_line(
+        name='Hlt2B2CC_BdToJpsiKshort_JpsiToMuMu_LD_TightLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BdToJpsimumuKshort_LD_tight_line(
+        process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BdToJpsimumuKshort_UL_tight_line(
+        name='Hlt2B2CC_BdToJpsiKshort_JpsiToMuMu_UL_TightLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BdToJpsimumuKshort_UL_tight_line(
+        process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BdToJpsimumuKshort_LL_detached_line(
+        name='Hlt2B2CC_BdToJpsiKshort_JpsiToMuMu_LL_DetachedLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BdToJpsimumuKshort_LL_detached_line(
+        process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BdToJpsimumuKshort_DD_detached_line(
+        name='Hlt2B2CC_BdToJpsiKshort_JpsiToMuMu_DD_DetachedLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BdToJpsimumuKshort_DD_detached_line(
+        process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BdToJpsimumuKshort_LD_detached_line(
+        name='Hlt2B2CC_BdToJpsiKshort_JpsiToMuMu_LD_DetachedLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BdToJpsimumuKshort_LD_detached_line(
+        process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BdToJpsimumuKshort_UL_detached_line(
+        name='Hlt2B2CC_BdToJpsiKshort_JpsiToMuMu_UL_DetachedLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BdToJpsimumuKshort_UL_detached_line(
+        process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BdTopsitwosmumuKshort_LL_tight_line(
+        name='Hlt2B2CC_BdToPsitwosKshort_PsitwosToMuMu_LL_TightLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BdTopsitwosmumuKshort_LL_tight_line(
+        process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BdTopsitwosmumuKshort_DD_tight_line(
+        name='Hlt2B2CC_BdToPsitwosKshort_PsitwosToMuMu_DD_TightLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BdTopsitwosmumuKshort_DD_tight_line(
+        process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BdTopsitwosmumuKshort_LL_detached_line(
+        name='Hlt2B2CC_BdToPsitwosKshort_PsitwosToMuMu_LL_DetachedLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BdTopsitwosmumuKshort_LL_detached_line(
+        process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BdTopsitwosmumuKshort_DD_detached_line(
+        name='Hlt2B2CC_BdToPsitwosKshort_PsitwosToMuMu_DD_DetachedLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BdTopsitwosmumuKshort_DD_detached_line(
+        process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BuToJpsimumuKplus_tight_line(
+        name='Hlt2B2CC_BuToJpsiKplus_JpsiToMuMu_TightLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BuToJpsimumuKplus_tight_line(process=PROCESS)
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BuToJpsimumuKplus_detached_line(
+        name='Hlt2B2CC_BuToJpsiKplus_JpsiToMuMu_DetachedLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BuToJpsimumuKplus_detached_line(process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BdToJpsimumuKstar_detached_line(
+        name='Hlt2B2CC_BdToJpsiKstar_JpsiToMuMu_DetachedLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BdToJpsimumuKstar_detached_line(process=PROCESS)
+
+    return HltLine(
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+def BdToJpsimumuKstar_tight_line(
+        name='Hlt2B2CC_BdToJpsiKstar_JpsiToMuMu_TightLine',
+        prescale=1,
+        persistreco=False):
+    line_alg = b_to_jpsix.make_BdToJpsimumuKstar_tight_line(process=PROCESS)
 
     return HltLine(
-        name=name, prescale=prescale, algs=b2cc_prefilters() + [b2jpsikstar])
+        name=name,
+        prescale=prescale,
+        algs=b2cc_prefilters() + line_alg,
+        extra_outputs=extra_outputs_for_FlavourTagging(line_alg[2]),
+        persistreco=persistreco)
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/spruce_b2cc.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/spruce_b2cc.py
index 31db86f110526f16bea0cb367e82587dbe1ebf13..f50be3f1f459720877f1ab6024e9d24fc2e864ed 100644
--- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/spruce_b2cc.py
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/b_to_charmonia/spruce_b2cc.py
@@ -33,7 +33,20 @@ def BsToJpsiPhi_JpsiToMuMu_sprucing_line(
     """
      Bs0 --> Jpsi(-> mu+ mu-) phi spruce line
     """
-    line_alg = b_to_jpsix.make_BsToJpsiPhi_detachedline(process=PROCESS)
+    line_alg = b_to_jpsix.make_BsToJpsiPhi_detached_line(process=PROCESS)
 
     return SpruceLine(
-        name=name, prescale=prescale, algs=b2cc_prefilters() + [line_alg])
+        name=name, prescale=prescale, algs=b2cc_prefilters() + line_alg)
+
+
+@register_line_builder(sprucing_lines)
+@configurable
+def BsToJpsiKstarWide_line(name='SpruceB2CC_BsToJpsiKstarWide_Line',
+                           prescale=1):
+    """
+     Bs0 --> Jpsi(-> mu+ mu-) Kst spruce line
+    """
+    line_alg = b_to_jpsix.make_BsToJpsiKstar_line(process=PROCESS)
+
+    return SpruceLine(
+        name=name, prescale=prescale, algs=b2cc_prefilters() + line_alg)
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/b_hadrons.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/b_hadrons.py
index b980f5a916441e1d9cbc33f87a3668eea124b204..d7cc931e934e6af98e2ee50537f01395ec3195e7 100644
--- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/b_hadrons.py
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/b_hadrons.py
@@ -45,13 +45,11 @@ def make_b_hadron(particles,
     combination_code = (in_range(am_min, F.MASS, am_max))
 
     vertex_code = require_all(
-        #there is still a bug in F.BPVLTIME
-        in_range(m_min, F.MASS, m_max),
-        F.CHI2DOF < vtx_chi2pdof_max,
+        in_range(m_min, F.MASS, m_max), F.CHI2DOF < vtx_chi2pdof_max,
+        F.BPVLTIME(pvs) > bpvltime_min,
         F.BPVVDRHO(pvs) > minRho,
         F.BPVVDZ(pvs) > minVDz,
         F.BPVDIRA(pvs) > minBPVDira)
-    #in_range(m_min, F.MASS, m_max), F.CHI2DOF < vtx_chi2pdof_max, F.BPVLTIME(pvs) > bpvltime_min)
 
     return ParticleCombiner(
         name=name,
@@ -75,7 +73,7 @@ def make_bds(particles, descriptor, name="bandq_Bds"):
 
 
 @configurable
-def make_withNeutrals_Bds(particles,
+def make_withneutrals_bds(particles,
                           descriptor,
                           name="bandq_withNeutrals_Bds",
                           am_min=4500 * MeV,
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/b_to_etacX.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/b_to_etacX.py
index d897c337cac81ca0a190eed488bc2acfbac00fb2..7948ecedbe4b803db602641f091a60d599d71524 100644
--- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/b_to_etacX.py
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/b_to_etacX.py
@@ -9,7 +9,7 @@
 # or submit itself to any jurisdiction.                                       #
 ###############################################################################
 """
-Make B&Q dimuon combinations.
+Make B&Q B -> etac X combinations.
 """
 
 import Functors as F
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/b_to_jpsiX.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/b_to_jpsiX.py
index f702b214380adca5891e950c3beebbd3edc158a4..282e2e48489a4f87c66a32ac82134e6b99bda4df 100644
--- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/b_to_jpsiX.py
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/b_to_jpsiX.py
@@ -9,7 +9,7 @@
 # or submit itself to any jurisdiction.                                       #
 ###############################################################################
 """
-Make B&Q dimuon combinations.
+Make B&Q B -> dimuon X combinations.
 """
 
 import Functors as F
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/c_hadrons.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/c_hadrons.py
new file mode 100644
index 0000000000000000000000000000000000000000..a3c6e678467c492cbebe2ed11421037f0d7c1f24
--- /dev/null
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/c_hadrons.py
@@ -0,0 +1,193 @@
+###############################################################################
+# (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration           #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+"""
+Definition of B&Q c-hadrons
+"""
+import Functors as F
+from Functors.math import in_range
+
+from GaudiKernel.SystemOfUnits import MeV, picosecond
+
+from Hlt2Conf.algorithms_thor import require_all, ParticleCombiner
+from PyConf import configurable
+
+from RecoConf.reconstruction_objects import make_pvs_v2 as make_pvs
+
+####################################
+# D0/D0bar                         #
+####################################
+
+
+@configurable
+def make_dz(particles,
+            descriptor,
+            name="bandq_Dz",
+            am_min=1780 * MeV,
+            am_max=1950 * MeV,
+            apt_min=950 * MeV,
+            m_min=1790 * MeV,
+            m_max=1940 * MeV,
+            pt_min=1000 * MeV,
+            vtx_chi2pdof_max=9,
+            bpvltime_min=0.2 * picosecond):
+
+    pvs = make_pvs()
+
+    combination_code = require_all(
+        in_range(am_min, F.MASS, am_max), F.PT > apt_min)
+
+    vertex_code = require_all(
+        in_range(m_min, F.MASS, m_max), F.PT > pt_min,
+        F.CHI2DOF < vtx_chi2pdof_max,
+        F.BPVLTIME(pvs) > bpvltime_min)
+
+    return ParticleCombiner(
+        name=name,
+        Inputs=particles,
+        DecayDescriptor=descriptor,
+        CombinationCut=combination_code,
+        CompositeCut=vertex_code)
+
+
+####################################
+# D+/D-                            #
+####################################
+
+
+@configurable
+def make_dp(particles,
+            descriptor,
+            name="bandq_Dp",
+            am_min=1805 * MeV,
+            am_max=1935 * MeV,
+            achi2_doca_max=16,
+            apt_min=950 * MeV,
+            m_min=1815 * MeV,
+            m_max=1925 * MeV,
+            pt_min=1000 * MeV,
+            vtx_chi2pdof_max=25,
+            bpvltime_min=0.2 * picosecond):
+
+    pvs = make_pvs()
+
+    combination_code = require_all(
+        in_range(am_min, F.MASS, am_max),
+        F.DOCACHI2(1, 2) < achi2_doca_max,
+        F.DOCACHI2(1, 3) < achi2_doca_max,
+        F.DOCACHI2(2, 3) < achi2_doca_max, F.PT > apt_min)
+
+    vertex_code = require_all(
+        in_range(m_min, F.MASS, m_max), F.PT > pt_min,
+        F.CHI2DOF < vtx_chi2pdof_max,
+        F.BPVLTIME(pvs) > bpvltime_min)
+
+    return ParticleCombiner(
+        name=name,
+        Inputs=particles,
+        DecayDescriptor=descriptor,
+        CombinationCut=combination_code,
+        CompositeCut=vertex_code)
+
+
+####################################
+# Ds+/Ds-                          #
+####################################
+
+
+@configurable
+def make_ds(particles,
+            descriptor,
+            name="bandq_Ds",
+            am_min=1900 * MeV,
+            am_max=2035 * MeV,
+            m_min=1910 * MeV,
+            m_max=2025 * MeV):
+
+    return make_dp(
+        particles,
+        descriptor,
+        name=name,
+        am_min=am_min,
+        am_max=am_max,
+        m_min=m_min,
+        m_max=m_max)
+
+
+####################################
+# Lc+/Lc-                          #
+####################################
+
+
+@configurable
+def make_lc(particles,
+            descriptor,
+            name="bandq_Lc",
+            am_min=2220 * MeV,
+            am_max=2350 * MeV,
+            m_min=2230 * MeV,
+            m_max=2340 * MeV):
+
+    return make_dp(
+        particles,
+        descriptor,
+        name=name,
+        am_min=am_min,
+        am_max=am_max,
+        m_min=m_min,
+        m_max=m_max)
+
+
+####################################
+# Xic+/Xic-/Xic0                   #
+####################################
+
+
+@configurable
+def make_xic(particles,
+             descriptor,
+             name="bandq_Xic",
+             am_min=2400 * MeV,
+             am_max=2530 * MeV,
+             m_min=2410 * MeV,
+             m_max=2520 * MeV):
+
+    return make_dp(
+        particles,
+        descriptor,
+        name=name,
+        am_min=am_min,
+        am_max=am_max,
+        m_min=m_min,
+        m_max=m_max)
+
+
+####################################
+# Omegac0                          #
+####################################
+
+
+@configurable
+def make_omegac(particles,
+                descriptor,
+                name="bandq_Omegac",
+                am_min=2630 * MeV,
+                am_max=2750 * MeV,
+                m_min=2640 * MeV,
+                m_max=2740 * MeV):
+
+    return make_dp(
+        particles,
+        descriptor,
+        name=name,
+        am_min=am_min,
+        am_max=am_max,
+        m_min=m_min,
+        m_max=m_max)
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/c_to_hadrons.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/c_to_hadrons.py
new file mode 100644
index 0000000000000000000000000000000000000000..34bcddb3e26ccc811f423fa62172cf12ac345b8d
--- /dev/null
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/c_to_hadrons.py
@@ -0,0 +1,187 @@
+###############################################################################
+# (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration           #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+"""
+Make B&Q c-hadrons standard decay modes.
+"""
+
+from PyConf import configurable
+
+from Hlt2Conf.algorithms import ParticleContainersMerger
+
+from Hlt2Conf.lines.bandq.builders import charged_hadrons, c_hadrons
+
+###########################################
+# D0 standard decay modes:                #
+# - D0 -> K- pi+                          #
+# - D0 -> pi+ pi-                         #
+# - D0 -> K+ K-                           #
+# - D0 -> hh combining the 3 above        #
+###########################################
+
+
+@configurable
+def make_DzToKmPip(name="bandq_DzToKmPip"):
+    kaons = charged_hadrons.make_detached_kaons(mipchi2dvprimary_min=7.)
+    pions = charged_hadrons.make_detached_pions(mipchi2dvprimary_min=7.)
+    line_alg = c_hadrons.make_dz(
+        name=name, particles=[kaons, pions], descriptor='[D0 -> K- pi+]cc')
+    return line_alg
+
+
+@configurable
+def make_DzToPimPip(name="bandq_DzToPimPip"):
+    pions = charged_hadrons.make_detached_pions(mipchi2dvprimary_min=7.)
+    line_alg = c_hadrons.make_dz(
+        name=name, particles=[pions, pions], descriptor='D0 -> pi- pi+')
+    return line_alg
+
+
+@configurable
+def make_DzToKmKp(name="bandq_DzToKmKp"):
+    kaons = charged_hadrons.make_detached_kaons(mipchi2dvprimary_min=7.)
+    line_alg = c_hadrons.make_dz(
+        name=name, particles=[kaons, kaons], descriptor='D0 -> K- K+')
+    return line_alg
+
+
+@configurable
+def make_DzToHH(name="bandq_DzToHH"):
+    Dz_KmPip = make_DzToKmPip()
+    Dz_PimPip = make_DzToPimPip()
+    Dz_KmKp = make_DzToKmKp()
+    return ParticleContainersMerger([Dz_KmPip, Dz_PimPip, Dz_KmKp], name=name)
+
+
+###########################################
+# D+ standard decay modes:                #
+# - D+ -> K- pi+ pi+                      #
+###########################################
+
+
+@configurable
+def make_DpToKmPipPip(name="bandq_DpToKmPipPip"):
+    kaons = charged_hadrons.make_detached_kaons(mipchi2dvprimary_min=7.)
+    pions = charged_hadrons.make_detached_pions(mipchi2dvprimary_min=7.)
+    line_alg = c_hadrons.make_dp(
+        name=name,
+        particles=[kaons, pions, pions],
+        descriptor='[D+ -> K- pi+ pi+]cc')
+    return line_alg
+
+
+###########################################
+# Ds+ standard decay modes:                #
+# - Ds+ -> K- K+ pi+                      #
+###########################################
+
+
+@configurable
+def make_DspToKmKpPip(name="bandq_DspToKmKpPip"):
+    kaons = charged_hadrons.make_detached_kaons(mipchi2dvprimary_min=7.)
+    pions = charged_hadrons.make_detached_pions(mipchi2dvprimary_min=7.)
+    line_alg = c_hadrons.make_ds(
+        name=name,
+        particles=[kaons, kaons, pions],
+        descriptor='[D_s+ -> K- K+ pi+]cc')
+    return line_alg
+
+
+###########################################
+# Lc+ standard decay modes:               #
+# - Lc+ -> p K- pi+                       #
+###########################################
+
+
+@configurable
+def make_LcToPpKmPip(name="bandq_LcToPpKmPip"):
+    protons = charged_hadrons.make_detached_protons(mipchi2dvprimary_min=5.)
+    kaons = charged_hadrons.make_detached_kaons(mipchi2dvprimary_min=5.)
+    pions = charged_hadrons.make_detached_pions(mipchi2dvprimary_min=5.)
+    line_alg = c_hadrons.make_lc(
+        name=name,
+        particles=[protons, kaons, pions],
+        descriptor='[Lambda_c+ -> p+ K- pi+]cc')
+    return line_alg
+
+
+###########################################
+# Xic+ standard decay modes:              #
+# - Xic+ -> p K- pi+                      #
+###########################################
+
+
+@configurable
+def make_XicpToPpKmPip(name="bandq_XicpToPpKmPip"):
+    protons = charged_hadrons.make_detached_protons(mipchi2dvprimary_min=5.)
+    kaons = charged_hadrons.make_detached_kaons(mipchi2dvprimary_min=5.)
+    pions = charged_hadrons.make_detached_pions(mipchi2dvprimary_min=5.)
+    line_alg = c_hadrons.make_xic(
+        name=name,
+        particles=[protons, kaons, pions],
+        descriptor='[Xi_c+ -> p+ K- pi+]cc')
+    return line_alg
+
+
+###########################################
+# Xic0 standard decay modes:              #
+# - Xic0 -> p K- K- pi+                   #
+###########################################
+
+
+@configurable
+def make_XiczToPpKmKmPip(name="bandq_XiczToPpKmKmPip"):
+    protons = charged_hadrons.make_detached_protons(mipchi2dvprimary_min=5.)
+    kaons = charged_hadrons.make_detached_kaons(mipchi2dvprimary_min=5.)
+    pions = charged_hadrons.make_detached_pions(mipchi2dvprimary_min=5.)
+    line_alg = c_hadrons.make_xic(
+        name=name,
+        particles=[protons, kaons, kaons, pions],
+        descriptor='[Xi_c0 -> p+ K- K- pi+]cc')
+    return line_alg
+
+
+###########################################
+# Omegac0 standard decay modes:           #
+# - Omegac0 -> p K- K- pi+                #
+###########################################
+
+
+@configurable
+def make_OmegaczToPpKmKmPip(name="bandq_OmegaczToPpKmKmPip"):
+    protons = charged_hadrons.make_detached_protons(mipchi2dvprimary_min=5.)
+    kaons = charged_hadrons.make_detached_kaons(mipchi2dvprimary_min=5.)
+    pions = charged_hadrons.make_detached_pions(mipchi2dvprimary_min=5.)
+    line_alg = c_hadrons.make_omegac(
+        name=name,
+        particles=[protons, kaons, kaons, pions],
+        descriptor='[Omega_c0 -> p+ K- K- pi+]cc')
+    return line_alg
+
+
+################################################
+# Build a single container with all the decays #
+################################################
+
+
+@configurable
+def make_charm_to_hadrons(name="bandq_charmToHadrons"):
+    DzToHH = make_DzToHH()
+    DpToKmPipPip = make_DpToKmPipPip()
+    DsToKmKpPip = make_DspToKmKpPip()
+    LcToPpKmPip = make_LcToPpKmPip()
+    XicpToPpKmPip = make_XicpToPpKmPip()
+    XiczToPpKmKmPip = make_XiczToPpKmKmPip()
+    OmegaczToPpKmKmPip = make_OmegaczToPpKmKmPip()
+    return ParticleContainersMerger([
+        DzToHH, DpToKmPipPip, DsToKmKpPip, LcToPpKmPip, XicpToPpKmPip,
+        XiczToPpKmKmPip, OmegaczToPpKmKmPip
+    ],
+                                    name=name)
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/charged_hadrons.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/charged_hadrons.py
index 1561671a97fae417023732a7bca90f70feef2edf..3be2b798d735eb3f6a6edcf426251287c406fa63 100644
--- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/charged_hadrons.py
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/charged_hadrons.py
@@ -34,25 +34,20 @@ from Functors.math import in_range
 
 
 @configurable
-def make_charged_hadrons(
-        make_particles=make_has_rich_long_pions,
-        name="bandq_charged_hadrons",
-        pt_min=200. * MeV,  #TBC with Reco
-        p_min=2.5 * GeV,
-        p_max=150. * GeV,
-        eta_min=2.,
-        eta_max=5.,
-        trchi2dof_max=4,  #TBC with Reco
-        trghostprob_max=0.4,  #TBC with Reco
-        mipchi2dvprimary_min=0,
-        pid=None):
+def make_charged_hadrons(make_particles=make_has_rich_long_pions,
+                         name="bandq_charged_hadrons",
+                         pt_min=200. * MeV,
+                         p_min=2.5 * GeV,
+                         p_max=150. * GeV,
+                         eta_min=2.,
+                         eta_max=5.,
+                         mipchi2dvprimary_min=0,
+                         pid=None):
 
     pvs = make_pvs()
 
     code = require_all(F.PT > pt_min, in_range(p_min, F.P, p_max),
-                       in_range(eta_min, F.ETA,
-                                eta_max), F.CHI2DOF < trchi2dof_max,
-                       F.GHOSTPROB < trghostprob_max,
+                       in_range(eta_min, F.ETA, eta_max),
                        F.MINIPCHI2(pvs) > mipchi2dvprimary_min)
 
     if pid is not None:
@@ -67,10 +62,9 @@ def make_charged_hadrons(
 
 
 @configurable
-def make_detached_pions(
-        name="bandq_detached_pions",
-        mipchi2dvprimary_min=3.,  #TBC
-        pid=(F.PID_K < 0.)):
+def make_detached_pions(name="bandq_detached_pions",
+                        mipchi2dvprimary_min=4.,
+                        pid=(F.PID_K < 0.)):
     """
     Return B&Q detached pions.
     """
@@ -82,10 +76,9 @@ def make_detached_pions(
 
 
 @configurable
-def make_detached_kaons(
-        name="bandq_detached_kaons",
-        mipchi2dvprimary_min=3.,  #TBC
-        pid=(F.PID_K > 0.)):
+def make_detached_kaons(name="bandq_detached_kaons",
+                        mipchi2dvprimary_min=4.,
+                        pid=(F.PID_K > 0.)):
     """
     Return B&Q detached kaons.
     """
@@ -97,12 +90,11 @@ def make_detached_kaons(
 
 
 @configurable
-def make_detached_protons(
-        name="bandq_detached_protons",
-        p_min=10. * GeV,
-        pt_min=200. * MeV,  #TBC with Reco
-        mipchi2dvprimary_min=3.,  #TBC
-        pid=(F.PID_P > 0.)):
+def make_detached_protons(name="bandq_detached_protons",
+                          p_min=10. * GeV,
+                          pt_min=200. * MeV,
+                          mipchi2dvprimary_min=3.,
+                          pid=(F.PID_P > 0.)):
     """
     Return B&Q detached protons.
     """
@@ -139,11 +131,10 @@ def make_prompt_kaons(name="onia_prompt_kaons", pid=(F.PID_K > 0.)):
 
 
 @configurable
-def make_prompt_protons(
-        name="bandq_prompt_protons",
-        p_min=10. * GeV,
-        pt_min=200. * MeV,  #TBC with Reco
-        pid=(F.PID_P > 0.)):
+def make_prompt_protons(name="bandq_prompt_protons",
+                        p_min=10. * GeV,
+                        pt_min=200. * MeV,
+                        pid=(F.PID_P > 0.)):
     """
     Return B&Q prompt protons.
     """
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/dimuon.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/dimuon.py
index 2c056fcefaf967487a6cb86632f440c9b063295c..1285d385bf1f5c0be2f076ecf2bbe845cbbb518c 100644
--- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/dimuon.py
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/dimuon.py
@@ -57,19 +57,14 @@ def make_bandq_muons(make_particles=make_ismuon_long_muon,
                      minIPChi2_muon=0,
                      minIP_muon=0,
                      minPIDmu=-999,
-                     maxTrackGhostProb_muon=1.0,
-                     maxIPChi2_muon=None,
-                     maxTrackChi2_muon=None):
+                     maxIPChi2_muon=None):
 
     pvs = make_pvs()
 
     code = require_all(F.PT > minPt_muon, F.ISMUON, F.P > minP_muon,
                        F.MINIPCHI2(pvs) > minIPChi2_muon,
-                       F.MINIP(pvs) > minIP_muon, F.PID_MU > minPIDmu,
-                       F.GHOSTPROB < maxTrackGhostProb_muon)
+                       F.MINIP(pvs) > minIP_muon, F.PID_MU > minPIDmu)
 
-    if maxTrackChi2_muon is not None:
-        code &= (F.CHI2 < maxTrackChi2_muon)
     if maxIPChi2_muon is not None:
         code &= (F.MINIPCHI2(pvs) < maxIPChi2_muon)
 
@@ -78,20 +73,16 @@ def make_bandq_muons(make_particles=make_ismuon_long_muon,
 
 # the new dimuon base for bandq lines
 @configurable
-def make_bandq_dimuon_base(
-        name='bandq_dimuon_base',
-        DecayDescriptor='J/psi(1S) -> mu+ mu-',
-        maxVertexChi2=25,
-        minPt_muon=0. * MeV,
-        minP_muon=0. * GeV,
-        minIPChi2_muon=0,
-        minIP_muon=0,
-        maxTrackGhostProb_muon=1.0,
-        minPIDmu=-999,
-        minMass_dimuon=0. * MeV,
-        maxMass_dimuon=100000. * MeV,
-        maxTrackChi2_muon=None,
-):
+def make_bandq_dimuon_base(name='bandq_dimuon_base',
+                           DecayDescriptor='J/psi(1S) -> mu+ mu-',
+                           maxVertexChi2=25,
+                           minPt_muon=0. * MeV,
+                           minP_muon=0. * GeV,
+                           minIPChi2_muon=0,
+                           minIP_muon=0,
+                           minPIDmu=-999,
+                           minMass_dimuon=0. * MeV,
+                           maxMass_dimuon=100000. * MeV):
 
     # get the long muons
     muons = make_bandq_muons(
@@ -99,8 +90,6 @@ def make_bandq_dimuon_base(
         minP_muon=minP_muon,
         minIPChi2_muon=minIPChi2_muon,
         minIP_muon=minIP_muon,
-        maxTrackGhostProb_muon=maxTrackGhostProb_muon,
-        maxTrackChi2_muon=maxTrackChi2_muon,
         minPIDmu=minPIDmu)
 
     combination_code = in_range(minMass_dimuon, F.MASS, maxMass_dimuon)
@@ -117,26 +106,22 @@ def make_bandq_dimuon_base(
 
 
 @configurable
-def make_dimuon(
-        name="bandq_dimuon",
-        DecayDescriptor='J/psi(1S) -> mu+ mu-',
-        minPt_dimuon=0 * MeV,
-        minPt_muon=300 * MeV,
-        minP_muon=0 * MeV,
-        maxVertexChi2=25,
-        #maxTrackChi2_muon=10, # to be decided if we want to keep TrackChi2 cuts in the trigger
-        maxTrackGhostProb_muon=0.4,  # this has to be reoptimised for the Upgrade
-        minPIDmu=-5,
-        bpvdls_min=0.,
-        minMass_dimuon=0. * MeV,
-        maxMass_dimuon=10000. * MeV):
+def make_dimuon(name="bandq_dimuon",
+                DecayDescriptor='J/psi(1S) -> mu+ mu-',
+                minPt_dimuon=0 * MeV,
+                minPt_muon=300 * MeV,
+                minP_muon=0 * MeV,
+                maxVertexChi2=25,
+                minPIDmu=-5,
+                bpvdls_min=0.,
+                minMass_dimuon=0. * MeV,
+                maxMass_dimuon=10000. * MeV):
 
     make_particles = make_bandq_dimuon_base(
         DecayDescriptor=DecayDescriptor,
         maxVertexChi2=maxVertexChi2,
         minPt_muon=minPt_muon,
         minP_muon=minP_muon,
-        maxTrackGhostProb_muon=maxTrackGhostProb_muon,
         minPIDmu=minPIDmu,
         minMass_dimuon=minMass_dimuon,
         maxMass_dimuon=maxMass_dimuon)
@@ -340,7 +325,6 @@ def make_soft_detached_dimuon(
         minP_muon=0. * GeV,
         minIPChi2_muon=9,
         minIP_muon=0.3 * mm,
-        maxTrackGhostProb_muon=0.4,
         minPIDmu=-5,
         maxDOCA=0.3,
         maxIPChi2_muon=10000.0,
@@ -359,7 +343,6 @@ def make_soft_detached_dimuon(
         minP_muon=minP_muon,
         minIPChi2_muon=minIPChi2_muon,
         minIP_muon=minIP_muon,
-        maxTrackGhostProb_muon=maxTrackGhostProb_muon,
         maxIPChi2_muon=maxIPChi2_muon,
         minPIDmu=minPIDmu,
     )
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/doublecharm.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/doublecharm.py
new file mode 100644
index 0000000000000000000000000000000000000000..cdfb6fae4a739a1e48c9cea4f76df9f7c90e96d5
--- /dev/null
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/builders/doublecharm.py
@@ -0,0 +1,95 @@
+###############################################################################
+# (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration           #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+"""
+Make B&Q double charm combinations.
+"""
+
+from Hlt2Conf.algorithms import ParticleContainersMerger
+import Functors as F
+from Hlt2Conf.algorithms_thor import require_all, ParticleCombiner
+
+from PyConf import configurable
+
+from Hlt2Conf.lines.bandq.builders import c_to_hadrons
+
+
+@configurable
+def _make_doublecharm(particles,
+                      descriptor,
+                      name="bandq_doublecharm_singledecay_template"):
+    combination_code = require_all(F.ALL)
+    vertex_code = require_all(F.ALL)
+    return ParticleCombiner(
+        name=name,
+        Inputs=particles,
+        DecayDescriptor=descriptor,
+        CombinationCut=combination_code,
+        CompositeCut=vertex_code)
+
+
+@configurable
+def make_doublecharm(particles, descriptors,
+                     name="bandq_doublecharm_template"):
+    assert len(descriptors) > 0
+    c_hadrons = []
+    for descriptor in descriptors:
+        c_hadrons.append(
+            _make_doublecharm(particles=particles, descriptor=descriptor))
+    return ParticleContainersMerger(c_hadrons, name=name)
+
+
+@configurable
+def make_doublecharm_samesign(name="bandq_doublecharm_samesign"):
+    c_hadron = c_to_hadrons.make_charm_to_hadrons()
+    line_alg = make_doublecharm(
+        name=name,
+        particles=[c_hadron, c_hadron],
+        descriptors=[
+            '[psi(3770) -> D0 D0]cc', '[psi(3770) -> D0 D+]cc',
+            '[psi(3770) -> D0 D_s+]cc', '[psi(3770) -> D0 Lambda_c+]cc',
+            '[psi(3770) -> D0 Xi_c0]cc', '[psi(3770) -> D0 Omega_c0]cc',
+            '[psi(3770) -> D+ D+]cc', '[psi(3770) -> D+ D_s+]cc',
+            '[psi(3770) -> D+ Lambda_c+]cc', '[psi(3770) -> D+ Xi_c0]cc',
+            '[psi(3770) -> D+ Omega_c0]cc', '[psi(3770) -> D_s+ D_s+]cc',
+            '[psi(3770) -> D_s+ Lambda_c+]cc', '[psi(3770) -> D_s+ Xi_c0]cc',
+            '[psi(3770) -> D_s+ Omega_c0]cc',
+            '[psi(3770) -> Lambda_c+ Lambda_c+]cc',
+            '[psi(3770) -> Lambda_c+ Xi_c0]cc',
+            '[psi(3770) -> Lambda_c+ Omega_c0]cc',
+            '[psi(3770) -> Xi_c0 Xi_c0]cc', '[psi(3770) -> Xi_c0 Omega_c0]cc',
+            '[psi(3770) -> Omega_c0 Omega_c0]cc'
+        ])
+    return line_alg
+
+
+@configurable
+def make_doublecharm_oppositesign(name="bandq_doublecharm_oppositesign"):
+    c_hadron = c_to_hadrons.make_charm_to_hadrons()
+    line_alg = make_doublecharm(
+        name=name,
+        particles=[c_hadron, c_hadron],
+        descriptors=[
+            '[psi(3770) -> D~0 D0]cc', '[psi(3770) -> D~0 D+]cc',
+            '[psi(3770) -> D~0 D_s+]cc', '[psi(3770) -> D~0 Lambda_c+]cc',
+            '[psi(3770) -> D~0 Xi_c0]cc', '[psi(3770) -> D~0 Omega_c0]cc',
+            '[psi(3770) -> D- D+]cc', '[psi(3770) -> D- D_s+]cc',
+            '[psi(3770) -> D- Lambda_c+]cc', '[psi(3770) -> D- Xi_c0]cc',
+            '[psi(3770) -> D- Omega_c0]cc', '[psi(3770) -> D_s- D_s+]cc',
+            '[psi(3770) -> D_s- Lambda_c+]cc', '[psi(3770) -> D_s- Xi_c0]cc',
+            '[psi(3770) -> D_s- Omega_c0]cc',
+            '[psi(3770) -> Lambda_c~- Lambda_c+]cc',
+            '[psi(3770) -> Lambda_c~- Xi_c0]cc',
+            '[psi(3770) -> Lambda_c~- Omega_c0]cc',
+            '[psi(3770) -> Xi_c~0 Xi_c0]cc',
+            '[psi(3770) -> Xi_c~0 Omega_c0]cc',
+            '[psi(3770) -> Omega_c~0 Omega_c0]cc'
+        ])
+    return line_alg
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/hlt2_bandq.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/hlt2_bandq.py
index 03e06f39191cdbb064622af93e1ec096ef279088..1f9db0a34de487139698285982617818a579d3cf 100644
--- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/hlt2_bandq.py
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/bandq/hlt2_bandq.py
@@ -9,7 +9,7 @@
 # or submit itself to any jurisdiction.                                       #
 ###############################################################################
 """
-Definition of exclusive Bc+->psiX HLT2 lines
+Definition of B&Q HLT2 lines
 """
 
 from __future__ import absolute_import, division, print_function
@@ -23,6 +23,7 @@ from Hlt2Conf.lines.bandq.builders import b_to_jpsiX
 from Hlt2Conf.lines.bandq.builders import dps
 from Hlt2Conf.lines.bandq.builders import dimuon
 from Hlt2Conf.lines.bandq.builders import chic_to_jpsimumu
+from Hlt2Conf.lines.bandq.builders import doublecharm
 from Hlt2Conf.standard_particles import make_has_rich_long_pions, make_has_rich_down_pions
 
 from Hlt2Conf.lines.bandq.builders import ccbar_to_hadrons
@@ -166,10 +167,15 @@ def Psi2SToMuMuTight_line(name='Hlt2BandQ_DiMuonPsi2STightLine', prescale=1):
 
 @register_line_builder(all_lines)
 @configurable
-def UpsilonToMuMu_line(name='Hlt2BandQ_DiMuonUpsilonLine', prescale=1):
+def UpsilonToMuMu_line(name='Hlt2BandQ_DiMuonUpsilonLine',
+                       prescale=1,
+                       persistreco=True):
     line_alg = dimuon.make_upsilon()
     return HltLine(
-        name=name, algs=make_prefilters() + [line_alg], prescale=prescale)
+        name=name,
+        algs=make_prefilters() + [line_alg],
+        prescale=prescale,
+        persistreco=persistreco)
 
 
 @register_line_builder(all_lines)
@@ -183,11 +189,15 @@ def ZToMuMu_line(name='Hlt2BandQ_DiMuonZLine', prescale=1):
 @register_line_builder(all_lines)
 @configurable
 def BcToJpsiPip_JpsiToMuMu_line(name='Hlt2BandQ_BcToJpsiPip_JpsiToMuMu_Line',
-                                prescale=1):
+                                prescale=1,
+                                persistreco=True):
     """Bc+ --> Jpsi(-> mu+ mu-)  pi+ line"""
     line_alg = b_to_jpsiX.make_BcToJpsiPip_JpsiToMuMu(process=PROCESS)
     return HltLine(
-        name=name, algs=make_prefilters() + [line_alg], prescale=prescale)
+        name=name,
+        algs=make_prefilters() + [line_alg],
+        prescale=prescale,
+        persistreco=persistreco)
 
 
 @register_line_builder(all_lines)
@@ -306,3 +316,29 @@ def chic2jpsimumu_line(name="Hlt2BandQ_DiMuonChicJpsiDiMuonLine", prescale=1):
     line_alg = chic_to_jpsimumu.make_chic2jpsimumu()
     return HltLine(
         name=name, algs=make_prefilters() + [line_alg], prescale=prescale)
+
+
+@register_line_builder(all_lines)
+@configurable
+def doublecharm_samesign_line(name="Hlt2BandQ_DoubleCharmSameSignLine",
+                              prescale=1,
+                              persistreco=True):
+    line_alg = doublecharm.make_doublecharm_samesign()
+    return HltLine(
+        name=name,
+        algs=make_prefilters() + [line_alg],
+        prescale=prescale,
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+@configurable
+def doublecharm_oppositesign_line(name="Hlt2BandQ_DoubleCharmOppositeSignLine",
+                                  prescale=1,
+                                  persistreco=True):
+    line_alg = doublecharm.make_doublecharm_oppositesign()
+    return HltLine(
+        name=name,
+        algs=make_prefilters() + [line_alg],
+        prescale=prescale,
+        persistreco=persistreco)
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/__init__.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/__init__.py
index 9b3b75aec6651572c054a7ee9230051b995bf814..46a5f92bec7a4ebee1d82ca918a77abd11a51fc5 100644
--- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/__init__.py
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/__init__.py
@@ -23,6 +23,8 @@ from . import rare_tau_decay_lines
 from . import RpK_lines
 from . import b_to_hemu
 from . import b_to_hemu_control_modes
+from . import b_to_majolep_majo_to_leppi
+from . import qqbar_to_ll
 
 # provide "all_lines" for correct registration by the overall HLT2 lines module
 all_lines = {}
@@ -37,6 +39,8 @@ all_lines.update(rare_tau_decay_lines.all_lines)
 all_lines.update(RpK_lines.all_lines)
 all_lines.update(b_to_hemu.all_lines)
 all_lines.update(b_to_hemu_control_modes.all_lines)
+all_lines.update(b_to_majolep_majo_to_leppi.all_lines)
+all_lines.update(qqbar_to_ll.all_lines)
 
 sprucing_lines = {}
 sprucing_lines.update(spruce_beauty2xtaul.sprucing_lines)
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/b_to_majolep_majo_to_leppi.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/b_to_majolep_majo_to_leppi.py
new file mode 100644
index 0000000000000000000000000000000000000000..33b99930525236d1964d3e96ba44975a0350c7c7
--- /dev/null
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/b_to_majolep_majo_to_leppi.py
@@ -0,0 +1,491 @@
+###############################################################################
+# (c) Copyright 2019 CERN for the benefit of the LHCb Collaboration           #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+"""
+This defines HLT2 lines for B+(-)/B_c+(-) -> mu/e(+/-) N, N-> e/mu pi, where N is a neutral lepton  
+And a normalisation line for B+ -> pi+ KS0, where KS0 -> pi+pi-
+Both same sign lepton and opposite sign lepton are included due to the KS0 descriptor being independent of the lepton signs. 
+N has no lifetime hypothesis applied. Combination of the neutral lepton daugthers is limited between 200(to cut conversion)-7000 MeV 
+All leptons from B are Long. Daughters of the neutral lepton can be both Long and Downstream.
+Loose and Tight lines have a different PID cut looseness on pions and electrons. Note, PID_E is applied to pions too, so there is a need for a no_brem added calibration.
+Tight lines will hopefully have raw event information saved, specifically tracking infor.
+
+List of lines (LL - Long, DD - downstream):
+
+Hlt2RD_BpToMajoMu_MajoToEPi_LL_Tight_Line: tight PID cut line for the B(_c)+ -> mu HNL(-> epi, LL)
+Hlt2RD_BpToMajoE_MajoToMuPi_LL_Tight_Line: tight PID cut line for the B(_c)+ -> e HNL(-> mupi, LL)
+Hlt2RD_BpToMajoMu_MajoToEPi_DD_Tight_Line: tight PID cut line for the B(_c)+ -> mu HNL(-> epi, DD)
+Hlt2RD_BpToMajoE_MajoToMuPi_DD_Tight_Line: tight PID cut line for the B(_c)+ -> e HNL(-> mupi, DD)
+
+Hlt2RD_BpToMajoMu_MajoToEPi_LL_Loose_Line: loose PID cut line for the B(_c)+ -> mu HNL(-> epi, LL)
+Hlt2RD_BpToMajoE_MajoToMuPi_LL_Loose_Line: loose PID cut line for the B(_c)+ -> e HNL(-> mupi, LL)
+Hlt2RD_BpToMajoMu_MajoToEPi_DD_Loose_Line: loose PID cut line for the B(_c)+ -> mu HNL(-> epi, DD)
+Hlt2RD_BpToMajoE_MajoToMuPi_DD_Loose_Line: loose PID cut line for the B(_c)+ -> e HNL(-> mupi, DD)
+
+Hlt2RD_BuToKs0Pi_Ks0ToPiPi_LL_Line: B+ -> pi KS0 (->pipi) LL line
+Hlt2RD_BuToKs0Pi_Ks0ToPiPi_DD_Line: B+ -> pi KS0 (->pipi) DD line
+
+
+Contact: Lera Lukashenko, valeriia.lukashenko@cern.ch
+
+TO DO:
+    - basic_builder depends on LoKi and is to be removed, all lines must be updated accordingly
+    - when standard_particles ported to ThOr, only make_pvs_v2 should be used
+
+"""
+from Moore.config import register_line_builder
+from Moore.lines import Hlt2Line
+from GaudiKernel.SystemOfUnits import MeV
+
+from Hlt2Conf.standard_particles import (
+    make_long_pions, make_long_muons, make_long_electrons_with_brem,
+    make_down_pions, make_down_muons, make_down_electrons_no_brem,
+    make_KsLL_fromSV, make_KsDD_fromSV)
+
+from RecoConf.reconstruction_objects import make_pvs_v2 as make_pvs  #check for the update
+from RecoConf.reconstruction_objects import make_pvs as make_pvs_v1  #when all is moved to Thor use make_pvs_v2 instead
+all_lines = {}
+
+from Hlt2Conf.lines.rd.builders import basic_builder
+from Hlt2Conf.lines.rd.builders.majorana_builder import make_majorana_lepton, make_majorana, make_bhadron_majorana
+from Hlt2Conf.lines.rd.builders.rd_prefilters import rd_prefilter
+import Functors as F
+
+
+@register_line_builder(all_lines)
+def BpToMajoMu_MajoToEPi_LL_Tight_line(
+        name="Hlt2RD_BpToMajoMu_MajoToEPi_LL_Tight_Line",
+        prescale=1,
+        presistreco=True):
+    pvs = make_pvs
+
+    muons = make_majorana_lepton(
+        leptons=make_long_muons,
+        name='majo_long_muons',
+        pvs=pvs,
+        pt_min=700 * MeV,
+        pid=F.ISMUON)
+
+    electrons_with_brem = make_majorana_lepton(
+        leptons=make_long_electrons_with_brem,
+        name='majo_long_electrons_with_brem',
+        pvs=pvs,
+        pid=(F.PID_E > 1.))
+
+    pions = make_majorana_lepton(
+        leptons=make_long_pions,
+        name='majo_long_pions',
+        pvs=pvs,
+        pid=(F.PID_E <= 0.))
+
+    majoranas2piE = make_majorana(
+        name='Majo2epi',
+        pions=pions,
+        leptons=electrons_with_brem,
+        descriptor='[KS0 -> e- pi+]cc')
+
+    b2MuN = make_bhadron_majorana(
+        name='B2MajoMu',
+        majoranas=majoranas2piE,
+        leptons=muons,
+        pvs=pvs,
+        descriptor='[B+ -> KS0 mu+]cc')
+
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [majoranas2piE, b2MuN],
+        prescale=prescale)
+
+
+@register_line_builder(all_lines)
+def BpToMajoE_MajoToMuPi_LL_Tight_line(
+        name="Hlt2RD_BpToMajoE_MajoToMuPi_LL_Tight_Line",
+        prescale=1,
+        presistreco=True):
+    pvs = make_pvs
+
+    muons = make_majorana_lepton(
+        leptons=make_long_muons, name='majo_long_muons', pvs=pvs, pid=F.ISMUON)
+
+    electrons_with_brem = make_majorana_lepton(
+        leptons=make_long_electrons_with_brem,
+        name='majo_long_electrons_with_brem',
+        pvs=pvs,
+        pt_min=700 * MeV,
+        pid=(F.PID_E > 1.))
+
+    pions = make_majorana_lepton(
+        leptons=make_long_pions,
+        name='majo_long_pions',
+        pvs=pvs,
+        pid=(F.PID_E <= 0.))
+
+    majoranas2piMu = make_majorana(
+        name='Majo2mupi',
+        pions=pions,
+        leptons=muons,
+        descriptor='[KS0 -> mu- pi+]cc')
+
+    b2EN = make_bhadron_majorana(
+        name='B2MajoE',
+        majoranas=majoranas2piMu,
+        leptons=electrons_with_brem,
+        pvs=pvs,
+        descriptor='[B+ -> KS0 e+]cc')
+
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [majoranas2piMu, b2EN],
+        prescale=prescale)
+
+
+@register_line_builder(all_lines)
+def BpToMajoMu_MajoToEPi_DD_Tight_line(
+        name="Hlt2RD_BpToMajoMu_MajoToEPi_DD_Tight_Line",
+        prescale=1,
+        presistreco=True):
+    pvs = make_pvs
+
+    muons = make_majorana_lepton(
+        leptons=make_long_muons,
+        name='majo_long_muons',
+        pvs=pvs,
+        pt_min=700 * MeV,
+        pid=F.ISMUON)
+
+    down_electrons_without_brem = make_majorana_lepton(
+        leptons=make_down_electrons_no_brem,
+        name='majo_down_electrons_without_brem',
+        pvs=pvs,
+        mipchi2dvprimary_min=None,
+        pt_min=600 * MeV,
+        pid=(F.PID_E > 1.))
+
+    down_pions = make_majorana_lepton(
+        leptons=make_down_pions,
+        name='majo_down_pions',
+        pvs=pvs,
+        pt_min=600 * MeV,
+        mipchi2dvprimary_min=None,
+        pid=(F.PID_E <= 0.))
+
+    majoranas2piE = make_majorana(
+        name='Majo2epi',
+        pions=down_pions,
+        leptons=down_electrons_without_brem,
+        descriptor='[KS0 -> e- pi+]cc')
+
+    b2MuN = make_bhadron_majorana(
+        name='B2MajoMu',
+        majoranas=majoranas2piE,
+        leptons=muons,
+        pvs=pvs,
+        descriptor='[B+ -> KS0 mu+]cc')
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [majoranas2piE, b2MuN],
+        prescale=prescale)
+
+
+@register_line_builder(all_lines)
+def BpToMajoE_MajoToMuPi_DD_Tight_line(
+        name="Hlt2RD_BpToMajoE_MajoToMuPi_DD_Tight_Line",
+        prescale=1,
+        presistreco=True):
+    pvs = make_pvs
+
+    electrons_with_brem = make_majorana_lepton(
+        leptons=make_long_electrons_with_brem,
+        name='majo_long_electrons_with_brem',
+        pvs=pvs,
+        pt_min=700 * MeV,
+        pid=(F.PID_E > 1.))
+
+    down_muons = make_majorana_lepton(
+        leptons=make_down_muons,
+        name='majo_down_muons',
+        pvs=pvs,
+        mipchi2dvprimary_min=None,
+        pt_min=600 * MeV,
+        pid=((F.ISMUON) & (F.PID_MU > 0.)))
+
+    down_pions = make_majorana_lepton(
+        leptons=make_down_pions,
+        name='majo_down_pions',
+        pvs=pvs,
+        mipchi2dvprimary_min=None,
+        pt_min=600 * MeV,
+        pid=(F.PID_E <= 0.))
+
+    majoranas2piMu = make_majorana(
+        name='Majo2mupi',
+        pions=down_pions,
+        leptons=down_muons,
+        descriptor='[KS0 -> mu- pi+]cc',
+    )
+
+    b2EN = make_bhadron_majorana(
+        name='B2MajoE',
+        majoranas=majoranas2piMu,
+        leptons=electrons_with_brem,
+        pvs=pvs,
+        descriptor='[B+ -> KS0 e+]cc')
+
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [majoranas2piMu, b2EN],
+        prescale=prescale)
+
+
+@register_line_builder(all_lines)
+def BpToMajoMu_MajoToEPi_LL_Loose_line(
+        name="Hlt2RD_BpToMajoMu_MajoToEPi_LL_Loose_Line",
+        prescale=1,
+        presistreco=False):
+    pvs = make_pvs
+
+    muons = make_majorana_lepton(
+        leptons=make_long_muons,
+        name='majo_long_muons',
+        pvs=pvs,
+        pt_min=700 * MeV,
+        pid=F.ISMUON)
+
+    electrons_with_brem = make_majorana_lepton(
+        leptons=make_long_electrons_with_brem,
+        name='majo_long_electrons_with_brem',
+        pvs=pvs,
+        pid=(F.PID_E > 0.))
+
+    pions = make_majorana_lepton(
+        leptons=make_long_pions,
+        name='majo_long_pions',
+        pvs=pvs,
+        pid=(F.PID_E <= 0))
+
+    majoranas2piE = make_majorana(
+        name='Majo2epi',
+        pions=pions,
+        leptons=electrons_with_brem,
+        descriptor='[KS0 -> e- pi+]cc')
+
+    b2MuN = make_bhadron_majorana(
+        name='B2MajoMu',
+        majoranas=majoranas2piE,
+        leptons=muons,
+        pvs=pvs,
+        descriptor='[B+ -> KS0 mu+]cc')
+
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [majoranas2piE, b2MuN],
+        prescale=prescale)
+
+
+@register_line_builder(all_lines)
+def BpToMajoE_MajoToMuPi_LL_Loose_line(
+        name="Hlt2RD_BpToMajoE_MajoToMuPi_LL_Loose_Line",
+        prescale=1,
+        presistreco=False):
+    pvs = make_pvs
+
+    muons = make_majorana_lepton(
+        leptons=make_long_muons, name='majo_long_muons', pvs=pvs, pid=F.ISMUON)
+
+    electrons_with_brem = make_majorana_lepton(
+        leptons=make_long_electrons_with_brem,
+        name='majo_long_electrons_with_brem',
+        pvs=pvs,
+        pt_min=700 * MeV,
+        pid=(F.PID_E > 0.))
+
+    pions = make_majorana_lepton(
+        leptons=make_long_pions,
+        name='majo_long_pions',
+        pvs=pvs,
+        pid=(F.PID_E <= 0))
+
+    majoranas2piMu = make_majorana(
+        name='Majo2mupi',
+        pions=pions,
+        leptons=muons,
+        descriptor='[KS0 -> mu- pi+]cc')
+
+    b2EN = make_bhadron_majorana(
+        name='B2MajoE',
+        majoranas=majoranas2piMu,
+        leptons=electrons_with_brem,
+        pvs=pvs,
+        descriptor='[B+ -> KS0 e+]cc')
+
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [majoranas2piMu, b2EN],
+        prescale=prescale)
+
+
+@register_line_builder(all_lines)
+def BpToMajoMu_MajoToEPi_DD_Loose_line(
+        name="Hlt2RD_BpToMajoMu_MajoToEPi_DD_Loose_Line",
+        prescale=1,
+        presistreco=False):
+    pvs = make_pvs
+
+    muons = make_majorana_lepton(
+        leptons=make_long_muons,
+        name='majo_long_muons',
+        pvs=pvs,
+        pt_min=700 * MeV,
+        pid=F.ISMUON)
+
+    down_electrons_without_brem = make_majorana_lepton(
+        leptons=make_down_electrons_no_brem,
+        name='majo_down_electrons_without_brem',
+        pvs=pvs,
+        pt_min=600 * MeV,
+        mipchi2dvprimary_min=None,
+        pid=(F.PID_E > 0.))
+
+    down_pions = make_majorana_lepton(
+        leptons=make_down_pions,
+        name='majo_down_pions',
+        pvs=pvs,
+        pt_min=600 * MeV,
+        mipchi2dvprimary_min=None,
+        pid=(F.PID_E <= 0.))
+
+    majoranas2piE = make_majorana(
+        name='Majo2epi',
+        pions=down_pions,
+        leptons=down_electrons_without_brem,
+        descriptor='[KS0 -> e- pi+]cc')
+
+    b2MuN = make_bhadron_majorana(
+        name='B2MajoMu',
+        majoranas=majoranas2piE,
+        leptons=muons,
+        pvs=pvs,
+        descriptor='[B+ -> KS0 mu+]cc')
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [majoranas2piE, b2MuN],
+        prescale=prescale)
+
+
+@register_line_builder(all_lines)
+def BpToMajoE_MajoToMuPi_DD_Loose_line(
+        name="Hlt2RD_BpToMajoE_MajoToMuPi_DD_Loose_Line",
+        prescale=1,
+        presistreco=False):
+    pvs = make_pvs
+
+    electrons_with_brem = make_majorana_lepton(
+        leptons=make_long_electrons_with_brem,
+        name='majo_long_electrons_with_brem',
+        pvs=pvs,
+        pt_min=700 * MeV,
+        pid=(F.PID_E > 0.))
+
+    down_muons = make_majorana_lepton(
+        leptons=make_down_muons,
+        name='majo_down_muons',
+        pvs=pvs,
+        mipchi2dvprimary_min=None,
+        pt_min=600 * MeV,
+        pid=((F.ISMUON) & (F.PID_MU > 0.)))
+
+    down_pions = make_majorana_lepton(
+        leptons=make_down_pions,
+        name='majo_down_pions',
+        pvs=pvs,
+        pt_min=600 * MeV,
+        mipchi2dvprimary_min=None,
+        pid=(F.PID_E <= 0.))
+
+    majoranas2piMu = make_majorana(
+        name='Majo2mupi',
+        pions=down_pions,
+        leptons=down_muons,
+        descriptor='[KS0 -> mu- pi+]cc',
+    )
+
+    b2EN = make_bhadron_majorana(
+        name='B2MajoE',
+        majoranas=majoranas2piMu,
+        leptons=electrons_with_brem,
+        pvs=pvs,
+        descriptor='[B+ -> KS0 e+]cc')
+
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [majoranas2piMu, b2EN],
+        prescale=prescale)
+
+
+@register_line_builder(all_lines)
+def BuToKs0Pi_Ks0ToPiPi_LL_line(name="Hlt2RD_BuToKs0Pi_Ks0ToPiPi_LL_Line",
+                                prescale=1,
+                                presistreco=False):
+    pvs = make_pvs
+
+    b_pions = make_majorana_lepton(
+        leptons=make_long_pions,
+        name='majo_long_pions',
+        pvs=pvs,
+        pt_min=700 * MeV,
+        pid=(F.PID_E <= 0.))
+    #Here change to make_pvs_v2 when basic_builders are in thor
+    Ks2pipi = basic_builder.filter_neutral_hadrons(make_KsLL_fromSV(),
+                                                   make_pvs_v1())
+
+    b2Ks0Pi = make_bhadron_majorana(
+        name='B2KsPi_LL',
+        majoranas=Ks2pipi,
+        leptons=b_pions,
+        pvs=pvs,
+        am_min=5000.,
+        am_max=5600.,
+        m_min=5100.,
+        m_max=5500.,
+        descriptor='[B+ -> KS0 pi+]cc')
+
+    return Hlt2Line(
+        name=name, algs=rd_prefilter() + [Ks2pipi, b2Ks0Pi], prescale=prescale)
+
+
+@register_line_builder(all_lines)
+def BuToKs0Pi_Ks0ToPiPi_DD_line(name="Hlt2RD_BuToKs0Pi_Ks0ToPiPi_DD_Line",
+                                prescale=1,
+                                presistreco=False):
+    pvs = make_pvs
+
+    long_pions = make_majorana_lepton(
+        leptons=make_long_pions,
+        name='majo_long_pions',
+        pvs=pvs,
+        pt_min=700 * MeV,
+        pid=(F.PID_E <= 0.))
+    #Here change to make_pvs_v2 when basic_builders are in thor
+    Ks2pipi = basic_builder.filter_neutral_hadrons(make_KsDD_fromSV(),
+                                                   make_pvs_v1())
+
+    b2Ks0Pi = make_bhadron_majorana(
+        name='B2KsPi_DD',
+        majoranas=Ks2pipi,
+        leptons=long_pions,
+        pvs=pvs,
+        am_min=5000.,
+        am_max=5600.,
+        m_min=5100.,
+        m_max=5500.,
+        descriptor='[B+ -> KS0 pi+]cc')
+
+    return Hlt2Line(
+        name=name, algs=rd_prefilter() + [Ks2pipi, b2Ks0Pi], prescale=prescale)
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/builders/majorana_builder.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/builders/majorana_builder.py
new file mode 100644
index 0000000000000000000000000000000000000000..35676b2eb665dea5a40d3855970d0fb68170ddb8
--- /dev/null
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/builders/majorana_builder.py
@@ -0,0 +1,110 @@
+###############################################################################
+# (c) Copyright 2019 CERN for the benefit of the LHCb Collaboration           #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+"""
+Definition of exotic majorana neutrino search builders for the B+/Bc+ -> lepton Majorana, where Majorana -> lepton + pion. 
+Builders description:
++ make_majorana_lepton : a default filter for the majorana lepton. TODO: When F.CHILD ready for the DD daughters the pt cut should be loosen and a tighter cut should be applied after vertex fix in make_majorana builder. Leads to a minor correction.
++ make_majorana : a default builder of a majorana candidate. TODO: see comment above
++ make_bhadron_majorana : a default builder of a charged b. TODO: add the IPCHI2 cut, when functor works. 
+
+TO DO:
+    - replace F.BPVDIRA(pvs) by ipchi2
+
+Contacts: Lera Lukashenko valeriia.lukashenk0@cern.ch
+"""
+
+from GaudiKernel.SystemOfUnits import MeV
+import Functors as F
+from Functors.math import in_range
+
+from PyConf import configurable
+
+from Hlt2Conf.lines.rd.builders.rdbuilder_thor import make_filter_tracks
+from Hlt2Conf.algorithms_thor import ParticleCombiner, require_all
+
+
+@configurable
+def make_majorana_lepton(leptons,
+                         pvs,
+                         name="standard_lepton_for_majorana",
+                         pt_min=500 * MeV,
+                         p_min=0 * MeV,
+                         mipchi2dvprimary_min=25.0,
+                         pid=None):
+    """
+    Filter default leptons for HNL
+    """
+    return make_filter_tracks(
+        make_particles=leptons,
+        make_pvs=pvs,
+        name=name,
+        pt_min=pt_min,
+        p_min=p_min,
+        mipchi2dvprimary_min=mipchi2dvprimary_min,
+        pid=pid)
+
+
+@configurable
+def make_majorana(pions,
+                  leptons,
+                  name='Generic_Majorana',
+                  descriptor='',
+                  am_min=200 * MeV,
+                  am_max=7000 * MeV,
+                  adocachi2=16.,
+                  pt_min=700 * MeV,
+                  vtxchi2_max=9.):
+    """
+    Make HNL -> lep +  pi. 
+    """
+    combination_code = require_all(
+        in_range(am_min, F.MASS, am_max), F.MAXDOCACHI2CUT(adocachi2))
+    majorana_code = require_all(F.PT > pt_min, F.CHI2 < vtxchi2_max)
+
+    return ParticleCombiner([leptons, pions],
+                            name=name,
+                            DecayDescriptor=descriptor,
+                            CombinationCut=combination_code,
+                            CompositeCut=majorana_code)
+
+
+@configurable
+def make_bhadron_majorana(majoranas,
+                          leptons,
+                          pvs,
+                          name='Generic_B_2_Majorana',
+                          descriptor='',
+                          am_min=4300 * MeV,
+                          am_max=7200 * MeV,
+                          m_min=4500 * MeV,
+                          m_max=6800 * MeV,
+                          adocachi2=25.,
+                          vtxchi2_max=9.,
+                          mipchi2_max=16.,
+                          bpvdls_min=4.,
+                          dira_min=0.):
+    """
+    Make B-> lep + HNL
+    """
+    #majoranas = make_majorana()
+    #leptons = make_majorana()
+    combination_code = require_all(
+        in_range(am_min, F.MASS, am_max), F.MAXDOCACHI2CUT(adocachi2))
+    b_code = require_all(
+        in_range(m_min, F.MASS, m_max),
+        F.BPVDLS(pvs()) > bpvdls_min, F.CHI2 < vtxchi2_max,
+        F.BPVDIRA(pvs()) > dira_min,
+        F.MINIPCHI2(pvs()) < mipchi2_max)
+    return ParticleCombiner([majoranas, leptons],
+                            name=name,
+                            DecayDescriptor=descriptor,
+                            CombinationCut=combination_code,
+                            CompositeCut=b_code)
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/builders/rdbuilder_thor.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/builders/rdbuilder_thor.py
index bab1df1a41cb6f08f678ac12b9fbf32775ca0af9..465bdbab8157a428d74ca3db1f32fca74efe75a8 100644
--- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/builders/rdbuilder_thor.py
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/builders/rdbuilder_thor.py
@@ -934,21 +934,21 @@ def make_rd_prompt_mue(
         p_min=p_muon_min,
         pid=pid_muon)
 
-    muons = make_rd_prompt_electrons(
-        name="rd_prompt_electrons_for" + name,
+    electrons = make_rd_prompt_electrons(
+        #name="rd_prompt_electrons_for" + name,
         pt_min=pt_electron_min,
         p_min=p_electron_min,
         pid=pid_electron)
 
-    DecayDescriptor = f'{parent_id} -> e+ mu-'
-    if same_sign: DecayDescriptor = f'[{parent_id} -> e+ mu+]cc'
+    DecayDescriptor = f'{parent_id} -> mu- e+'
+    if same_sign: DecayDescriptor = f'[{parent_id} -> mu+ e+]cc'
 
     combination_code = require_all(
         in_range(am_min, F.MASS, am_max), F.PT > pt_dilepton_min,
         F.MAXDOCACHI2CUT(adocachi2cut_max))
     #pvs = make_pvs()
     vertex_code = require_all(F.CHI2DOF < vchi2pdof_max)
-    return ParticleCombiner([muons, muons],
+    return ParticleCombiner([muons, electrons],
                             name=name + "_combiner",
                             DecayDescriptor=DecayDescriptor,
                             CombinationCut=combination_code,
@@ -1030,6 +1030,7 @@ def make_rd_detached_dielectron(name="rd_detached_dielectron",
 
 @configurable
 def make_rd_detached_mue(name="rd_detached_mue",
+                         min_dilepton_mass=0. * MeV,
                          max_dilepton_mass=6000. * MeV,
                          parent_id='J/psi(1S)',
                          min_probnn_mu=0.,
@@ -1047,7 +1048,7 @@ def make_rd_detached_mue(name="rd_detached_mue",
     dileptons = make_detached_mue_with_brem(
         dilepton_ID=parent_id,
         min_probnn_mu=min_probnn_mu,
-        min_PIDmu=0.,
+        min_PIDmu=min_PIDmu,
         IsMuon=False,
         min_PIDe=min_PIDe,
         same_sign=same_sign,
@@ -1055,7 +1056,7 @@ def make_rd_detached_mue(name="rd_detached_mue",
         min_pt_mu=min_pt_mu,
         min_bpvvdchi2=min_bpvvdchi2,
         max_vchi2ndof=max_vchi2ndof)
-    code = require_all(F.MASS < max_dilepton_mass)
+    code = require_all(in_range(min_dilepton_mass, F.MASS, max_dilepton_mass))
     return ParticleFilter(dileptons, F.FILTER(code), name=name)
 
 
@@ -1101,11 +1102,11 @@ def make_rd_tauons_hadronic_decay(
     pvs = make_pvs()
     combination_code = require_all(
         in_range(am_min, F.MASS, am_max),
-        F.SUBCOMB(Functor=(F.MASS < am_2pi_max), Indices=[1, 3]),
+        F.SUBCOMB(Functor=(F.MASS < am_2pi_max), Indices=(1, 3)),
         # F.DOCA(1, 3) < adoca_max,
         # F.DOCA(2, 3) < adoca_max,
-        F.SUBCOMB(Functor=F.MAXDOCACHI2CUT(adocachi2_max), Indices=[2, 3]),
-        F.SUBCOMB(Functor=F.MAXDOCACHI2CUT(adocachi2_max), Indices=[1, 3]),
+        F.SUBCOMB(Functor=F.MAXDOCACHI2CUT(adocachi2_max), Indices=(2, 3)),
+        F.SUBCOMB(Functor=F.MAXDOCACHI2CUT(adocachi2_max), Indices=(1, 3)),
         F.SUM(F.PT > best_pi_pt_min) > 1,
         F.SUM(F.MINIPCHI2(pvs) > best_pi_ipchi2_min) > 1,
     )
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/qqbar_to_ll.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/qqbar_to_ll.py
new file mode 100644
index 0000000000000000000000000000000000000000..1d78e430d583e986e56162c2c24958d404d9e9a9
--- /dev/null
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/qqbar_to_ll.py
@@ -0,0 +1,360 @@
+##############################################################################
+# (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration           #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+"""
+Definiton of LFV lines of qqbar -> emu
+- Phi(1020) -> E Mu + SS prompt
+- Phi(1020) -> E Mu + SS detached
+- J/Psi(1S) -> E Mu + SS prompt
+- J/Psi(1S) -> E Mu + SS detached
+- Upsilon(1S) -> E Mu + SS prompt only
+
+Control channels:
+- Phi(1020) -> E E prompt
+- J/Psi(1S) -> E E prompt
+- Upsilon(1S) -> E E prompt
+
+author: Miroslav Saur
+date: 27.12.2021
+
+"""
+
+from GaudiKernel.SystemOfUnits import MeV, GeV
+from PyConf import configurable
+from Moore.config import register_line_builder
+from Moore.lines import Hlt2Line
+from Hlt2Conf.lines.rd.builders.rdbuilder_thor import make_rd_detached_mue, make_rd_prompt_mue, make_rd_prompt_dielectrons  #make_rd_prompt_dimuons
+from Hlt2Conf.lines.rd.builders.rd_prefilters import rd_prefilter
+from Hlt2Conf.algorithms_thor import require_all
+import Functors as F
+
+all_lines = {}
+
+###### PROMPT LINES #####
+
+
+@register_line_builder(all_lines)
+@configurable
+def phi_to_mue_line(name="Hlt2RD_PhiToMuE_Line",
+                    prescale=0.01,
+                    persistreco=False):
+    """
+    Definiton of [phi(1020) -> mu- e+]CC
+    """
+    emu = make_rd_prompt_mue(
+        name="Hlt2RD_PhiToMuE_Builder",
+        parent_id='phi(1020)',
+        am_min=850. * MeV,  #850
+        am_max=1170. * MeV,  #1220
+        pt_dilepton_min=0.5 * GeV,
+        pid_muon=require_all(F.ISMUON, F.PID_MU > 3.),
+        same_sign=False)
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [emu],
+        prescale=prescale,
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+@configurable
+def phi_to_mue_ss_line(name="Hlt2RD_PhiToMuE_SS_Line",
+                       prescale=0.001,
+                       persistreco=False):
+    emu_SS = make_rd_prompt_mue(
+        name="Hlt2RD_PhiToMuE_SS_Builder",
+        parent_id='phi(1020)',
+        am_min=850. * MeV,
+        am_max=1170. * MeV,
+        pt_dilepton_min=0.5 * GeV,
+        pid_muon=require_all(F.ISMUON, F.PID_MU > 3.),
+        same_sign=True)
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [emu_SS],
+        prescale=prescale,
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+@configurable
+def jpsi_to_mue_line(name="Hlt2RD_JpsiToMuE_Line",
+                     prescale=1,
+                     persistreco=False):
+
+    emu = make_rd_prompt_mue(
+        name="Hlt2RD_JpsiToMuE_Builder",
+        parent_id='J/psi(1S)',
+        am_min=2700. * MeV,
+        am_max=3400. * MeV,
+        pt_dilepton_min=2.5 * GeV,
+        pt_electron_min=1.0 * GeV,
+        pt_muon_min=1.0 * GeV,
+        pid_muon=require_all(F.ISMUON, F.PID_MU > 3.))
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [emu],
+        prescale=prescale,
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+@configurable
+def jpsi_to_mue_ss_line(name="Hlt2RD_JpsiToMuE_SS_Line",
+                        prescale=0.1,
+                        persistreco=False):
+
+    emu = make_rd_prompt_mue(
+        name="Hlt2RD_JpsiToMuE_SS_Builder",
+        parent_id='J/psi(1S)',
+        am_min=2700. * MeV,
+        am_max=3400. * MeV,
+        pt_dilepton_min=2.5 * GeV,
+        pt_electron_min=1.0 * GeV,
+        pt_muon_min=1.0 * GeV,
+        pid_muon=require_all(F.ISMUON, F.PID_MU > 3.),
+        same_sign=True)
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [emu],
+        prescale=prescale,
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+@configurable
+def upsilon_to_mue_line(name="Hlt2RD_UpsilonToMuE_Line",
+                        prescale=1,
+                        persistreco=False):
+
+    emu = make_rd_prompt_mue(
+        name="Hlt2RD_UpsilonToMuE_Builder",
+        parent_id='Upsilon(1S)',
+        am_min=8000. * MeV,
+        am_max=12000. * MeV,
+        pt_dilepton_min=2.0 * GeV,
+        pt_electron_min=1.0 * GeV,
+        pt_muon_min=1.0 * GeV,
+        pid_muon=require_all(F.ISMUON, F.PID_MU > 3.),
+        same_sign=False)
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [emu],
+        prescale=prescale,
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+@configurable
+def upsilon_to_mue_ss_line(name="Hlt2RD_UpsilonToMuE_SS_Line",
+                           prescale=1,
+                           persistreco=False):
+
+    emu = make_rd_prompt_mue(
+        name="Hlt2RD_UpsilonToMuE_SS_Builder",
+        parent_id='Upsilon(1S)',
+        am_min=8000. * MeV,
+        am_max=12000. * MeV,
+        pt_dilepton_min=2.0 * GeV,
+        pt_electron_min=1.0 * GeV,
+        pt_muon_min=1.0 * GeV,
+        pid_muon=require_all(F.ISMUON, F.PID_MU > 3.),
+        same_sign=True)
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [emu],
+        prescale=prescale,
+        persistreco=persistreco)
+
+
+##### DETACHED LINES #####
+
+
+@register_line_builder(all_lines)
+@configurable
+def phi_to_mue_detached_line(name="Hlt2RD_PhiToMuE_Detached_Line",
+                             prescale=0.1,
+                             persistreco=False):
+    """
+    Definiton of [phi(1020) -> mu- e+]CC
+    """
+    emu = make_rd_detached_mue(
+        name="Hlt2RD_PhiToMuE_detached_Builder",
+        parent_id='phi(1020)',
+        min_dilepton_mass=800. * MeV,
+        max_dilepton_mass=1170. * MeV,
+        min_probnn_mu=0.,
+        min_pt_e=0.4 * GeV,
+        min_pt_mu=0.4 * GeV,
+        min_bpvvdchi2=30.,
+        max_vchi2ndof=4.,
+        min_PIDmu=3,
+        IsMuon=True,
+    )
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [emu],
+        prescale=prescale,
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+@configurable
+def phi_to_mue_ss_detached_line(name="Hlt2RD_PhiToMuE_SS_Detached_Line",
+                                prescale=0.05,
+                                persistreco=False):
+    """
+    Definiton of [phi(1020) -> mu+ e+]CC
+    """
+    emu = make_rd_detached_mue(
+        name="Hlt2RD_PhiToMuE_SS_detached_Builder",
+        parent_id='phi(1020)',
+        min_dilepton_mass=800. * MeV,
+        max_dilepton_mass=1170. * MeV,
+        min_probnn_mu=0.,
+        min_pt_e=0.4 * GeV,
+        min_pt_mu=0.4 * GeV,
+        min_bpvvdchi2=30.,
+        max_vchi2ndof=4.,
+        min_PIDmu=3,
+        IsMuon=True,
+        same_sign=True)
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [emu],
+        prescale=prescale,
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+@configurable
+def jpsi_to_mue_detached_line(name="Hlt2RD_JpsiToMuE_Detached_Line",
+                              prescale=1,
+                              persistreco=False):
+    """
+    Definiton of [J/psi(1S) -> mu- e+]CC
+    """
+    emu = make_rd_detached_mue(
+        name="Hlt2RD_JpsiToMuE_detached_Builder",
+        parent_id='J/psi(1S)',
+        min_dilepton_mass=2700. * MeV,
+        max_dilepton_mass=2400. * MeV,
+        min_probnn_mu=0.,
+        min_pt_e=1. * GeV,
+        min_pt_mu=1. * GeV,
+        min_bpvvdchi2=30.,
+        max_vchi2ndof=4.,
+        min_PIDmu=3,
+        IsMuon=True,
+    )
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [emu],
+        prescale=prescale,
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+@configurable
+def jpsi_to_mue_ss_detached_line(name="Hlt2RD_JpsiToMuE_SS_Detached_Line",
+                                 prescale=1,
+                                 persistreco=False):
+    """
+    Definiton of [J/psi(1S) -> mu+ e+]CC
+    """
+    emu = make_rd_detached_mue(
+        name="Hlt2RD_JpsiToMuE_SS_deached_Builder",
+        parent_id='J/psi(1S)',
+        min_dilepton_mass=2700. * MeV,
+        max_dilepton_mass=3400. * MeV,
+        min_probnn_mu=0.,
+        min_pt_e=0.5 * GeV,
+        min_pt_mu=0.5 * GeV,
+        min_bpvvdchi2=30.,
+        max_vchi2ndof=4.,
+        min_PIDmu=3,
+        IsMuon=True,
+        same_sign=True)
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [emu],
+        prescale=prescale,
+        persistreco=persistreco)
+
+
+##### CONTROL ee LINES #####
+
+
+@register_line_builder(all_lines)
+@configurable
+def phi_to_ee_line(name="Hlt2RD_PhiToEE_Line",
+                   prescale=0.01,
+                   persistreco=False):
+    emu = make_rd_prompt_dielectrons(
+        name="Hlt2RD_PhiToMuE_SS_Builder",
+        parent_id='phi(1020)',
+        same_sign=False,
+        PIDe_min=2.,
+        pt_e_min=1.5 * GeV,
+        min_dilepton_pt=2.0 * GeV,
+        min_dilepton_mass=850 * MeV,
+        max_dilepton_mass=1170 * MeV)
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [emu],
+        prescale=prescale,
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+@configurable
+def jpsi_to_ee_line(name="Hlt2RD_JpsiToEE_Line",
+                    prescale=0.001,
+                    persistreco=False):
+    emu = make_rd_prompt_dielectrons(
+        name="Hlt2RD_JpsiToEE_Builder",
+        parent_id='J/psi(1S)',
+        same_sign=False,
+        PIDe_min=2.,
+        pt_e_min=0.5 * GeV,
+        min_dilepton_pt=1.0 * GeV,
+        min_dilepton_mass=2700 * MeV,
+        max_dilepton_mass=3400 * MeV)
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [emu],
+        prescale=prescale,
+        persistreco=persistreco)
+
+
+@register_line_builder(all_lines)
+@configurable
+def upsilon_to_ee_line(name="Hlt2RD_UpsilonToEE_Line",
+                       prescale=0.1,
+                       persistreco=False):
+    emu = make_rd_prompt_dielectrons(
+        name="Hlt2RD_UpsilonToEE_Builder",
+        parent_id='Upsilon(1S)',
+        same_sign=False,
+        PIDe_min=2.,
+        pt_e_min=1. * GeV,
+        min_dilepton_pt=2.5 * GeV,
+        min_dilepton_mass=8000 * MeV,
+        max_dilepton_mass=12000 * MeV)
+    return Hlt2Line(
+        name=name,
+        algs=rd_prefilter() + [emu],
+        prescale=prescale,
+        persistreco=persistreco)
+
+
+#################
+## END OF FILE ##
+#################
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/semileptonic/builders/base_builder.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/semileptonic/builders/base_builder.py
index ca7155e9ccdd746cca2bf1fd2aed583807ac4872..1f218c170544fa1eb4760107e6410d2b7543efda 100644
--- a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/semileptonic/builders/base_builder.py
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/semileptonic/builders/base_builder.py
@@ -400,7 +400,7 @@ def make_tauons_hadronic_decay(make_pvs=make_pvs,
     pvs = make_pvs()
     combination_code = require_all(
         in_range(comb_m_min, F.MASS, comb_m_max), F.MAXDOCACUT(comb_doca_max),
-        F.SUBCOMB(Functor=F.MASS < twobody_m_max, Indices=[1, 3]))
+        F.SUBCOMB(Functor=F.MASS < twobody_m_max, Indices=(1, 3)))
 
     if mipchi2:
         combination_code = require_all(combination_code,
diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/standard_particles.py b/Hlt/Hlt2Conf/python/Hlt2Conf/standard_particles.py
index fc47e583d861eec99a86fa8e475d72591685a0f5..f406fb2a131f4ea4b7f0e311d0ae3e7333addeec 100644
--- a/Hlt/Hlt2Conf/python/Hlt2Conf/standard_particles.py
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/standard_particles.py
@@ -328,6 +328,20 @@ def make_down_protons():
         make_protoparticle_filter=standard_protoparticle_filter)
 
 
+def make_down_electrons_no_brem():
+    return _make_particles(
+        species="electron",
+        get_track_selector=get_down_track_selector,
+        make_protoparticle_filter=standard_protoparticle_filter)
+
+
+def make_down_muons():
+    return _make_particles(
+        species="muon",
+        get_track_selector=get_down_track_selector,
+        make_protoparticle_filter=standard_protoparticle_filter)
+
+
 @configurable
 def make_phi2kk(am_max=1100. * MeV, adoca_chi2=30, vchi2=25.0):
     kaons = make_long_kaons()
@@ -354,6 +368,11 @@ def _make_down_for_V0(particles):
     return ParticleFilter(particles, Code=code)
 
 
+def _make_up_for_V0(particles):
+    code = require_all("P>1000*MeV", "PT > 175.*MeV")
+    return ParticleFilter(particles, Code=code)
+
+
 def make_long_pions_for_V0():
     return _make_long_for_V0(make_long_pions(), _make_pvs())
 
@@ -370,6 +389,10 @@ def make_down_protons_for_V0():
     return _make_down_for_V0(make_down_protons())
 
 
+def make_up_pions_for_V0():
+    return _make_up_for_V0(make_up_pions())
+
+
 @configurable
 def _make_V0LL(particles,
                descriptors,
@@ -384,13 +407,21 @@ def _make_V0LL(particles,
     """
     combination_code = require_all("ADAMASS('{pname}') < {am_dmass}").format(
         pname=pname, am_dmass=am_dmass)
-    vertex_code = require_all("ADMASS('{pname}')<{m_dmass}",
-                              "CHI2VXNDOF<{vchi2pdof_max}",
-                              "BPVLTIME() > {bpvltime_min}").format(
-                                  pname=pname,
-                                  m_dmass=m_dmass,
-                                  vchi2pdof_max=vchi2pdof_max,
-                                  bpvltime_min=bpvltime_min)
+    if bpvltime_min is not None:
+        vertex_code = require_all("ADMASS('{pname}')<{m_dmass}",
+                                  "CHI2VXNDOF<{vchi2pdof_max}",
+                                  "BPVLTIME() > {bpvltime_min}").format(
+                                      pname=pname,
+                                      m_dmass=m_dmass,
+                                      vchi2pdof_max=vchi2pdof_max,
+                                      bpvltime_min=bpvltime_min)
+    else:
+        vertex_code = require_all("ADMASS('{pname}')<{m_dmass}",
+                                  "CHI2VXNDOF<{vchi2pdof_max}").format(
+                                      pname=pname,
+                                      m_dmass=m_dmass,
+                                      vchi2pdof_max=vchi2pdof_max)
+
     return ParticleCombinerWithPVs(
         particles=particles,
         pvs=pvs,
@@ -421,6 +452,35 @@ def _make_V0DD(particles,
                                   m_max=m_max,
                                   vchi2pdof_max=vchi2pdof_max,
                                   bpvvdz_min=bpvvdz_min)
+
+    return ParticleCombinerWithPVs(
+        particles=particles,
+        pvs=pvs,
+        DecayDescriptors=descriptors,
+        CombinationCut=combination_code,
+        MotherCut=vertex_code)
+
+
+@configurable
+def _make_V0LD_UL(particles,
+                  descriptors,
+                  pvs,
+                  am_min=_KAON0_M - 80 * MeV,
+                  am_max=_KAON0_M + 80 * MeV,
+                  m_min=_KAON0_M - 64 * MeV,
+                  m_max=_KAON0_M + 64 * MeV,
+                  vchi2pdof_max=30):
+    """Make long-down or long-up V0 -> h+ h'- candidates
+    Initial implementation a replication of the _make_V0DD function without
+    the BPVVDZ() requirement
+    """
+    combination_code = require_all("in_range({am_min},  AM, {am_max})").format(
+        am_min=am_min, am_max=am_max)
+    vertex_code = require_all("in_range({m_min},  M, {m_max})",
+                              "CHI2VXNDOF<{vchi2pdof_max}").format(
+                                  m_min=m_min,
+                                  m_max=m_max,
+                                  vchi2pdof_max=vchi2pdof_max)
     return ParticleCombinerWithPVs(
         particles=particles,
         pvs=pvs,
@@ -429,21 +489,69 @@ def _make_V0DD(particles,
         MotherCut=vertex_code)
 
 
-def make_KsLL():
+def make_KsLL(pions_long=None):
+    if pions_long is None:
+        pions_long = make_long_pions_for_V0()
+    descriptors = ["KS0 -> pi+ pi-"]
+    return _make_V0LL(
+        particles=[pions_long],
+        descriptors=descriptors,
+        pname='KS0',
+        pvs=_make_pvs())
+
+
+def make_KsDD(pions_down=None):
+    if pions_down is None:
+        pions_down = make_down_pions_for_V0()
+    descriptors = ["KS0 -> pi+ pi-"]
+    return _make_V0DD(
+        particles=[pions_down], descriptors=descriptors, pvs=_make_pvs())
+
+
+def make_KsLD(pions_down=None, pions_long=None):
+    if pions_down is None:
+        pions_down = make_down_pions_for_V0()
+    if pions_long is None:
+        pions_long = make_long_pions_for_V0()
+    descriptors = ["KS0 -> pi+ pi-"]
+    return _make_V0LD_UL(
+        particles=[pions_long, pions_down],
+        descriptors=descriptors,
+        pvs=_make_pvs())
+
+
+def make_KsUL(pions_long=None, pions_up=None):
+    if pions_up is None:
+        pions_up = make_up_pions_for_V0()
+    if pions_long is None:
+        pions_long = make_long_pions_for_V0()
+    descriptors = ["KS0 -> pi+ pi-"]
+    return _make_V0LD_UL(
+        particles=[pions_long, pions_up],
+        descriptors=descriptors,
+        pvs=_make_pvs())
+
+
+def make_KsLL_fromSV():
     pions = make_long_pions_for_V0()
     descriptors = ["KS0 -> pi+ pi-"]
     return _make_V0LL(
         particles=[pions],
         descriptors=descriptors,
         pname='KS0',
-        pvs=_make_pvs())
+        pvs=_make_pvs(),
+        vchi2pdof_max=25.0,
+        bpvltime_min=None)
 
 
-def make_KsDD():
+def make_KsDD_fromSV():
     pions = make_down_pions_for_V0()
     descriptors = ["KS0 -> pi+ pi-"]
     return _make_V0DD(
-        particles=[pions], descriptors=descriptors, pvs=_make_pvs())
+        particles=[pions],
+        descriptors=descriptors,
+        pvs=_make_pvs(),
+        vchi2pdof_max=25.0)
 
 
 def make_LambdaLL():
@@ -761,7 +869,7 @@ def make_detached_mue_with_brem(same_sign=False,
                                 min_bpvvdchi2=30,
                                 max_vchi2ndof=10):
     """Make detached J/psi(1S) -> mu e candidates with ismuon muons and adding bremsstrahlung correction to the
-    electrons. The same_sign flag is a boolean that can be activated. 
+    electrons. The same_sign flag is a boolean that can be activated.
     """
     muons = make_ismuon_long_muon()
     electrons = make_long_electrons_with_brem()
diff --git a/Hlt/Hlt2Conf/tests/options/hlt2_thor_selections.py b/Hlt/Hlt2Conf/tests/options/hlt2_thor_selections.py
index d26b8a13347049ec0f5798890d2945ad2cd09e26..ed40c234f903aac965589454a1d7b28ae3834c60 100644
--- a/Hlt/Hlt2Conf/tests/options/hlt2_thor_selections.py
+++ b/Hlt/Hlt2Conf/tests/options/hlt2_thor_selections.py
@@ -60,8 +60,8 @@ def make_lines():
         DecayDescriptor="D0 -> KS0 pi+ pi-",
         Combination12Cut=F.MAXDOCACHI2CUT(10.),
         CombinationCut=require_all(
-            F.SUBCOMB(Functor=F.MAXDOCACHI2CUT(10.), Indices=[2, 3]),
-            F.SUBCOMB(Functor=F.MAXDOCACHI2CUT(10.), Indices=[1, 3]),
+            F.SUBCOMB(Functor=F.MAXDOCACHI2CUT(10.), Indices=(2, 3)),
+            F.SUBCOMB(Functor=F.MAXDOCACHI2CUT(10.), Indices=(1, 3)),
             in_range(1500 * MeV, F.MASS, 2500 * MeV),
             F.MAXDOCACHI2CUT(16.),
         ),
diff --git a/Hlt/Hlt2Conf/tests/options/sprucing/spruce_all_lines_analytics.py b/Hlt/Hlt2Conf/tests/options/sprucing/spruce_all_lines_analytics.py
new file mode 100644
index 0000000000000000000000000000000000000000..24f0b08496328738d8f890aee6be7cf5557d5c5f
--- /dev/null
+++ b/Hlt/Hlt2Conf/tests/options/sprucing/spruce_all_lines_analytics.py
@@ -0,0 +1,147 @@
+###############################################################################
+# (c) Copyright 2022 CERN for the benefit of the LHCb Collaboration           #
+#                                                                             #
+# This software is distributed under the terms of the GNU General Public      #
+# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
+#                                                                             #
+# In applying this licence, CERN does not waive the privileges and immunities #
+# granted to it by virtue of its status as an Intergovernmental Organization  #
+# or submit itself to any jurisdiction.                                       #
+###############################################################################
+"""
+Run with
+`./run gaudirun.py spruce_all_lines_analytics.py`
+
+Performs event size analytics on Sprucing events by exploiting the fact that each
+stream gets its own instance of `CombineRawBankViewsToRawEvent`.
+
+-Make each Sprucing line its own stream.
+-Report size of DstData RawBank (contains the physics and reconstruction objects) and
+ total event size where the event contains the RawBanks defined in `banks` in this options file
+-Will not produce output files through use of `stream_writer.bind(write=False)`.
+-In log will see StatCounter with name of line
+
+LineName...    INFO Number of counters : X
+ |    Counter                                      |     #     |    sum | mean/eff^* | rms/err^*  |     min   |     max    |
+ | "DstData bank size (bytes)"                     |         X |      Y |         YY |     YYY    |      YYYY |      YYYYY |
+ | "Event size (bytes)"                            |         X |      Z |         ZZ |     ZZZ    |      ZZZZ |      ZZZZZ |
+
+
+Note that by running `CombineRawBankViewsToRawEvent` in VERBOSE mode - achieved through
+`CombineRawBankViewsToRawEvent.bind(OutputLevel=1)` one also has the log of the sizes of ALL RawBanks in `banks`.
+
+Runs Sprucing over HLT1 filtered Min bias sample that has been processed by TOPO{2, 3} HLT2 lines - 478 events.
+If you do not see this for your line then your line did not fire on any event in the input data.
+
+Eventually we should have a test like this over each stream as that will define `banks` and hence the appropriate
+event size. At the moment this script runs over ALL Sprucing lines and analyses ALL RawBanks so the event size contains
+everything.
+
+"""
+
+import json
+from Moore import options, run_moore
+from Moore.config import stream_writer
+from PyConf.Algorithms import CombineRawBankViewsToRawEvent
+from RecoConf.global_tools import stateProvider_with_simplified_geom
+from RecoConf.reconstruction_objects import reconstruction
+from Hlt2Conf.lines import sprucing_lines
+
+import XRootD.client
+from Configurables import HltANNSvc
+import re
+
+from Moore.streams_hlt2 import DETECTOR_RAW_BANK_TYPES, HLT1_REPORT_RAW_BANK_TYPES, HLT2_REPORT_RAW_BANK_TYPES
+import Moore.streams_spruce
+
+
+## Return HltANNSvc when tck is on eos
+def tck_from_eos(url):
+    with XRootD.client.File() as f:
+        status, _ = f.open(url)
+        if not status.ok:
+            raise RuntimeError(f"could not open {url}: {status.message}")
+        status, data = f.read()
+        if not status.ok:
+            raise RuntimeError(f"could not read {url}: {status.message}")
+    dict = json.loads(data.decode('utf-8'))
+    ann_config = dict["HltANNSvc/HltANNSvc"]
+    packed_object_locs = {
+        str(k): v
+        for k, v in ann_config["PackedObjectLocations"].items()
+    }
+    hlt2_sel_ids = {
+        str(k): v
+        for k, v in ann_config["Hlt2SelectionID"].items()
+    }
+
+    return HltANNSvc(
+        "HltANNSvcReading",
+        Hlt2SelectionID=hlt2_sel_ids,
+        PackedObjectLocations=packed_object_locs,
+    )
+
+
+## Configure `HltANNSvc`
+url = 'root://eoslhcb.cern.ch//eos/lhcb/wg/rta/samples/mc/Hlt1Hlt2filtered_MinBias_sprucing/hlt2_2or3bodytopo_realtime.tck.json'
+tck_from_eos(url)
+
+##Run over HLT1 filtered Min bias sample that has been processed by TOPO{2, 3} HLT2 lines.
+##To produce this see `Hlt/Hlt2Conf/options/Sprucing/hlt2_2or3bodytopo_realtime.py`
+input_files = [
+    'mdf:root://eoslhcb.cern.ch//eos/lhcb/wg/rta/samples/mc/Hlt1Hlt2filtered_MinBias_sprucing/hlt2_2or3bodytopo_realtime.mdf'
+]
+
+options.input_raw_format = 0.3
+options.input_files = input_files
+options.input_type = 'MDF'
+
+options.evt_max = -1
+options.simulation = True
+options.data_type = 'Upgrade'
+options.dddb_tag = 'dddb-20171126'
+options.conddb_tag = 'sim-20171127-vc-md100'
+options.monitoring_file = "monitoring.json"
+
+#Note output will be produced but for other reasons an `output_file` must be declared
+options.output_file = 'dummy.{stream}.dst'
+options.output_type = 'ROOT'
+
+# Create new dictionary based on `sprucing_lines` with "readable" line names:
+# SpruceRD_LbToKpTauE_TauTo3Pi_OS_Line -> RD_LbToKpTauE_TauTo3Pi_OS
+streamdict = {}
+for k, v in sprucing_lines.items():
+    try:
+        wg, name = re.search('Spruce(.+?)_', k).group(1), re.search(
+            '_(.+?)_Line', k).group(1)
+    except AttributeError:
+        wg, name = re.search('Spruce(.+?)_', k).group(1), re.search(
+            '_(.+?)Line', k).group(1)
+
+    streamdict[wg + "_" + name] = [v]
+
+
+def make_streams():
+    "Makes each line its own stream"
+    dict = {}
+    for k, v in streamdict.items():
+        # v can only contain one element
+        dict[k] = [v[0]()]
+
+    return dict
+
+
+##Must declare "new" streams (one for each line) and the RawBanks you wish to analyse
+banks = set.union(DETECTOR_RAW_BANK_TYPES, HLT1_REPORT_RAW_BANK_TYPES,
+                  HLT2_REPORT_RAW_BANK_TYPES)
+Moore.streams_spruce.stream_banks = {
+    k: [i for i in banks]
+    for k in streamdict.keys()
+}
+
+public_tools = [stateProvider_with_simplified_geom()]
+
+with reconstruction.bind(
+        from_file=True, spruce=True), stream_writer.bind(
+            write=False), CombineRawBankViewsToRawEvent.bind(OutputLevel=4):
+    config = run_moore(options, make_streams, public_tools)
diff --git a/Hlt/Hlt2Conf/tests/options/thor/loki_comparison.py b/Hlt/Hlt2Conf/tests/options/thor/loki_comparison.py
index d8496f0fd3347fcdd51ee83682527ed67afefa81..fa50ced5256d478e3224de5d7d2143872b2fc63f 100644
--- a/Hlt/Hlt2Conf/tests/options/thor/loki_comparison.py
+++ b/Hlt/Hlt2Conf/tests/options/thor/loki_comparison.py
@@ -222,7 +222,7 @@ def make_lines():
         "ETA": (F.ETA > 3.45, "ETA > 3.45"),
         "MASS": (F.MASS > 3 * GeV, "M > 3 * GeV"),
         #"MASSWITHHYPOTHESES":
-        #(F.MASSWITHHYPOTHESES(Masses=[135., 135., 450.]) > 3.5 * GeV,
+        #(F.MASSWITHHYPOTHESES(Masses=(135., 135., 450.)) > 3.5 * GeV,
         #"WMASS(135.,135.,450.) > 3.5 * GeV"),#ThOr functor works fine here, but Loki implementation does not, so removing from tests
     }
     vertex_lines = []
diff --git a/Hlt/Hlt2Conf/tests/qmtest/sprucing.qms/test_spruce_all_lines_analytics.qmt b/Hlt/Hlt2Conf/tests/qmtest/sprucing.qms/test_spruce_all_lines_analytics.qmt
new file mode 100644
index 0000000000000000000000000000000000000000..adc63f328659ee5223c117aecd8ebb2d6c0e65ce
--- /dev/null
+++ b/Hlt/Hlt2Conf/tests/qmtest/sprucing.qms/test_spruce_all_lines_analytics.qmt
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE extension  PUBLIC '-//QM/2.3/Extension//EN'  'http://www.codesourcery.com/qm/dtds/2.3/-//qm/2.3/extension//en.dtd'>
+<!--
+    (c) Copyright 2022 CERN for the benefit of the LHCb Collaboration
+
+    This software is distributed under the terms of the GNU General Public
+    Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".
+
+    In applying this licence, CERN does not waive the privileges and immunities
+    granted to it by virtue of its status as an Intergovernmental Organization
+    or submit itself to any jurisdiction.
+-->
+<!--
+Run event size analysis on all sprucing lines
+
+Runs all sprucing lines on output of {2, 3}body topo lines run using real time reco over HLT1 filtered Min bias sample
+
+Input stored on eos
+-->
+<extension class="GaudiTest.GaudiExeTest" kind="test">
+<argument name="program"><text>gaudirun.py</text></argument>
+<argument name="timeout"><integer>3000</integer></argument>
+<argument name="args"><set>
+  <text>$HLT2CONFROOT/tests/options/sprucing/spruce_all_lines_analytics.py</text>
+</set></argument>
+<argument name="use_temp_dir"><enumeral>true</enumeral></argument>
+<argument name="validator"><text>
+
+from Moore.qmtest.exclusions import remove_known_warnings
+countErrorLines({"FATAL": 0, "WARNING": 0, "ERROR": 0},
+                stdout=remove_known_warnings(stdout))
+
+import re
+import json
+
+def log_results(table):
+    longest_line = len(
+        max([table[i][0] for i in range(0, len(table))], key=len))
+    longest_dstdata = len(
+        max([str(table[i][1]) for i in range(0, len(table))], key=len))
+    longest_evtsize = len(
+        max([str(table[i][2]) for i in range(0, len(table))], key=len))
+
+    print("Results: ")
+    print("=" * (longest_line + longest_dstdata + longest_evtsize))
+    for match in table:
+        (line, dstdata, evtsize) = match
+        print(
+            f"{line:{longest_line}} | {dstdata:{longest_dstdata}} | {evtsize:{longest_evtsize}}"
+        )
+    print("=" * (longest_line + longest_dstdata + longest_evtsize))
+
+
+if not os.path.isfile("monitoring.json"):
+    causes.append("monitoring.json was not produced")
+
+with open("monitoring.json") as f:
+    data = json.load(f)
+
+##There are nicer ways to do the following in python but the qmt testing does not like it
+names = []
+dstdata = []
+totdata = []
+
+for name in data:
+    if name.startswith('EvtSize_') and not data[name]['DstData bank size (bytes)']['empty']:
+        names.append(name)
+
+for name in names:
+    dstdata.append(data[name]['DstData bank size (bytes)']['mean'])
+    totdata.append(data[name]['Event size (bytes)']['mean'])
+
+table_headers = [("Line", "Av. DstData Rawbank size (bytes)", "Av. total event size (bytes)")]
+
+table = []
+for i in range(0, len(names)):
+    table.append((names[i][8:], dstdata[i], totdata[i]))
+
+log_results(table_headers + table)
+
+# In this test we are running over approx. 5000 HLT1-filtered events that are additionaly
+# filtered with the topo. 2 or 3 body topological trigger requirement (this is per-prepared and stored on RTA eos/).
+# The topo. trigger requirement reduces the sample by about 1/10 so about 500 events are passed to the sprucing.
+# We consider a failure if the DstData bank has size greater than 30kB
+
+
+for i in range(0, len(names)):
+    if float(dstdata[i]) &gt; 60000:
+        causes.append('DstData RawBank of line {} is on average {} bytes!! This is big!\n'.format(names[i], dstdata[i]))
+
+</text></argument>
+</extension>
+
diff --git a/Hlt/Hlt2Conf/tests/qmtest/test_hlt2_all_lines.qmt b/Hlt/Hlt2Conf/tests/qmtest/test_hlt2_all_lines.qmt
index 14e2f943aec913921580a8dbdd5371b59d103307..98ff074dfecc554aa164d874d1b10bda35e308ef 100644
--- a/Hlt/Hlt2Conf/tests/qmtest/test_hlt2_all_lines.qmt
+++ b/Hlt/Hlt2Conf/tests/qmtest/test_hlt2_all_lines.qmt
@@ -26,12 +26,13 @@ HiveDataBrokerSvc().OutputLevel = 5
 <argument name="use_temp_dir"><enumeral>true</enumeral></argument>
 <argument name="validator"><text>
 from GaudiTesting.BaseTest import LineSkipper
+from Moore.qmtest.exclusions import remove_known_warnings
 
 # Brunel  does not persist VELO tracks and so the PVs we unpack in HLT2 have
 # null SmartRef pointers to their VELO tracks; this causes the PVs-with-tracks
 # cloner to complain because it can't clone the VELO tracks associated to PVs.
 # We can't do anything about this so ignore the warning from the cloner.
-remove_known_warnings = LineSkipper([
+remove_known_warnings = remove_known_warnings + LineSkipper([
     "CopyLinePersistenceLocations.Tur... WARNING VertexBaseFromRecVertexClonerWithTracks:: Null Track SmartRef found in PV in '/Event/Rec/Vertex/Primary'",
     "CopyLinePersistenceLocations.Tur... WARNING VertexBaseFromRecVertexClonerWithTracks:: The WARNING message is suppressed : 'Null Track SmartRef found in PV in '/Event/Rec/Vertex/Primary''",
 ])
diff --git a/Hlt/Hlt2Conf/tests/refs/hlt2_persistreco_check_flavourtags.ref b/Hlt/Hlt2Conf/tests/refs/hlt2_persistreco_check_flavourtags.ref
index 05ca08761322f83077635ece042918804af3340e..1fcb4ff8834af391c42f4908624e5be16213dc72 100644
--- a/Hlt/Hlt2Conf/tests/refs/hlt2_persistreco_check_flavourtags.ref
+++ b/Hlt/Hlt2Conf/tests/refs/hlt2_persistreco_check_flavourtags.ref
@@ -60,10 +60,6 @@ EventLoopMgr         INFO No more events in event selection
 0.027979999780654907
 1
 16
-0.46560001373291016
--0.1295499950647354
-1
-16
 0.2612999975681305
 0.7510600090026855
 1
@@ -108,22 +104,6 @@ EventLoopMgr         INFO No more events in event selection
 0.0
 0
 16
-0.42739999294281006
-0.17648999392986298
-1
-16
-0.45969998836517334
--0.06789000332355499
-1
-16
-0.42739999294281006
-0.17648999392986298
-1
-16
-0.45969998836517334
--0.06789000332355499
-1
-16
 0.5
 0.0
 0
@@ -156,6 +136,10 @@ EventLoopMgr         INFO No more events in event selection
 0.09053999930620193
 1
 16
+0.458133339881897
+-0.05268000066280365
+1
+16
 0.44156667590141296
 0.08399999886751175
 1
@@ -176,6 +160,10 @@ EventLoopMgr         INFO No more events in event selection
 -0.36201998591423035
 1
 16
+0.4510333240032196
+0.010710000060498714
+1
+16
 0.4496000111103058
 0.022530000656843185
 1
diff --git a/Hlt/Hlt2Conf/tests/refs/hlt2_persistreco_check_flavourtags.ref.x86_64_v3-opt b/Hlt/Hlt2Conf/tests/refs/hlt2_persistreco_check_flavourtags.ref.x86_64_v3-opt
index 05ca08761322f83077635ece042918804af3340e..1fcb4ff8834af391c42f4908624e5be16213dc72 100644
--- a/Hlt/Hlt2Conf/tests/refs/hlt2_persistreco_check_flavourtags.ref.x86_64_v3-opt
+++ b/Hlt/Hlt2Conf/tests/refs/hlt2_persistreco_check_flavourtags.ref.x86_64_v3-opt
@@ -60,10 +60,6 @@ EventLoopMgr         INFO No more events in event selection
 0.027979999780654907
 1
 16
-0.46560001373291016
--0.1295499950647354
-1
-16
 0.2612999975681305
 0.7510600090026855
 1
@@ -108,22 +104,6 @@ EventLoopMgr         INFO No more events in event selection
 0.0
 0
 16
-0.42739999294281006
-0.17648999392986298
-1
-16
-0.45969998836517334
--0.06789000332355499
-1
-16
-0.42739999294281006
-0.17648999392986298
-1
-16
-0.45969998836517334
--0.06789000332355499
-1
-16
 0.5
 0.0
 0
@@ -156,6 +136,10 @@ EventLoopMgr         INFO No more events in event selection
 0.09053999930620193
 1
 16
+0.458133339881897
+-0.05268000066280365
+1
+16
 0.44156667590141296
 0.08399999886751175
 1
@@ -176,6 +160,10 @@ EventLoopMgr         INFO No more events in event selection
 -0.36201998591423035
 1
 16
+0.4510333240032196
+0.010710000060498714
+1
+16
 0.4496000111103058
 0.022530000656843185
 1
diff --git a/Hlt/Hlt2Conf/tests/refs/hlt2_sspion_tagger_on_example_b2jpsik_lines.ref b/Hlt/Hlt2Conf/tests/refs/hlt2_sspion_tagger_on_example_b2jpsik_lines.ref
index ebe36d298451212b2baec1a059c68d9210a9d963..5bb5c9b35b7dcbd600a9252bef19e1021ed44225 100644
--- a/Hlt/Hlt2Conf/tests/refs/hlt2_sspion_tagger_on_example_b2jpsik_lines.ref
+++ b/Hlt/Hlt2Conf/tests/refs/hlt2_sspion_tagger_on_example_b2jpsik_lines.ref
@@ -1,12 +1,12 @@
 ApplicationMgr                         INFO Application Manager Stopped successfully
-CopyInputStream                        INFO Events output: 33
+CopyInputStream                        INFO Events output: 32
 ToolSvc                                INFO Removing all tools created by ToolSvc
 ApplicationMgr                         INFO Application Manager Finalized successfully
 ApplicationMgr                         INFO Application Manager Terminated successfully
 ChargedProtoParticleAssociator         INFO Number of counters : 2
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- |*"Efficiency"                                    |      3966 |       3198 |( 80.63540 +- 0.6274668)% |
- | "MC particles per ProtoParticle"                |      3198 |       3622 |     1.1326 |
+ |*"Efficiency"                                    |      3947 |       3181 |( 80.59286 +- 0.6294997)% |
+ | "MC particles per ProtoParticle"                |      3181 |       3599 |     1.1314 |
 DeterministicPrescaler                 INFO Number of counters : 1
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
  |*"#accept"                                       |       100 |        100 |( 100.0000 +-  0.000000)% |
@@ -27,36 +27,36 @@ FunctionalParticleMaker#1              INFO Number of counters : 4
  | "Nb created particles"                          |       100 |       4681 |     46.810 |     23.838 |      3.0000 |      143.00 |
 FunctionalParticleMaker#2              INFO Number of counters : 4
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- |*"# passed ProtoParticle filter"                 |      2972 |       2820 |( 94.88560 +- 0.4040854)% |
- |*"# passed Track filter"                         |      3966 |       2972 |( 74.93696 +- 0.6881586)% |
- | "Nb created anti-particles"                     |        33 |       1392 |     42.182 |     23.960 |      6.0000 |      98.000 |
- | "Nb created particles"                          |        33 |       1428 |     43.273 |     24.811 |      6.0000 |      100.00 |
+ |*"# passed ProtoParticle filter"                 |      2968 |       2818 |( 94.94609 +- 0.4020872)% |
+ |*"# passed Track filter"                         |      3947 |       2968 |( 75.19635 +- 0.6874207)% |
+ | "Nb created anti-particles"                     |        32 |       1395 |     43.594 |     24.114 |      6.0000 |      98.000 |
+ | "Nb created particles"                          |        32 |       1423 |     44.469 |     24.882 |      6.0000 |      100.00 |
 FunctionalSSPionTagger                 INFO Number of counters : 3
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- | "#BCandidates"                                  |        33 |         36 |     1.0909 |
- | "#goodFlavourTags"                              |        29 |         29 |     1.0000 |
- | "#taggingPions"                                 |        33 |       2820 |     85.455 |
+ | "#BCandidates"                                  |        32 |         35 |     1.0938 |
+ | "#goodFlavourTags"                              |        28 |         28 |     1.0000 |
+ | "#taggingPions"                                 |        32 |       2818 |     88.062 |
 FunctionalSSPionTagger#1               INFO Number of counters : 3
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- | "#BCandidates"                                  |         5 |          6 |     1.2000 |
- | "#goodFlavourTags"                              |         5 |          5 |     1.0000 |
- | "#taggingPions"                                 |         5 |        390 |     78.000 |
+ | "#BCandidates"                                  |         4 |          4 |     1.0000 |
+ | "#goodFlavourTags"                              |         3 |          3 |     1.0000 |
+ | "#taggingPions"                                 |         4 |        344 |     86.000 |
 FunctionalSSPionTagger#1.Tagging...    INFO Number of counters : 3
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- | "#iterations/1"                                 |        25 |         30 |     1.2000 |    0.40000 |      1.0000 |      2.0000 |
+ | "#iterations/1"                                 |        12 |         17 |     1.4167 |    0.49301 |      1.0000 |      2.0000 |
  | "#iterations/2"                                 |         6 |         12 |     2.0000 |      0.0000 |      2.0000 |      2.0000 |
- | "#iterations/Opt"                               |        26 |          6 |    0.23077 |    0.42133 |       0.0000 |      1.0000 |
+ | "#iterations/Opt"                               |        13 |          6 |    0.46154 |    0.49852 |       0.0000 |      1.0000 |
 FunctionalSSPionTagger.TaggingHe...    INFO Number of counters : 3
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- | "#iterations/1"                                 |       125 |        138 |     1.1040 |    0.30526 |      1.0000 |      2.0000 |
- | "#iterations/2"                                 |        14 |         28 |     2.0000 |      0.0000 |      2.0000 |      2.0000 |
- | "#iterations/Opt"                               |       126 |         14 |    0.11111 |    0.31427 |       0.0000 |      1.0000 |
+ | "#iterations/1"                                 |       115 |        129 |     1.1217 |    0.32698 |      1.0000 |      2.0000 |
+ | "#iterations/2"                                 |        15 |         30 |     2.0000 |      0.0000 |      2.0000 |      2.0000 |
+ | "#iterations/Opt"                               |       116 |         15 |    0.12931 |    0.33554 |       0.0000 |      1.0000 |
 HltPackedDataWriter                    INFO Number of counters : 2
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- | "Size of serialized data"                       |        33 |    3758960 | 1.1391e+05 |     62453.0 |      16840.0 |  2.5225e+05 |
+ | "Size of serialized data"                       |        32 |    3743066 | 1.1697e+05 |     62859.0 |      16840.0 |  2.5225e+05 |
 LoKi__HDRFilter                        INFO Number of counters : 1
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- |*"#passed"                                       |        33 |         33 |( 100.0000 +-  0.000000)% |
+ |*"#passed"                                       |        32 |         32 |( 100.0000 +-  0.000000)% |
 ToolSvc.HltFactory                     INFO Number of counters : 1
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
 ToolSvc.PPFactoryHybridFactory         INFO Number of counters : 1
@@ -74,37 +74,37 @@ UnpackMuonTracks                       INFO Number of counters : 1
  | "# Unpacked Tracks"                             |       100 |       2814 |     28.140 |
 bandq_b_hadron                         INFO Number of counters : 6
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- |*"# passed"                                      |       100 |         33 |( 33.00000 +- 4.702127)% |
- |*"# passed CombinationCut"                       |       526 |         82 |( 15.58935 +- 1.581684)% |
- |*"# passed CompositeCut"                         |        82 |         36 |( 43.90244 +- 5.480364)% |
- |*"# passed vertex fit"                           |        82 |         82 |( 100.0000 +-  0.000000)% |
+ |*"# passed"                                      |       100 |         32 |( 32.00000 +- 4.664762)% |
+ |*"# passed CombinationCut"                       |       485 |         83 |( 17.11340 +- 1.710171)% |
+ |*"# passed CompositeCut"                         |        83 |         35 |( 42.16867 +- 5.420477)% |
+ |*"# passed vertex fit"                           |        83 |         83 |( 100.0000 +-  0.000000)% |
  | "Input1 size"                                   |       100 |         60 |    0.60000 |
- | "Input2 size"                                   |       100 |        917 |     9.1700 |
+ | "Input2 size"                                   |       100 |        843 |     8.4300 |
 bandq_b_hadron#1                       INFO Number of counters : 6
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- |*"# passed"                                      |       100 |          5 |( 5.000000 +- 2.179449)% |
- |*"# passed CombinationCut"                       |       526 |         82 |( 15.58935 +- 1.581684)% |
- |*"# passed CompositeCut"                         |        82 |          6 |( 7.317073 +- 2.875820)% |
- |*"# passed vertex fit"                           |        82 |         82 |( 100.0000 +-  0.000000)% |
+ |*"# passed"                                      |       100 |          4 |( 4.000000 +- 1.959592)% |
+ |*"# passed CombinationCut"                       |       485 |         83 |( 17.11340 +- 1.710171)% |
+ |*"# passed CompositeCut"                         |        83 |          4 |( 4.819277 +- 2.350858)% |
+ |*"# passed vertex fit"                           |        83 |         83 |( 100.0000 +-  0.000000)% |
  | "Input1 size"                                   |       100 |         60 |    0.60000 |
- | "Input2 size"                                   |       100 |        917 |     9.1700 |
+ | "Input2 size"                                   |       100 |        843 |     8.4300 |
 bandq_detached_kaons                   INFO Number of counters : 1
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- |*"Cut selection efficiency"                      |      9381 |        917 |( 9.775077 +- 0.3066188)% |
+ |*"Cut selection efficiency"                      |      9381 |        843 |( 8.986249 +- 0.2952692)% |
 bandq_dimuon                           INFO Number of counters : 1
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
  |*"Cut selection efficiency"                      |        64 |         60 |( 93.75000 +- 3.025768)% |
 bandq_dimuon_base                      INFO Number of counters : 6
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
  |*"# passed"                                      |       100 |         60 |( 60.00000 +- 4.898979)% |
- |*"# passed CombinationCut"                       |       599 |         69 |( 11.51920 +- 1.304434)% |
- |*"# passed CompositeCut"                         |        69 |         64 |( 92.75362 +- 3.121055)% |
- |*"# passed vertex fit"                           |        69 |         69 |( 100.0000 +-  0.000000)% |
- | "Input1 size"                                   |       100 |        420 |     4.2000 |
- | "Input2 size"                                   |       100 |        420 |     4.2000 |
+ |*"# passed CombinationCut"                       |       843 |         72 |( 8.540925 +- 0.9626138)% |
+ |*"# passed CompositeCut"                         |        72 |         64 |( 88.88889 +- 3.703704)% |
+ |*"# passed vertex fit"                           |        72 |         72 |( 100.0000 +-  0.000000)% |
+ | "Input1 size"                                   |       100 |        452 |     4.5200 |
+ | "Input2 size"                                   |       100 |        452 |     4.5200 |
 bandq_ismuon_long_muons                INFO Number of counters : 1
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- |*"Cut selection efficiency"                      |      1444 |        420 |( 29.08587 +- 1.195154)% |
+ |*"Cut selection efficiency"                      |      1444 |        452 |( 31.30194 +- 1.220322)% |
 bandq_jpsi                             INFO Number of counters : 1
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
  |*"Cut selection efficiency"                      |        60 |         60 |( 100.0000 +-  0.000000)% |
diff --git a/Hlt/Hlt2Conf/tests/refs/hlt2_sspion_tagger_on_example_b2jpsik_lines.ref.x86_64_v3-opt b/Hlt/Hlt2Conf/tests/refs/hlt2_sspion_tagger_on_example_b2jpsik_lines.ref.x86_64_v3-opt
index ebe36d298451212b2baec1a059c68d9210a9d963..5bb5c9b35b7dcbd600a9252bef19e1021ed44225 100644
--- a/Hlt/Hlt2Conf/tests/refs/hlt2_sspion_tagger_on_example_b2jpsik_lines.ref.x86_64_v3-opt
+++ b/Hlt/Hlt2Conf/tests/refs/hlt2_sspion_tagger_on_example_b2jpsik_lines.ref.x86_64_v3-opt
@@ -1,12 +1,12 @@
 ApplicationMgr                         INFO Application Manager Stopped successfully
-CopyInputStream                        INFO Events output: 33
+CopyInputStream                        INFO Events output: 32
 ToolSvc                                INFO Removing all tools created by ToolSvc
 ApplicationMgr                         INFO Application Manager Finalized successfully
 ApplicationMgr                         INFO Application Manager Terminated successfully
 ChargedProtoParticleAssociator         INFO Number of counters : 2
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- |*"Efficiency"                                    |      3966 |       3198 |( 80.63540 +- 0.6274668)% |
- | "MC particles per ProtoParticle"                |      3198 |       3622 |     1.1326 |
+ |*"Efficiency"                                    |      3947 |       3181 |( 80.59286 +- 0.6294997)% |
+ | "MC particles per ProtoParticle"                |      3181 |       3599 |     1.1314 |
 DeterministicPrescaler                 INFO Number of counters : 1
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
  |*"#accept"                                       |       100 |        100 |( 100.0000 +-  0.000000)% |
@@ -27,36 +27,36 @@ FunctionalParticleMaker#1              INFO Number of counters : 4
  | "Nb created particles"                          |       100 |       4681 |     46.810 |     23.838 |      3.0000 |      143.00 |
 FunctionalParticleMaker#2              INFO Number of counters : 4
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- |*"# passed ProtoParticle filter"                 |      2972 |       2820 |( 94.88560 +- 0.4040854)% |
- |*"# passed Track filter"                         |      3966 |       2972 |( 74.93696 +- 0.6881586)% |
- | "Nb created anti-particles"                     |        33 |       1392 |     42.182 |     23.960 |      6.0000 |      98.000 |
- | "Nb created particles"                          |        33 |       1428 |     43.273 |     24.811 |      6.0000 |      100.00 |
+ |*"# passed ProtoParticle filter"                 |      2968 |       2818 |( 94.94609 +- 0.4020872)% |
+ |*"# passed Track filter"                         |      3947 |       2968 |( 75.19635 +- 0.6874207)% |
+ | "Nb created anti-particles"                     |        32 |       1395 |     43.594 |     24.114 |      6.0000 |      98.000 |
+ | "Nb created particles"                          |        32 |       1423 |     44.469 |     24.882 |      6.0000 |      100.00 |
 FunctionalSSPionTagger                 INFO Number of counters : 3
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- | "#BCandidates"                                  |        33 |         36 |     1.0909 |
- | "#goodFlavourTags"                              |        29 |         29 |     1.0000 |
- | "#taggingPions"                                 |        33 |       2820 |     85.455 |
+ | "#BCandidates"                                  |        32 |         35 |     1.0938 |
+ | "#goodFlavourTags"                              |        28 |         28 |     1.0000 |
+ | "#taggingPions"                                 |        32 |       2818 |     88.062 |
 FunctionalSSPionTagger#1               INFO Number of counters : 3
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- | "#BCandidates"                                  |         5 |          6 |     1.2000 |
- | "#goodFlavourTags"                              |         5 |          5 |     1.0000 |
- | "#taggingPions"                                 |         5 |        390 |     78.000 |
+ | "#BCandidates"                                  |         4 |          4 |     1.0000 |
+ | "#goodFlavourTags"                              |         3 |          3 |     1.0000 |
+ | "#taggingPions"                                 |         4 |        344 |     86.000 |
 FunctionalSSPionTagger#1.Tagging...    INFO Number of counters : 3
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- | "#iterations/1"                                 |        25 |         30 |     1.2000 |    0.40000 |      1.0000 |      2.0000 |
+ | "#iterations/1"                                 |        12 |         17 |     1.4167 |    0.49301 |      1.0000 |      2.0000 |
  | "#iterations/2"                                 |         6 |         12 |     2.0000 |      0.0000 |      2.0000 |      2.0000 |
- | "#iterations/Opt"                               |        26 |          6 |    0.23077 |    0.42133 |       0.0000 |      1.0000 |
+ | "#iterations/Opt"                               |        13 |          6 |    0.46154 |    0.49852 |       0.0000 |      1.0000 |
 FunctionalSSPionTagger.TaggingHe...    INFO Number of counters : 3
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- | "#iterations/1"                                 |       125 |        138 |     1.1040 |    0.30526 |      1.0000 |      2.0000 |
- | "#iterations/2"                                 |        14 |         28 |     2.0000 |      0.0000 |      2.0000 |      2.0000 |
- | "#iterations/Opt"                               |       126 |         14 |    0.11111 |    0.31427 |       0.0000 |      1.0000 |
+ | "#iterations/1"                                 |       115 |        129 |     1.1217 |    0.32698 |      1.0000 |      2.0000 |
+ | "#iterations/2"                                 |        15 |         30 |     2.0000 |      0.0000 |      2.0000 |      2.0000 |
+ | "#iterations/Opt"                               |       116 |         15 |    0.12931 |    0.33554 |       0.0000 |      1.0000 |
 HltPackedDataWriter                    INFO Number of counters : 2
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- | "Size of serialized data"                       |        33 |    3758960 | 1.1391e+05 |     62453.0 |      16840.0 |  2.5225e+05 |
+ | "Size of serialized data"                       |        32 |    3743066 | 1.1697e+05 |     62859.0 |      16840.0 |  2.5225e+05 |
 LoKi__HDRFilter                        INFO Number of counters : 1
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- |*"#passed"                                       |        33 |         33 |( 100.0000 +-  0.000000)% |
+ |*"#passed"                                       |        32 |         32 |( 100.0000 +-  0.000000)% |
 ToolSvc.HltFactory                     INFO Number of counters : 1
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
 ToolSvc.PPFactoryHybridFactory         INFO Number of counters : 1
@@ -74,37 +74,37 @@ UnpackMuonTracks                       INFO Number of counters : 1
  | "# Unpacked Tracks"                             |       100 |       2814 |     28.140 |
 bandq_b_hadron                         INFO Number of counters : 6
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- |*"# passed"                                      |       100 |         33 |( 33.00000 +- 4.702127)% |
- |*"# passed CombinationCut"                       |       526 |         82 |( 15.58935 +- 1.581684)% |
- |*"# passed CompositeCut"                         |        82 |         36 |( 43.90244 +- 5.480364)% |
- |*"# passed vertex fit"                           |        82 |         82 |( 100.0000 +-  0.000000)% |
+ |*"# passed"                                      |       100 |         32 |( 32.00000 +- 4.664762)% |
+ |*"# passed CombinationCut"                       |       485 |         83 |( 17.11340 +- 1.710171)% |
+ |*"# passed CompositeCut"                         |        83 |         35 |( 42.16867 +- 5.420477)% |
+ |*"# passed vertex fit"                           |        83 |         83 |( 100.0000 +-  0.000000)% |
  | "Input1 size"                                   |       100 |         60 |    0.60000 |
- | "Input2 size"                                   |       100 |        917 |     9.1700 |
+ | "Input2 size"                                   |       100 |        843 |     8.4300 |
 bandq_b_hadron#1                       INFO Number of counters : 6
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- |*"# passed"                                      |       100 |          5 |( 5.000000 +- 2.179449)% |
- |*"# passed CombinationCut"                       |       526 |         82 |( 15.58935 +- 1.581684)% |
- |*"# passed CompositeCut"                         |        82 |          6 |( 7.317073 +- 2.875820)% |
- |*"# passed vertex fit"                           |        82 |         82 |( 100.0000 +-  0.000000)% |
+ |*"# passed"                                      |       100 |          4 |( 4.000000 +- 1.959592)% |
+ |*"# passed CombinationCut"                       |       485 |         83 |( 17.11340 +- 1.710171)% |
+ |*"# passed CompositeCut"                         |        83 |          4 |( 4.819277 +- 2.350858)% |
+ |*"# passed vertex fit"                           |        83 |         83 |( 100.0000 +-  0.000000)% |
  | "Input1 size"                                   |       100 |         60 |    0.60000 |
- | "Input2 size"                                   |       100 |        917 |     9.1700 |
+ | "Input2 size"                                   |       100 |        843 |     8.4300 |
 bandq_detached_kaons                   INFO Number of counters : 1
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- |*"Cut selection efficiency"                      |      9381 |        917 |( 9.775077 +- 0.3066188)% |
+ |*"Cut selection efficiency"                      |      9381 |        843 |( 8.986249 +- 0.2952692)% |
 bandq_dimuon                           INFO Number of counters : 1
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
  |*"Cut selection efficiency"                      |        64 |         60 |( 93.75000 +- 3.025768)% |
 bandq_dimuon_base                      INFO Number of counters : 6
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
  |*"# passed"                                      |       100 |         60 |( 60.00000 +- 4.898979)% |
- |*"# passed CombinationCut"                       |       599 |         69 |( 11.51920 +- 1.304434)% |
- |*"# passed CompositeCut"                         |        69 |         64 |( 92.75362 +- 3.121055)% |
- |*"# passed vertex fit"                           |        69 |         69 |( 100.0000 +-  0.000000)% |
- | "Input1 size"                                   |       100 |        420 |     4.2000 |
- | "Input2 size"                                   |       100 |        420 |     4.2000 |
+ |*"# passed CombinationCut"                       |       843 |         72 |( 8.540925 +- 0.9626138)% |
+ |*"# passed CompositeCut"                         |        72 |         64 |( 88.88889 +- 3.703704)% |
+ |*"# passed vertex fit"                           |        72 |         72 |( 100.0000 +-  0.000000)% |
+ | "Input1 size"                                   |       100 |        452 |     4.5200 |
+ | "Input2 size"                                   |       100 |        452 |     4.5200 |
 bandq_ismuon_long_muons                INFO Number of counters : 1
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
- |*"Cut selection efficiency"                      |      1444 |        420 |( 29.08587 +- 1.195154)% |
+ |*"Cut selection efficiency"                      |      1444 |        452 |( 31.30194 +- 1.220322)% |
 bandq_jpsi                             INFO Number of counters : 1
  |    Counter                                      |     #     |    sum     | mean/eff^* | rms/err^*  |     min     |     max     |
  |*"Cut selection efficiency"                      |        60 |         60 |( 100.0000 +-  0.000000)% |
diff --git a/Hlt/Moore/python/Moore/config.py b/Hlt/Moore/python/Moore/config.py
index ba61506d871ed6447a6159900b9f96e8bc9adae1..d961fa5e1b310dd6ef37129b947781ff5d4c2fe8 100644
--- a/Hlt/Moore/python/Moore/config.py
+++ b/Hlt/Moore/python/Moore/config.py
@@ -296,13 +296,15 @@ def report_writers_node(streams,
     return node, new_hlt_banks, extra_locations_to_persist, barrier_algorithms, erw
 
 
+@configurable
 def stream_writer(stream,
                   path,
                   output_type,
                   process,
                   new_locations,
                   persist_locations,
-                  extra_locations=[]):
+                  extra_locations=[],
+                  write=True):
     """Return node for writing output for a stream.
 
     These algorithms are not functional and must be explicitly scheduled,
@@ -316,7 +318,9 @@ def stream_writer(stream,
         new_locations (list of DataHandle): Newly created raw event parts to write.
         persist_locations (list of str): Banks to persist from previous passes.
         extra_locations (list of str): Extra locations for ROOT file
-            persistence. Ignored for MDF files.
+            persistence. Ignored for MDF files. Defaults to [].
+        write (bool, optional): If False output files are not written out. For use in rate/event size analysis.
+            Defaults to True.
 
     Returns:
         (pre_algs, post_algs): Lists of configured algorithms that
@@ -382,22 +386,21 @@ def stream_writer(stream,
             ]
 
             consolidate_views = CombineRawBankViewsToRawEvent(
+                name="EvtSize_" + stream,
                 # FIXME this only works because of a bug https://gitlab.cern.ch/lhcb/LHCb/-/issues/160
                 # There is no trivial fix.
                 RawBankViews=locations,
                 #RawEvent dependent on the stream name -
                 #else multiple algs (one for each stream) output to same location
                 outputs={'RawEvent': force_location('/Event/' + stream)})
-
             # Kill any links the output file might have had to the input file
             writers.append(AddressKillerAlg())
-
-            writers.extend([
-                consolidate_views,
-                root_writer(
-                    full_fname,
-                    extra_locations_to_persist + [consolidate_views.RawEvent]),
-            ])
+            writers.append(consolidate_views)
+            if write:
+                writers.append(
+                    root_writer(
+                        full_fname, extra_locations_to_persist +
+                        [consolidate_views.RawEvent]))
 
         else:
             raw_events = [default_raw_event([bt]) for bt in persist_locations]
diff --git a/Hlt/RecoConf/options/hlt1_reco_allen_track_reconstruction.py b/Hlt/RecoConf/options/hlt1_reco_allen_track_reconstruction.py
index 325de7fb6b6ab7b9726530b75054e29d14ea38b1..8f740152a4e6206e3d2490c1e90349d1e1416939 100644
--- a/Hlt/RecoConf/options/hlt1_reco_allen_track_reconstruction.py
+++ b/Hlt/RecoConf/options/hlt1_reco_allen_track_reconstruction.py
@@ -14,10 +14,6 @@ from RecoConf.hlt1_tracking import require_gec
 from RecoConf.hlt1_allen import (make_allen_tracks, sequence)
 from RecoConf.mc_checking import get_track_checkers
 
-key = 'Upgrade_BsPhiPhi_MD_FTv4_DIGI'
-options.set_input_and_conds_from_testfiledb(key)
-options.evt_max = 1000
-
 
 def hlt1_reco_allen_tracks():
 
diff --git a/Hlt/RecoConf/python/RecoConf/phoenix_check.py b/Hlt/RecoConf/python/RecoConf/phoenix_check.py
index ac6d6ae62cdf784fcc370a1f71919cd39ece2285..c1382cfe23fb7449619acb8be6d34c5be004c706 100644
--- a/Hlt/RecoConf/python/RecoConf/phoenix_check.py
+++ b/Hlt/RecoConf/python/RecoConf/phoenix_check.py
@@ -102,6 +102,18 @@ def hitsCheck(data_name, data):
             posAttributeCheck(it, data_name)
 
 
+def fibersCheck(data_name, data):
+    # check that hits is a list of objects containing proper attributes
+    if not isinstance(data, list):
+        raise PhoenixFormatError(
+            "Expected FTHits to be a list. Not the case for %s" % data_name)
+    for item in data:
+        if "x0" not in item or "y" not in item or "z0" not in item or "dxDy" not in item:
+            raise PhoenixFormatError(
+                "Expected FTHits to have x0, y0, y and dxDy as attributes. Not the case for %s"
+                % data_name)
+
+
 def clustersCheck(data_name, data):
     return
 
@@ -123,6 +135,7 @@ KnownDataTypes = {
     'Tracks': tracksCheck,
     'Clusters': clustersCheck,
     'Jets': jetsCheck,
+    'Fibers': fibersCheck,
     'Hits': hitsCheck,
     'Vertices': verticesCheck,
     'PlanarCaloCells': planarCaloCheck,
diff --git a/Hlt/RecoConf/python/RecoConf/standalone.py b/Hlt/RecoConf/python/RecoConf/standalone.py
index 6242cb28b38cdbeffcfc6f7d51d623d6b5cbd20e..eb4810a5f043089784d84f8c5aadf868fe05e793 100644
--- a/Hlt/RecoConf/python/RecoConf/standalone.py
+++ b/Hlt/RecoConf/python/RecoConf/standalone.py
@@ -19,6 +19,7 @@ from .hlt1_tracking import (
     make_RetinaDecoder_raw_event, get_global_measurement_provider)
 
 from RecoConf.hlt1_muonmatch import make_tracks_with_muonmatch_ipcut
+from RecoConf.hlt1_tracking import make_PrStoreSciFiHits_hits
 from .hlt1_muonid import make_muon_id, make_tracks_with_muon_id
 from .hlt2_muonid import make_muon_ids as make_muon_id_hlt2
 from .hlt2_tracking import (
@@ -58,10 +59,8 @@ from Moore.config import Reconstruction
 from .data_from_file import boole_links_digits_mcparticles, mc_unpackers
 from .rich_add_reconstruction_monitoring_checking import add_hlt2_rich
 from PyConf.Algorithms import (
-    LHCb__Phoenix__DumpPlanarCaloCellsToJson,
-    LHCb__Phoenix__DumpVPHitEvent,
-    LHCb__Phoenix__DumpTracksEvent,
-)
+    LHCb__Phoenix__DumpPlanarCaloCellsToJson, LHCb__Phoenix__DumpVPHitEvent,
+    LHCb__Phoenix__DumpTracksEvent, LHCb__Phoenix__DumpFTHitEvent)
 
 
 @configurable
@@ -105,7 +104,7 @@ def standalone_hlt1_reco(do_mc_checking=False):
 def phoenix_data_dump():
     """ Runs only components needed to produce run3 event data (eg. run3 VPHits)
         Args:
-            None
+            none
         Returns:
             Reconstruction: Run3 Event Data To be used in LHCb / Phoenix Web Event / Geometry Display
 
@@ -113,6 +112,7 @@ def phoenix_data_dump():
     hlt1_tracks = make_hlt1_tracks()
     fitted_tracks = make_VeloKalman_fitted_tracks(hlt1_tracks)
     VP_hits = make_VeloClusterTrackingSIMD_hits()
+    FT_hits = make_PrStoreSciFiHits_hits()
     odin = make_odin()
     raw = default_raw_event(["VP"])
     calo_Edig = make_ecal_digits(raw)
@@ -126,10 +126,13 @@ def phoenix_data_dump():
     vp_dumper = LHCb__Phoenix__DumpVPHitEvent(
         VPHitsLocation=VP_hits, ODIN=odin)
 
+    ft_dumper = LHCb__Phoenix__DumpFTHitEvent(
+        FTHitsLocation=FT_hits, ODIN=odin)
+
     tracks_dumper = LHCb__Phoenix__DumpTracksEvent(
         InputTracksName=fitted_tracks["v1"], ODIN=odin)
 
-    data = [planar_dumper, vp_dumper, tracks_dumper]
+    data = [planar_dumper, vp_dumper, tracks_dumper, ft_dumper]
 
     return Reconstruction('data_dump', data, reco_prefilters())