diff --git a/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/builders/rdbuilder_thor.py b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/builders/rdbuilder_thor.py
new file mode 100644
index 0000000000000000000000000000000000000000..bce8cb7b84b8cfc28c2adf7e9d6c7a56256824e0
--- /dev/null
+++ b/Hlt/Hlt2Conf/python/Hlt2Conf/lines/rd/builders/rdbuilder_thor.py
@@ -0,0 +1,731 @@
+###############################################################################
+# (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 RD builders for ThOr framework.
+For now does not use any MVA tools as they are not ThOr-friendly.
+"""
+from GaudiKernel.SystemOfUnits import GeV, MeV, mm, ps
+
+from RecoConf.reconstruction_objects import make_pvs_v2 as make_pvs
+
+import Functors as F
+from Functors.math import in_range
+
+from Hlt2Conf.algorithms_thor import require_all, ParticleCombiner, ParticleFilter
+
+from PyConf import configurable
+
+from Hlt2Conf.standard_particles import (
+    make_has_rich_long_pions,
+    make_has_rich_long_kaons,
+    make_has_rich_long_protons,
+    make_long_pions,
+    make_long_kaons,
+    make_long_protons,
+    #make_has_rich_down_pions, make_has_rich_down_kaons, make_has_rich_down_protons, # we don't usually need RICH info in fact for D tracks
+    make_down_pions,
+    make_down_kaons,
+    make_down_protons,
+    #make_KsLL, make_KsDD, make_LambdaLL, make_LambdaDD, # we build our own versions below
+    make_long_muons,
+    make_long_electrons_with_brem,
+    make_photons,
+    make_resolved_pi0s,
+    make_merged_pi0s,
+    make_detached_mumu,
+    make_detached_dielectron_with_brem,
+    make_detached_mue_with_brem)
+
+####################################
+# Charged hadron selections        #
+####################################
+
+
+@configurable
+def make_filter_tracks(
+        make_particles=make_has_rich_long_pions,
+        make_pvs=make_pvs,
+        name="rd_has_rich_long_pions",
+        pt_min=250. * MeV,
+        p_min=2.0 * GeV,
+        trchi2dof_max=3,  #TBC with Reco
+        trghostprob_max=0.4,  #TBC with Reco
+        mipchi2dvprimary_min=None,
+        pid=None):
+
+    code = require_all(F.PT > pt_min, F.P > p_min, F.CHI2DOF < trchi2dof_max,
+                       F.GHOSTPROB < trghostprob_max)
+
+    if pid is not None:
+        code &= pid
+
+    if mipchi2dvprimary_min is not None:
+        pvs = make_pvs()
+        code &= F.MINIPCHI2(pvs) > mipchi2dvprimary_min
+
+    return ParticleFilter(make_particles(), name=name, Cut=F.FILTER(code))
+
+
+####################################
+# Detached                         #
+####################################
+
+# @configurable
+# def make_rd_detached_tracks(name="rd_detached_tracks",
+#                             mipchi2dvprimary_min=3.):
+#     """
+#     Return RD detached tracks.
+#     """
+#     return make_filter_tracks(
+#         name=name,
+#         make_particles=make_long_pions,
+#         mipchi2dvprimary_min=mipchi2dvprimary_min)
+
+
+@configurable
+def make_rd_detached_muons(
+        name="rd_detached_muons",
+        mipchi2dvprimary_min=3.,  #TBC
+        pid=(F.PID_MU > 0.)):
+    """
+    Return RD detached muons.
+    """
+    return make_filter_tracks(
+        name=name,
+        make_particles=make_long_muons,
+        mipchi2dvprimary_min=mipchi2dvprimary_min,
+        pid=pid)
+
+
+@configurable
+def make_rd_detached_electrons(
+        name="rd_detached_electrons",
+        mipchi2dvprimary_min=3.,  #TBC
+        pid=(F.PID_E > 0.)):
+    """
+    Return RD detached electrons with brem recovery.
+    """
+    return make_filter_tracks(
+        name=name,
+        make_particles=make_long_electrons_with_brem,
+        mipchi2dvprimary_min=mipchi2dvprimary_min,
+        pid=pid)
+
+
+@configurable
+def make_rd_detached_pions(
+        name="rd_detached_pions",
+        p_min=2 * GeV,
+        pt_min=250 * MeV,
+        mipchi2dvprimary_min=3.,  #TBC
+        pid=(F.PID_K <= 2.)):
+    """
+    Return RD detached pions.
+    """
+    return make_filter_tracks(
+        name=name,
+        make_particles=make_long_pions,
+        p_min=p_min,
+        pt_min=pt_min,
+        mipchi2dvprimary_min=mipchi2dvprimary_min,
+        pid=pid)
+
+
+@configurable
+def make_rd_detached_kaons(
+        name="rd_detached_kaons",
+        p_min=2 * GeV,
+        pt_min=250 * MeV,
+        mipchi2dvprimary_min=3.,  #TBC
+        pid=(F.PID_K > -2.)):
+    """
+    Return RD detached kaons.
+    """
+    return make_filter_tracks(
+        name=name,
+        make_particles=make_long_kaons,
+        p_min=p_min,
+        pt_min=pt_min,
+        mipchi2dvprimary_min=mipchi2dvprimary_min,
+        pid=pid)
+
+
+@configurable
+def make_rd_detached_protons(
+        name="rd_detached_protons",
+        p_min=2. * GeV,
+        pt_min=250 * MeV,
+        mipchi2dvprimary_min=3.,  #TBC
+        pid=(F.PID_P > -2.)):
+    """
+    Return RD detached protons.
+    """
+    return make_filter_tracks(
+        name=name,
+        make_particles=make_long_protons,
+        p_min=p_min,
+        pt_min=pt_min,
+        mipchi2dvprimary_min=mipchi2dvprimary_min,
+        pid=pid)
+
+
+@configurable
+def make_rd_has_rich_detached_pions(
+        name="rd_has_rich_detached_pions",
+        p_min=2 * GeV,
+        pt_min=250 * MeV,
+        mipchi2dvprimary_min=3.,  #TBC
+        pid=(F.PID_K <= 0.)):
+    """
+    Return RD detached pions with hasRich.
+    """
+    return make_filter_tracks(
+        name=name,
+        make_particles=make_has_rich_long_pions,
+        p_min=p_min,
+        pt_min=pt_min,
+        mipchi2dvprimary_min=mipchi2dvprimary_min,
+        pid=pid)
+
+
+@configurable
+def make_rd_has_rich_detached_kaons(
+        name="rd_has_rich_detached_kaons",
+        p_min=2 * GeV,
+        pt_min=250 * MeV,
+        mipchi2dvprimary_min=3.,  #TBC
+        pid=(F.PID_K > 0.)):
+    """
+    Return RD detached kaons with hasRich.
+    """
+    return make_filter_tracks(
+        name=name,
+        make_particles=make_has_rich_long_kaons,
+        p_min=p_min,
+        pt_min=pt_min,
+        mipchi2dvprimary_min=mipchi2dvprimary_min,
+        pid=pid)
+
+
+@configurable
+def make_rd_has_rich_detached_protons(
+        name="rd_has_rich_detached_protons",
+        p_min=8.5 *
+        GeV,  #kaon RICH threshold below which we have no p-K separation
+        pt_min=250 * MeV,
+        mipchi2dvprimary_min=3.,  #TBC
+        pid=require_all(F.PID_P > 0., F.PID_P - F.PID_K > -2.)):
+    """
+    Return RD detached protons with hasRich.
+    """
+    return make_filter_tracks(
+        name=name,
+        make_particles=make_has_rich_long_protons,
+        p_min=p_min,
+        pt_min=pt_min,
+        mipchi2dvprimary_min=mipchi2dvprimary_min,
+        pid=pid)
+
+
+####################################
+# Prompt                           #
+####################################
+
+
+@configurable
+def make_rd_prompt_pions(name="rd_prompt_pions", pid=(F.PID_K < 0.)):
+    """
+    Return RD prompt pions.
+    """
+    return make_filter_tracks(
+        make_particles=make_has_rich_long_pions, name=name, pid=pid)
+
+
+@configurable
+def make_rd_prompt_kaons(name="rd_prompt_kaons", pid=(F.PID_K > 0.)):
+    """
+    Return RD prompt kaons.
+    """
+    return make_filter_tracks(
+        make_particles=make_has_rich_long_kaons, name=name, pid=pid)
+
+
+@configurable
+def make_rd_prompt_protons(name="rd_prompt_protons",
+                           p_min=10. * GeV,
+                           pid=(F.PID_P > 0.)):
+    """
+    Return RD prompt protons.
+    """
+    return make_filter_tracks(
+        make_particles=make_has_rich_long_protons,
+        name=name,
+        p_min=p_min,
+        pid=pid)
+
+
+####################################
+# Downstream tracks                #
+####################################
+# def make_down_tracks(name="rd_down_tracks",
+#                      pid=None):  #do we really need this one?
+#     """
+#     Return RD downstream hadrons with pion mass hypothesis.
+#     """
+#     return make_filter_tracks(
+#         make_particles=make_down_pions, name=name, pid=pid)
+
+
+def make_rd_detached_down_pions(
+        name="rd_detached_down_pions",
+        #mipchi2dvprimary_min=3.,  #this does not work
+        pt_min=0. * MeV,
+        p_min=0 * GeV,
+        pid=None):
+    """
+    Return RD downstream hadrons with pion mass hypothesis.
+    """
+    return make_filter_tracks(
+        make_particles=make_down_pions,
+        name=name,
+        #mipchi2dvprimary_min=mipchi2dvprimary_min,
+        pt_min=pt_min,
+        p_min=pt_min,
+        pid=pid)
+
+
+def make_rd_detached_down_kaons(
+        name="rd_detached_down_kaons",
+        #mipchi2dvprimary_min=3.,  #TBC
+        pt_min=0. * MeV,
+        p_min=0 * GeV,
+        pid=None):
+    """
+    Return RD downstream hadrons with kaon mass hypothesis.
+    """
+    return make_filter_tracks(
+        make_particles=make_down_kaons,
+        name=name,
+        #mipchi2dvprimary_min=mipchi2dvprimary_min,
+        pt_min=pt_min,
+        p_min=pt_min,
+        pid=pid)
+
+
+def make_rd_detached_down_protons(
+        name="rd_detached_down_protons",
+        #mipchi2dvprimary_min=3.,  #TBC
+        pt_min=0. * MeV,
+        p_min=0 * GeV,
+        pid=None):
+    """
+    Return RD downstream hadrons with proton mass hypothesis.
+    """
+    return make_filter_tracks(
+        make_particles=make_down_protons,
+        name=name,
+        #mipchi2dvprimary_min=mipchi2dvprimary_min,
+        pt_min=pt_min,
+        p_min=pt_min,
+        pid=pid)
+
+
+####################################
+# Neutral particles                #
+####################################
+# builders to be updated once the CL functor is implemented in ThOr.
+
+
+@configurable
+def make_rd_photons(name="rd_photons",
+                    make_particles=make_photons,
+                    cl_min=0.1,
+                    et_min=250 * MeV,
+                    e_min=0 * MeV):
+    """For the time being just a dummy selection"""
+
+    code = F.PT > et_min
+    return ParticleFilter(make_particles(), F.FILTER(code), name=name)
+
+
+@configurable
+def make_rd_resolved_pi0s(
+        name="rd_resolved_pi0s",
+        make_particles=make_resolved_pi0s,
+        pt_min=250 * MeV,
+        cl_min=0,
+        # photon_args={
+        #     'ConfLevelCut': 0.1,
+        #     'PtCut': 250. * MeV
+        # },
+):
+    """For the time being just a dummy selection"""
+
+    # code = require_all('PT > {pt_min}', 'P > {p_min}').format(
+    #     pt_min=pt_min, p_min=p_min)
+    #
+    # return ParticleFilter(
+    #     make_particles(photon_args=photon_args), Code=code, name=name)
+    code = F.PT > pt_min
+    return ParticleFilter(make_particles(), F.FILTER(code))
+
+
+@configurable
+def make_rd_merged_pi0s(name="rd_merged_pi0s",
+                        make_particles=make_merged_pi0s,
+                        pt_min=250 * MeV,
+                        cl_min=0):
+    """For the time being just a dummy selection"""
+
+    code = F.PT > pt_min
+    return ParticleFilter(make_particles(), F.FILTER(code), name=name)
+
+
+####################################
+# V0 particles and alike           #
+####################################
+# they are in principle defined in the Hlt2 standard_particles, however there is no way to tune IPCHI2 cuts on their children with the current ThOr framework.
+
+
+@configurable
+def make_rd_ks0_lls(
+        name="rd_ks0_lls",
+        make_pions=make_rd_detached_pions,
+        make_pvs=make_pvs,
+        am_min=460 * MeV,  # ~40 MeV window
+        am_max=540 * MeV,
+        pi_p_min=2 * GeV,
+        pi_pt_min=0 * GeV,  # has to be 0 !!!
+        pi_ipchi2_min=9,
+        adocachi2cut=30.,
+        bpvvdchi2_min=4.,
+        bpvltime_min=1 * ps,
+        vchi2pdof_max=30.):
+    '''
+    Build Long-Long KS0 candidates. Approximately corresponding to the Run2
+    "StdVeryLooseKsLL" cuts.
+    '''
+
+    pions = make_pions(
+        p_min=pi_p_min,
+        pt_min=pi_pt_min,
+        mipchi2dvprimary_min=pi_ipchi2_min,
+        pid=None)  # important to get rid of any PID cuts!
+    descriptor = 'KS0 -> pi+ pi-'
+    combination_code = require_all(
+        in_range(am_min, F.MASS, am_max), F.MAXDOCACHI2CUT(adocachi2cut))
+    pvs = make_pvs()
+    vertex_code = require_all(
+        F.CHI2DOF < vchi2pdof_max,
+        #F.BPVLTIME(pvs) > bpvltime_min,
+        F.BPVFDCHI2(pvs) > bpvvdchi2_min)
+    return ParticleCombiner([pions, pions],
+                            name=name,
+                            DecayDescriptor=descriptor,
+                            CombinationCut=combination_code,
+                            CompositeCut=vertex_code)
+
+
+@configurable
+def make_rd_ks0_dds(
+        name="rd_ks0_dds",
+        make_pions=make_rd_detached_down_pions,
+        make_pvs=make_pvs,
+        am_min=420 * MeV,  # ~75 MeV window
+        am_max=570 * MeV,
+        pi_p_min=2 * GeV,
+        pi_pt_min=0,  # has to be 0 !!!
+        #pi_ipchi2_min=4,
+        adocachi2cut=30.,
+        bpvvdchi2_min=4.,
+        bpvltime_min=1 * ps,
+        vchi2pdof_max=25.):
+    '''
+    Build Long-Long KS0 candidates. Approximately corresponding to the Run2
+    "StdVeryLooseKsLL" cuts.
+    '''
+
+    pions = make_pions(
+        p_min=pi_p_min,
+        pt_min=pi_pt_min,
+        #mipchi2dvprimary_min=pi_ipchi2_min,
+        pid=None)
+    descriptor = 'KS0 -> pi+ pi-'
+    combination_code = require_all(
+        in_range(am_min, F.MASS, am_max), F.MAXDOCACHI2CUT(adocachi2cut))
+    pvs = make_pvs()
+    vertex_code = require_all(
+        F.CHI2DOF < vchi2pdof_max,
+        #F.BPVLTIME(pvs) > bpvltime_min,
+        F.BPVFDCHI2(pvs) > bpvvdchi2_min)
+    return ParticleCombiner([pions, pions],
+                            name=name,
+                            DecayDescriptor=descriptor,
+                            CombinationCut=combination_code,
+                            CompositeCut=vertex_code)
+
+
+@configurable
+def make_rd_lambda_lls(
+        name="rd_lambda_lls",
+        make_protons=make_rd_detached_protons,
+        make_pions=make_rd_detached_pions,
+        make_pvs=make_pvs,
+        am_min=1076 * MeV,  # ~40 MeV window
+        am_max=1156 * MeV,
+        pi_p_min=2 * GeV,
+        p_p_min=2 * GeV,
+        p_pt_min=0,  # recommended to be 0
+        pi_pt_min=0,  # has to be 0 !!!
+        pi_ipchi2_min=6,
+        p_ipchi2_min=9,
+        adocachi2cut=30.,
+        bpvvdchi2_min=4.,
+        bpvltime_min=1 * ps,
+        vchi2pdof_max=30.):
+    '''
+    Build Long-Long Lambda candidates. Approximately corresponding to the Run2
+    "StdVeryLooseLambdaLL" cuts.
+    '''
+
+    protons = make_protons(
+        p_min=p_p_min,
+        pt_min=p_pt_min,
+        mipchi2dvprimary_min=p_ipchi2_min,
+        pid=None)  # important to get rid of any PID cuts!
+    pions = make_pions(
+        p_min=pi_p_min,
+        pt_min=pi_pt_min,
+        mipchi2dvprimary_min=pi_ipchi2_min,
+        pid=None)
+    descriptor = '[Lambda0 -> p+ pi-]cc'
+    combination_code = require_all(
+        in_range(am_min, F.MASS, am_max), F.MAXDOCACHI2CUT(adocachi2cut))
+    pvs = make_pvs()
+    vertex_code = require_all(
+        F.CHI2DOF < vchi2pdof_max,
+        #F.BPVLTIME(pvs) > bpvltime_min,
+        F.BPVFDCHI2(pvs) > bpvvdchi2_min)
+    return ParticleCombiner([protons, pions],
+                            name=name,
+                            DecayDescriptor=descriptor,
+                            CombinationCut=combination_code,
+                            CompositeCut=vertex_code)
+
+
+@configurable
+def make_rd_lambda_dds(
+        name="rd_lambda_dds",
+        make_protons=make_rd_detached_down_protons,
+        make_pions=make_rd_detached_down_pions,
+        make_pvs=make_pvs,
+        am_min=1050 * MeV,  # ~65 MeV window
+        am_max=1180 * MeV,
+        pi_p_min=2 * GeV,
+        p_p_min=2 * GeV,
+        p_pt_min=0,  # recommended to be 0
+        pi_pt_min=0,  # has to be 0 !!!
+        #pi_ipchi2_min=6,
+        #p_ipchi2_min=9,
+        adocachi2cut=30.,
+        bpvvdchi2_min=4.,
+        bpvltime_min=1 * ps,
+        vchi2pdof_max=25.):
+    '''
+    Build Down-Down Lambda candidates. Approximately corresponding to the Run2
+    "StdVeryLooseLambdaLL" cuts.
+    '''
+
+    protons = make_protons(
+        p_min=p_p_min,
+        pt_min=p_pt_min,
+        #mipchi2dvprimary_min=p_ipchi2_min,
+        pid=None)  # important to get rid of any PID cuts!
+    pions = make_pions(
+        p_min=pi_p_min,
+        pt_min=pi_pt_min,
+        #mipchi2dvprimary_min=pi_ipchi2_min,
+        pid=None)
+    descriptor = '[Lambda0 -> p+ pi-]cc'
+    combination_code = require_all(
+        in_range(am_min, F.MASS, am_max), F.MAXDOCACHI2CUT(adocachi2cut))
+    pvs = make_pvs()
+    vertex_code = require_all(
+        F.CHI2DOF < vchi2pdof_max,
+        #F.BPVLTIME(pvs) > bpvltime_min,
+        F.BPVFDCHI2(pvs) > bpvvdchi2_min)
+    return ParticleCombiner([protons, pions],
+                            name=name,
+                            DecayDescriptor=descriptor,
+                            CombinationCut=combination_code,
+                            CompositeCut=vertex_code)
+
+
+####################################
+# 2-body hadron combinations       #
+####################################
+
+
+@configurable
+def make_rd_detached_kstar0s(
+        name="rd_detached_kstar0s",
+        make_rd_detached_pions=make_rd_has_rich_detached_pions,
+        make_rd_detached_kaons=make_rd_has_rich_detached_kaons,
+        make_pvs=make_pvs,
+        am_min=592 * MeV,
+        am_max=1192 * MeV,
+        pi_p_min=2 * GeV,
+        pi_pt_min=100 * MeV,
+        k_p_min=2 * GeV,
+        k_pt_min=100 * MeV,
+        kstar0_pt_min=400 * MeV,
+        adocachi2cut=30.,
+        vchi2pdof_max=25):
+    '''
+    Build Kstar0 candidates. Approximately corresponding to the Run2
+    "StdVeryLooseDetachedKstar" cuts.
+    '''
+
+    pions = make_rd_detached_pions(p_min=pi_p_min, pt_min=pi_pt_min)
+    kaons = make_rd_detached_kaons(p_min=k_p_min, pt_min=k_pt_min)
+    descriptor = '[K*(892)0 -> K+ pi-]cc'
+    combination_code = require_all(
+        in_range(am_min, F.MASS, am_max), F.MAXDOCACHI2CUT(adocachi2cut))
+    #pvs = make_pvs()
+    vertex_code = require_all(F.CHI2DOF < vchi2pdof_max, F.PT > kstar0_pt_min)
+    return ParticleCombiner([kaons, pions],
+                            name=name,
+                            DecayDescriptor=descriptor,
+                            CombinationCut=combination_code,
+                            CompositeCut=vertex_code)
+
+
+# this is in principle defined in the Hlt2 standard_particles, however there is no way to provide IPCHI2 cuts on the kaons within the current ThOr framework.
+@configurable
+def make_rd_detached_phis(
+        name="rd_detached_phis",
+        make_rd_detached_kaons=make_rd_has_rich_detached_kaons,
+        make_pvs=make_pvs,
+        am_max=1100 * MeV,  #min is the di-kaon threshold anyway
+        k_p_min=2 * GeV,
+        k_pt_min=100 * MeV,
+        phi_pt_min=400 * MeV,
+        adocachi2cut=30.,
+        vchi2pdof_max=25):
+    '''
+    Build phi(1020) candidates. Approximately corresponding to the Run2
+    "StdLooseDetachedPhi2KK" cuts.
+    '''
+
+    kaons = make_rd_detached_kaons(p_min=k_p_min, pt_min=k_pt_min)
+    descriptor = 'phi(1020) -> K+ K-'
+    combination_code = require_all(F.MASS < am_max,
+                                   F.MAXDOCACHI2CUT(adocachi2cut))
+    #pvs = make_pvs()
+    vertex_code = require_all(F.CHI2DOF < vchi2pdof_max, F.PT > phi_pt_min)
+    return ParticleCombiner([kaons, kaons],
+                            name=name,
+                            DecayDescriptor=descriptor,
+                            CombinationCut=combination_code,
+                            CompositeCut=vertex_code)
+
+
+####################################
+# Dileptons                        #
+####################################
+
+
+@configurable
+def filter_dimuon_noMVA(probnn_mu=0.0, max_dimuon_mass=6000 * MeV):
+
+    dimuons = make_detached_mumu(probnn_mu=probnn_mu, pt_mu=150 * MeV)
+    code = require_all(F.MASS < max_dimuon_mass)
+    return ParticleFilter(dimuons, F.FILTER(code))
+
+
+@configurable
+def filter_dielectron_noMVA(probnn_e=0.05, max_dielectron_mass=6000 * MeV):
+
+    dielectrons = make_detached_dielectron_with_brem(
+        probnn_e=probnn_e, m_diE_max=max_dielectron_mass)
+    code = require_all(F.MASS < max_dielectron_mass)
+    return ParticleFilter(dielectrons, F.FILTER(code))
+
+
+@configurable
+def filter_mue_noMVA(max_dilepton_mass=6000 * MeV,
+                     min_probnn_mu=0.0,
+                     min_PIDe=2.,
+                     same_sign=False):
+
+    dileptons = make_detached_mue_with_brem(
+        min_probnn_mu=min_probnn_mu, min_PIDe=min_PIDe, same_sign=same_sign)
+    code = require_all(F.MASS < max_dilepton_mass)
+    return ParticleFilter(dileptons, F.FILTER(code))
+
+
+####################################
+# Tau builders                     #
+####################################
+
+
+@configurable
+def make_rd_tauons_hadronic_decay(
+        name="rd_tauons_hadronic_decay",
+        make_pions=make_rd_detached_pions,
+        descriptor="[tau+ -> pi- pi+ pi+]cc",
+        pi_pt_min=150 * MeV,
+        pi_ipchi2_min=4.0,
+        pi_pid=(F.PID_K < 8.),
+        best_pi_pt_min=300 * MeV,
+        best_pi_ipchi2_min=5,
+        pt_max=300 * MeV,
+        am_min=400 * MeV,
+        am_max=3500 * MeV,
+        make_pvs=make_pvs,
+        adoca_max=0.15 * mm,
+        am_2pi_max=1670 * MeV,
+        vchi2pdof_max=25,
+        bpvdira_min=0.99,
+):
+    '''
+    Build tau->3pi candidates. Approximately corresponding to the Run2
+    "StdLooseDetachedTau" cuts.
+    '''
+
+    pions = make_pions(
+        pt_min=pi_pt_min, mipchi2dvprimary_min=pi_ipchi2_min, pid=pi_pid)
+
+    combination12_code = require_all(
+        F.MASS < am_2pi_max,
+        F.DOCA(1, 2) < adoca_max,
+    )
+
+    pvs = make_pvs()
+    combination_code = require_all(
+        in_range(am_min, F.MASS, am_max),
+        F.DOCA(1, 3) < adoca_max,
+        F.DOCA(2, 3) < adoca_max,
+        F.SUM(F.PT > best_pi_pt_min) > 1,
+        F.SUM(F.MINIPCHI2(pvs) > best_pi_ipchi2_min) > 1,
+    )
+    #TODO: add the M13<1670 cut once this is possible.
+    vertex_code = require_all(
+        in_range(am_min, F.MASS, am_max),
+        F.CHI2DOF < vchi2pdof_max,
+        F.BPVDIRA(pvs) > bpvdira_min,
+    )
+    return ParticleCombiner([pions, pions, pions],
+                            name=name,
+                            DecayDescriptor=descriptor,
+                            Combination12Cut=combination12_code,
+                            CombinationCut=combination_code,
+                            CompositeCut=vertex_code)