From 57300cbf7d23ee9a809cd749369369cf2206f9c6 Mon Sep 17 00:00:00 2001
From: Eduardo Rodrigues <eduardo.rodrigues@cern.ch>
Date: Fri, 5 Mar 2021 08:23:25 +0000
Subject: [PATCH] Fixed formatting

patch generated by https://gitlab.cern.ch/lhcb/DaVinci/-/jobs/12434240
---
 .../python/DaVinci/common_particles.py        | 167 +++++++
 Phys/DaVinci/python/DaVinci/data_from_file.py | 422 ++++++++----------
 .../python/DaVinci/filters_selectors.py       | 167 +++++++
 Phys/DaVinci/python/DaVinci/locations.py      | 133 ++++++
 Phys/DaVinci/python/DaVinci/optionChecker.py  |   2 +-
 Phys/DaVinci/python/DaVinci/reco_objects.py   |  16 +-
 .../python/DaVinci/standard_particles.py      |  45 +-
 7 files changed, 684 insertions(+), 268 deletions(-)
 create mode 100644 Phys/DaVinci/python/DaVinci/common_particles.py
 create mode 100644 Phys/DaVinci/python/DaVinci/filters_selectors.py
 create mode 100644 Phys/DaVinci/python/DaVinci/locations.py

diff --git a/Phys/DaVinci/python/DaVinci/common_particles.py b/Phys/DaVinci/python/DaVinci/common_particles.py
new file mode 100644
index 000000000..f8783effe
--- /dev/null
+++ b/Phys/DaVinci/python/DaVinci/common_particles.py
@@ -0,0 +1,167 @@
+###############################################################################
+# (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.                                       #
+###############################################################################
+"""
+Definitions of "common particles" very similar to those of Runs 1 & 2.
+"""
+
+from PyConf.tonic import configurable
+from PyConf.Algorithms import FunctionalParticleMaker
+from PyConf.Algorithms import LHCb__Phys__ParticleMakers__PhotonMaker as PhotonMaker
+
+from .reco_objects import make_charged_protoparticles as _make_charged_protoparticles
+from .reco_objects import make_neutral_protoparticles as _make_neutral_protoparticles
+from .reco_objects import make_pvs as _make_pvs
+
+from .selectors import default_particle_cuts, default_track_cuts
+from .selectors import get_long_track_selector, get_down_track_selector
+from .filters import all_protoparticle_filter as standard_protoparticle_filter
+
+from .algorithms_pyconf import ParticleFilterWithPVs, ParticleCombinerWithPVs
+
+#########
+# Helpers
+#########
+
+
+@configurable
+def _make_particles(species,
+                    make_protoparticles=_make_charged_protoparticles,
+                    get_track_selector=get_long_track_selector,
+                    make_protoparticle_filter=standard_protoparticle_filter):
+    """
+    Helper configurable to create `LHCb::Particle`s from `LHCb::ProtoParticle`s.
+
+    Args:
+        species (str): Particle species hypothesis accepted by
+            `FunctionalParticleMaker`, i.e. one of the strings
+            "pion", "kaon", "muon", "electron", "proton".
+    """
+    particles = FunctionalParticleMaker(
+        ParticleID=species,
+        InputProtoParticles=make_protoparticles(),
+        TrackSelector=get_track_selector(),
+        ProtoParticleFilter=make_protoparticle_filter()).Particles
+    return particles
+
+
+@configurable
+def make_photons(make_neutral_protoparticles=_make_neutral_protoparticles,
+                 pvs=_make_pvs,
+                 **kwargs):
+    """
+    Configurable to create photon `LHCb::Particle`s from `LHCb::ProtoParticle`s.
+    """
+    particles = PhotonMaker(
+        InputProtoParticles=make_neutral_protoparticles(),
+        InputPrimaryVertices=pvs(),
+        **kwargs).Particles
+    return particles
+
+
+def _make_std_loose_particles(particles, pvs, name):
+    return ParticleFilterWithPVs(
+        particles, pvs, name=name, Code=default_particle_cuts())
+
+
+#######################
+# Bacic particle makers
+#######################
+
+
+def make_long_pions():
+    return _make_particles(species="pion")
+
+
+def make_long_kaons():
+    return _make_particles(species="kaon")
+
+
+def make_long_protons():
+    return _make_particles(species="proton")
+
+
+def make_long_muons():
+    return _make_particles(species="muon")
+
+
+def make_long_electrons_no_brem():
+    return _make_particles(species="electron")
+
+
+def make_down_pions():
+    return _make_particles(
+        species="pion", get_track_selector=get_down_track_selector)
+
+
+def make_down_kaons():
+    return _make_particles(
+        species="kaon", get_track_selector=get_down_track_selector)
+
+
+def make_down_protons():
+    return _make_particles(
+        species="proton", get_track_selector=get_down_track_selector)
+
+
+#################################
+# Particle makers with loose cuts
+#################################
+
+
+@configurable
+def make_std_loose_pions():
+    with get_long_track_selector.bind(
+            Code=default_track_cuts()), standard_protoparticle_filter.bind(
+                Code='PP_HASRICH'):
+        return _make_std_loose_particles(
+            make_long_pions(), _make_pvs(), name='StdLoosePions')
+
+
+@configurable
+def make_std_loose_kaons():
+    with get_long_track_selector.bind(
+            Code=default_track_cuts()), standard_protoparticle_filter.bind(
+                Code='PP_HASRICH'):
+        return _make_std_loose_particles(
+            make_long_kaons(), _make_pvs(), name='StdLooseKaons')
+
+
+@configurable
+def make_std_loose_protons():
+    with get_long_track_selector.bind(
+            Code=default_track_cuts()), standard_protoparticle_filter.bind(
+                Code='PP_HASRICH'):
+        return _make_std_loose_particles(
+            make_long_protons(), _make_pvs(), name='StdLooseProtons')
+
+
+def make_std_loose_muons():
+    #with get_long_track_selector.bind(Code=default_track_cuts()):
+    return _make_std_loose_particles(
+        make_long_muons(), _make_pvs(), name='StdLooseMuons')
+
+
+@configurable
+def make_std_loose_jpsi2mumu():
+    muons = make_std_loose_muons()
+    descriptors = ["J/psi(1S) -> mu+ mu-"]
+    daughters_code = {"mu+": "ALL", "mu-": "ALL"}
+    combination_code = "(ADAMASS('J/psi(1S)') < 100.*MeV) & (ADOCACHI2CUT(30,''))"
+    vertex_code = "(CHI2VX < 25.)"
+
+    return ParticleCombinerWithPVs(
+        name="StdLooseJpsi2MuMu",
+        particles=muons,
+        pvs=_make_pvs(),
+        DecayDescriptors=descriptors,
+        DaughtersCuts=daughters_code,
+        CombinationCut=combination_code,
+        MotherCut=vertex_code)
diff --git a/Phys/DaVinci/python/DaVinci/data_from_file.py b/Phys/DaVinci/python/DaVinci/data_from_file.py
index 25ec69269..471effb02 100644
--- a/Phys/DaVinci/python/DaVinci/data_from_file.py
+++ b/Phys/DaVinci/python/DaVinci/data_from_file.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".   #
@@ -8,206 +8,129 @@
 # granted to it by virtue of its status as an Intergovernmental Organization  #
 # or submit itself to any jurisdiction.                                       #
 ###############################################################################
-
-######
-### N.B. THIS FILE IS INTENDED TO AVOID DEPENDENCIES ON MOORE,
-### IS NEEDED FOR TESTING PURPOSES AND NEEDS TO BE REMOVED IN PRODUCTION
-######
-"""Load data from files and set up unpackers.
+"""
+Helper module with functions to load reco./MC data and linker tables from files,
+and set up reconstruction and simulation unpackers.
 
 There are two things we have to deal with:
 
 1. Loading the data from the file in to the TES, done by
-   Gaudi::Hive::FetchDataFromFile.
+   `Gaudi::Hive::FetchDataFromFile`.
 2. Unpacking and preparing packed containers, if the 'reconstruction' is
    defined as the objects already present in the file.
 
-In most LHCb applications, step 2 is done for you behind the scenes. The
-DataOnDemandSvc is configured in LHCb/GaudiConf/DstConf.py to unpack containers
-when they are requested. It also configures adding RICH, MUON, and combined PID
-information to ProtoParticles when they're unpacked. Because we don't have the
-DataOnDemandSvc here, we have to do this by hand.
-
-The interesting 'user-facing' exports of this module are:
-
-* [reco,mc]_from_file(): Dict of names to locations that can be loaded from a file.
-* [reco,mc]_unpackers(): Dict from unpacked object name to Algorithm that produces a
-  container of those objects.
+In most LHCb applications step 2 is done behind the scenes:
+the `DataOnDemandSvc` is configured in `LHCb/GaudiConf/DstConf.py`
+to unpack containers when they are requested.
+It also configures adding RICH, MUON, and combined PID information to ProtoParticles
+when the unpacking takes place. This module effectively does all these steps
+explicitly because the `PyConf` framework does not rely (by construction!)
+on the somewhat subtle and obscure `DataOnDemandSvc`.
+
+The interesting "user-facing" exports of this module are
+`{reco,mc}_unpackers()`, which return a dict from unpacked object name to
+a `PyConf.Algorithm` instance that produces a container of those objects.
+
+ The locations are defined under `DaVinci.locations`.
+
+.. note::
+    1) The functions defined in this module rely on data paths used in Runs 1 & 2,
+    and may need a revision once the Run 3 event model is finalised
+    and the definition of what gets persisted gets formalised.
+    2) Code very heavily relies on its Moore equivalent. Thank you, RTA team.
 """
 from __future__ import absolute_import, division, print_function
+
 import collections
 
 from Gaudi.Configuration import ERROR
+
+from Configurables import (UnpackCaloHypo, UnpackProtoParticle,
+                           UnpackRecVertex, UnpackTrackFunctional,
+                           UnpackMCParticle, UnpackMCVertex)
 from Configurables import (
     DataPacking__Unpack_LHCb__MuonPIDPacker_,
-    DataPacking__Unpack_LHCb__RichPIDPacker_, UnpackCaloHypo,
-    UnpackProtoParticle, UnpackRecVertex, UnpackTrackFunctional,
-    UnpackMCParticle, UnpackMCVertex, DataPacking__Unpack_LHCb__MCVPHitPacker_
-    as UnpackMCVPHit, DataPacking__Unpack_LHCb__MCUTHitPacker_ as
-    UnpackMCUTHit, DataPacking__Unpack_LHCb__MCFTHitPacker_ as UnpackMCFTHit,
+    DataPacking__Unpack_LHCb__RichPIDPacker_,
+    DataPacking__Unpack_LHCb__MCVPHitPacker_ as UnpackMCVPHit,
+    DataPacking__Unpack_LHCb__MCUTHitPacker_ as UnpackMCUTHit,
+    DataPacking__Unpack_LHCb__MCFTHitPacker_ as UnpackMCFTHit,
     DataPacking__Unpack_LHCb__MCRichHitPacker_ as UnpackMCRichHit,
     DataPacking__Unpack_LHCb__MCEcalHitPacker_ as UnpackMCEcalHit,
     DataPacking__Unpack_LHCb__MCHcalHitPacker_ as UnpackMCHcalHit,
     DataPacking__Unpack_LHCb__MCMuonHitPacker_ as UnpackMCMuonHit,
     DataPacking__Unpack_LHCb__MCRichDigitSummaryPacker_ as RichSumUnPack)
 
-from PyConf.components import Algorithm, force_location
-from PyConf.application import make_data_with_FetchDataFromFile
 from PyConf.Tools import (ChargedProtoParticleAddRichInfo,
                           ChargedProtoParticleAddMuonInfo,
                           ChargedProtoParticleAddCombineDLLs)
 
+from PyConf.components import Algorithm, force_location
+from PyConf.application import make_data_with_FetchDataFromFile
 
-def packed_reco_from_file():
-    return {
-        'PackedPVs': '/Event/pRec/Vertex/Primary',
-        'PackedCaloElectrons': '/Event/pRec/Calo/Electrons',
-        'PackedCaloPhotons': '/Event/pRec/Calo/Photons',
-        'PackedCaloMergedPi0s': '/Event/pRec/Calo/MergedPi0s',
-        'PackedCaloSplitPhotons': '/Event/pRec/Calo/SplitPhotons',
-        'PackedMuonPIDs': '/Event/pRec/Muon/MuonPID',
-        'PackedRichPIDs': '/Event/pRec/Rich/PIDs',
-        'PackedTracks': '/Event/pRec/Track/Best',
-        'PackedMuonTracks': '/Event/pRec/Track/Muon',
-        'PackedNeutralProtos': '/Event/pRec/ProtoP/Neutrals',
-        'PackedChargedProtos': '/Event/pRec/ProtoP/Charged',
-    }
-
-
-def packed_mc_from_file():
-    return {
-        'PackedMCParticles': '/Event/pSim/MCParticles',
-        'PackedMCVertices': '/Event/pSim/MCVertices',
-        'PackedMCVPHits': '/Event/pSim/VP/Hits',
-        'PackedMCUTHits': '/Event/pSim/UT/Hits',
-        'PackedMCFTHits': '/Event/pSim/FT/Hits',
-        'PackedMCRichHits': '/Event/pSim/Rich/Hits',
-        'PackedMCEcalHits': '/Event/pSim/Ecal/Hits',
-        'PackedMCHcalHits': '/Event/pSim/Hcal/Hits',
-        'PackedMCMuonHits': '/Event/pSim/Muon/Hits',
-        'PackedMCRichDigitSummaries': '/Event/pSim/Rich/DigitSummaries',
-    }
-
-
-def unpacked_reco_locations():
-    # If the structure is not like this, pointers point to to the wrong place...
-    # The SmartRefs held by the unpacked MC objects only work if we unpack to these specific locations
-    locations = {
-        k: v.replace('pRec', 'Rec')
-        for k, v in packed_reco_from_file().items()
-    }
-    return locations
-
-
-def unpacked_mc_locations():
-    # If the structure is not like this, pointers point to to the wrong place...
-    # The SmartRefs held by the unpacked MC objects only work if we unpack to these specific locations
-    return {
-        'PackedMCParticles': '/Event/MC/Particles',
-        'PackedMCVertices': '/Event/MC/Vertices',
-        'PackedMCVPHits': '/Event/MC/VP/Hits',
-        'PackedMCUTHits': '/Event/MC/UT/Hits',
-        'PackedMCFTHits': '/Event/MC/FT/Hits',
-        'PackedMCRichHits': '/Event/MC/Rich/Hits',
-        'PackedMCEcalHits': '/Event/MC/Ecal/Hits',
-        'PackedMCHcalHits': '/Event/MC/Hcal/Hits',
-        'PackedMCMuonHits': '/Event/MC/Muon/Hits',
-        'PackedMCRichDigitSummaries': '/Event/MC/Rich/DigitSummaries',
-    }
-
-
-def reco_from_file():
-    # TODO(AP) should only add the packed data if we're running on Upgrade MC
-    # where Brunel has already been run
-    packed_data = packed_reco_from_file()
-    # raw_event = raw_event_from_file()
-    # We don't want any keys accidentally overwriting each other
-    # assert set(packed_data.keys()).intersection(set(raw_event.keys())) == set()
-    # return dict(list(packed_data.items()) + list(raw_event.items()))
-    return packed_data
-
-
-def mc_from_file():
-    # TODO(AP) should only add the packed data if we're running on Upgrade MC
-    # where Brunel has already been run
-    packed_data = packed_mc_from_file()
-    return packed_data
-
-
-def reco_unpacker(key, configurable, name, **kwargs):
-    """Return unpacker that reads from file and unpacks to a forced output location."""
-    packed_loc = reco_from_file()[key]
-    unpacked_loc = unpacked_reco_locations()[key]
-    alg = Algorithm(
-        configurable,
-        name=name,
-        outputs={'OutputName': force_location(unpacked_loc)},
-        InputName=make_data_with_FetchDataFromFile(packed_loc),
-        **kwargs)
-    return alg
-
-
-def mc_unpacker(key, configurable, name, **kwargs):
-    """Return unpacker that reads from file and unpacks to a forced output location."""
-    packed_loc = mc_from_file()[key]
-    unpacked_loc = unpacked_mc_locations()[key]
-    alg = Algorithm(
-        configurable,
-        name=name,
-        outputs={'OutputName': force_location(unpacked_loc)},
-        InputName=make_data_with_FetchDataFromFile(packed_loc),
-        **kwargs)
-    return alg
-
-
-def make_mc_track_info():
-    return make_data_with_FetchDataFromFile('/Event/MC/TrackInfo')
+from .locations import (LocationsPackedReco, LocationsUnpackedReco)
+from .locations import (LocationsPackedSim, LocationsUnpackedSim)
+from .locations import (LocationsBooleMCParticleLinkers,
+                        LocationsBooleMCHitsLinkers, LocationsBrunelMCLinkers,
+                        LocationMCTrackInfo)
+from .locations import enums_as_dict
 
 
 def reco_unpackers():
-    muonPIDs = reco_unpacker('PackedMuonPIDs',
+    """
+    Return a {object name: `PyConf.Algorithm` instance}  `OrderedDict`
+    effectively mapping unpacked reconstruction object names to their respective
+    unpacked data.
+    The names (keys) are the following:
+        'PVs',
+        'Tracks', 'MuonTracks',
+        'NeutralProtos', 'ChargedProtos',
+        'CaloElectrons', 'CaloPhotons', 'CaloMergedPi0s', 'CaloSplitPhotons',
+        'MuonPIDs', 'RichPIDs'.
+    """
+    muonPIDs = reco_unpacker(LocationsPackedReco.PackedMuonPIDs.name,
                              DataPacking__Unpack_LHCb__MuonPIDPacker_,
-                             'UnpackMuonPIDs')
+                             "UnpackMuonPIDs")
     richPIDs = reco_unpacker(
-        'PackedRichPIDs',
+        LocationsPackedReco.PackedRichPIDs.name,
         DataPacking__Unpack_LHCb__RichPIDPacker_,
-        'UnpackRichPIDs',
+        "UnpackRichPIDs",
         OutputLevel=ERROR)
     # The OutputLevel above suppresses the following useless warnings (plus more?)
     # WARNING DataPacking::Unpack<LHCb::RichPIDPacker>:: Incorrect data version 0 for packing version > 3. Correcting data to version 2.
 
     # Ordered so that dependents are unpacked first
     d = collections.OrderedDict([
-        ('PVs', reco_unpacker('PackedPVs', UnpackRecVertex,
-                              'UnpackRecVertices')),
-        ('CaloElectrons',
-         reco_unpacker('PackedCaloElectrons', UnpackCaloHypo,
-                       'UnpackCaloElectrons')),
-        ('CaloPhotons',
-         reco_unpacker('PackedCaloPhotons', UnpackCaloHypo,
-                       'UnpackCaloPhotons')),
-        ('CaloMergedPi0s',
-         reco_unpacker('PackedCaloMergedPi0s', UnpackCaloHypo,
-                       'UnpackCaloMergedPi0s')),
-        ('CaloSplitPhotons',
-         reco_unpacker('PackedCaloSplitPhotons', UnpackCaloHypo,
-                       'UnpackCaloSplitPhotons')),
-        ('MuonPIDs', muonPIDs),
-        ('RichPIDs', richPIDs),
-        ('Tracks',
-         reco_unpacker('PackedTracks', UnpackTrackFunctional,
-                       'UnpackBestTracks')),
-        ('MuonTracks',
-         reco_unpacker('PackedMuonTracks', UnpackTrackFunctional,
-                       'UnpackMuonTracks')),
-        ('NeutralProtos',
-         reco_unpacker('PackedNeutralProtos', UnpackProtoParticle,
-                       'UnpackNeutralProtos')),
-        ('ChargedProtos',
+        ("PVs",
+         reco_unpacker(LocationsPackedReco.PackedPVs.name, UnpackRecVertex,
+                       "UnpackRecVertices")),
+        ("CaloElectrons",
+         reco_unpacker(LocationsPackedReco.PackedCaloElectrons.name,
+                       UnpackCaloHypo, "UnpackCaloElectrons")),
+        ("CaloPhotons",
+         reco_unpacker(LocationsPackedReco.PackedCaloPhotons.name,
+                       UnpackCaloHypo, "UnpackCaloPhotons")),
+        ("CaloMergedPi0s",
+         reco_unpacker(LocationsPackedReco.PackedCaloMergedPi0s.name,
+                       UnpackCaloHypo, "UnpackCaloMergedPi0s")),
+        ("CaloSplitPhotons",
+         reco_unpacker(LocationsPackedReco.PackedCaloSplitPhotons.name,
+                       UnpackCaloHypo, "UnpackCaloSplitPhotons")),
+        ("MuonPIDs", muonPIDs),
+        ("RichPIDs", richPIDs),
+        ("Tracks",
+         reco_unpacker(LocationsPackedReco.PackedTracks.name,
+                       UnpackTrackFunctional, "UnpackBestTracks")),
+        ("MuonTracks",
+         reco_unpacker(LocationsPackedReco.PackedMuonTracks.name,
+                       UnpackTrackFunctional, "UnpackMuonTracks")),
+        ("NeutralProtos",
+         reco_unpacker(LocationsPackedReco.PackedNeutralProtos.name,
+                       UnpackProtoParticle, "UnpackNeutralProtos")),
+        ("ChargedProtos",
          reco_unpacker(
-             'PackedChargedProtos',
+             LocationsPackedReco.PackedChargedProtos.name,
              UnpackProtoParticle,
-             'UnpackChargedProtos',
+             "UnpackChargedProtos",
              AddInfo=[
                  ChargedProtoParticleAddRichInfo(
                      InputRichPIDLocation=richPIDs.OutputName),
@@ -219,103 +142,152 @@ def reco_unpackers():
 
     # Make sure we have consistent names, and that we're unpacking everything
     # we load from the file
-    assert set(['Packed' + k for k in d.keys()]) - set(
-        packed_reco_from_file().keys()) == set()
+    assert set(["Packed" + k for k in d.keys()]) - set(
+        enums_as_dict(LocationsPackedReco).keys()) == set()
 
     return d
 
 
 def mc_unpackers():
+    """
+    Return a {object name: `PyConf.Algorithm` instance}  `OrderedDict`
+    effectively mapping unpacked reconstruction object names to their respective
+    unpacked data.
+    The names (keys) are the following:
+        'MCRichDigitSummaries',
+        'MCParticles', 'MCVertices',
+        'MCVPHits', 'MCUTHits', 'MCFTHits','MCRichHits',
+        'MCEcalHits', 'MCHcalHits', 'MCMuonHits'.
+    """
     # Ordered so that dependents are unpacked first
-    mc_vertices = mc_unpacker('PackedMCVertices', UnpackMCVertex,
-                              'UnpackMCVertices')
+    mc_vertices = mc_unpacker(LocationsPackedSim.PackedMCVertices.name,
+                              UnpackMCVertex, "UnpackMCVertices")
     # Make sure that MC particles and MC vertices are unpacked together,
     # see https://gitlab.cern.ch/lhcb/LHCb/issues/57 for details.
     mc_particles = mc_unpacker(
-        'PackedMCParticles',
+        LocationsPackedSim.PackedMCParticles.name,
         UnpackMCParticle,
-        'UnpackMCParticles',
+        "UnpackMCParticles",
         ExtraInputs=[mc_vertices])
 
-    mc_vp_hits = mc_unpacker('PackedMCVPHits', UnpackMCVPHit, 'UnpackMCVPHits')
-    mc_ut_hits = mc_unpacker('PackedMCUTHits', UnpackMCUTHit, 'UnpackMCUTHits')
-    mc_ft_hits = mc_unpacker('PackedMCFTHits', UnpackMCFTHit, 'UnpackMCFTHits')
-    mc_rich_hits = mc_unpacker('PackedMCRichHits', UnpackMCRichHit,
-                               'UnpackMCRichHits')
-    mc_ecal_hits = mc_unpacker('PackedMCEcalHits', UnpackMCEcalHit,
-                               'UnpackMCEcalHits')
-    mc_hcal_hits = mc_unpacker('PackedMCHcalHits', UnpackMCHcalHit,
-                               'UnpackMCHcalHits')
-    mc_muon_hits = mc_unpacker('PackedMCMuonHits', UnpackMCMuonHit,
-                               'UnpackMCMuonHits')
-
-    # RICH Digit summaries
-    mc_rich_digit_sums = mc_unpacker('PackedMCRichDigitSummaries',
-                                     RichSumUnPack, "RichSumUnPack")
+    mc_vp_hits = mc_unpacker(LocationsPackedSim.PackedMCVPHits.name,
+                             UnpackMCVPHit, "UnpackMCVPHits")
+    mc_ut_hits = mc_unpacker(LocationsPackedSim.PackedMCUTHits.name,
+                             UnpackMCUTHit, "UnpackMCUTHits")
+    mc_ft_hits = mc_unpacker(LocationsPackedSim.PackedMCFTHits.name,
+                             UnpackMCFTHit, "UnpackMCFTHits")
+    mc_rich_hits = mc_unpacker(LocationsPackedSim.PackedMCRichHits.name,
+                               UnpackMCRichHit, "UnpackMCRichHits")
+    mc_ecal_hits = mc_unpacker(LocationsPackedSim.PackedMCEcalHits.name,
+                               UnpackMCEcalHit, "UnpackMCEcalHits")
+    mc_hcal_hits = mc_unpacker(LocationsPackedSim.PackedMCHcalHits.name,
+                               UnpackMCHcalHit, "UnpackMCHcalHits")
+    mc_muon_hits = mc_unpacker(LocationsPackedSim.PackedMCMuonHits.name,
+                               UnpackMCMuonHit, "UnpackMCMuonHits")
+
+    mc_rich_digit_sums = mc_unpacker(
+        LocationsPackedSim.PackedMCRichDigitSummaries.name, RichSumUnPack,
+        "RichSumUnPack")
 
     d = collections.OrderedDict([
-        ('MCRichDigitSummaries', mc_rich_digit_sums),
-        ('MCParticles', mc_particles),
-        ('MCVertices', mc_vertices),
-        ('MCVPHits', mc_vp_hits),
-        ('MCUTHits', mc_ut_hits),
-        ('MCFTHits', mc_ft_hits),
-        ('MCRichHits', mc_rich_hits),
-        ('MCEcalHits', mc_ecal_hits),
-        ('MCHcalHits', mc_hcal_hits),
-        ('MCMuonHits', mc_muon_hits),
+        ("MCRichDigitSummaries", mc_rich_digit_sums),
+        ("MCParticles", mc_particles),
+        ("MCVertices", mc_vertices),
+        ("MCVPHits", mc_vp_hits),
+        ("MCUTHits", mc_ut_hits),
+        ("MCFTHits", mc_ft_hits),
+        ("MCRichHits", mc_rich_hits),
+        ("MCEcalHits", mc_ecal_hits),
+        ("MCHcalHits", mc_hcal_hits),
+        ("MCMuonHits", mc_muon_hits),
     ])
 
     # Make sure we have consistent names, and that we're unpacking everything
     # we load from the file
-    assert set(['Packed' + k for k in d.keys()]) - set(
-        packed_mc_from_file().keys()) == set()
+    assert set(["Packed" + k for k in d.keys()]) - set(
+        enums_as_dict(LocationsPackedSim).keys()) == set()
 
     return d
 
 
+def reco_unpacker(key, configurable, name, **kwargs):
+    """
+    Return a reco. unpacker (`PyConf.Algorithm` instance) that reads from file
+    at `LocationsPackedReco[key]` and unpacks to the
+    forced output location `LocationsUnpackedReco[key]`.
+    """
+    alg = Algorithm(
+        configurable,
+        name=name,
+        InputName=make_data_with_FetchDataFromFile(
+            LocationsPackedReco[key].value),
+        outputs={
+            "OutputName": force_location(LocationsUnpackedReco[key].value)
+        },
+        **kwargs)
+    return alg
+
+
+def mc_unpacker(key, configurable, name, **kwargs):
+    """
+    Return a sim. unpacker (`PyConf.Algorithm` instance) that reads from file
+    at `LocationsPackedSim[key]` and unpacks to the
+    forced output location `LocationsUnpackedSim[key]`.
+    """
+    alg = Algorithm(
+        configurable,
+        name=name,
+        InputName=make_data_with_FetchDataFromFile(
+            LocationsPackedSim[key].value),
+        outputs={
+            "OutputName": force_location(LocationsUnpackedSim[key].value)
+        },
+        **kwargs)
+    return alg
+
+
+def make_mc_track_info():
+    """
+    Return the MCTrackInfo data under `locations.LocationMCTrackInfo`
+    via `Gaudi::Hive::FetchDataFromFile`.
+    """
+    return make_data_with_FetchDataFromFile(LocationMCTrackInfo)
+
+
 def boole_links_digits_mcparticles():
-    """Return a dict of locations for MC linker tables (to mcparticles) created by Boole."""
-    locations = {
-        "EcalDigits": "/Event/Link/Raw/Ecal/Digits",
-        "FTLiteClusters": "/Event/Link/Raw/FT/LiteClusters",
-        "HcalDigits": "/Event/Link/Raw/Hcal/Digits",
-        "MuonDigits": "/Event/Link/Raw/Muon/Digits",
-        "UTClusters": "/Event/Link/Raw/UT/Clusters",
-        "VPDigits": "/Event/Link/Raw/VP/Digits",
-    }
+    """
+    Return a {TES_path: make_data_with_FetchDataFromFile(TES_path)} dict
+    of locations (`locations.LocationsBooleMCParticleLinkers`) for MC linker tables
+    (to `MCParticles`) created by Boole.
+    """
     return {
-        key: make_data_with_FetchDataFromFile(loc)
-        for key, loc in locations.items()
+        loc.name: make_data_with_FetchDataFromFile(loc.value)
+        for loc in LocationsBooleMCParticleLinkers
     }
 
 
 def boole_links_digits_mchits():
-    """Return a dict of locations for MC linker tables (to mchits) created by Boole.
+    """
+    Return a {TES_path: make_data_with_FetchDataFromFile(TES_path)} dict
+    of locations (`locations.LocationsBooleMCHitsLinkers`) for MC linker tables
+    (to `MCHits`) created by Boole.
 
-    These locations are only propagated out of Boole for eXtendend DIGI and DST types.
+    These locations are only propagated and persisted out of Boole
+    for eXtendend DIGI and DST types.
     """
-    locations = {
-        "FTLiteClusters": "/Event/Link/Raw/FT/LiteClusters2MCHits",
-        "UTClusters": "/Event/Link/Raw/UT/Clusters2MCHits",
-        "VPDigits": "/Event/Link/Raw/VP/Digits2MCHits",
-    }
     return {
-        key: make_data_with_FetchDataFromFile(loc)
-        for key, loc in locations.items()
+        loc.name: make_data_with_FetchDataFromFile(loc.value)
+        for loc in LocationsBooleMCHitsLinkers
     }
 
 
 def brunel_links():
-    """Return a dict of locations for MC linker tables created by Brunel."""
-    locations = {
-        "CaloElectrons": "/Event/Link/Rec/Calo/Electrons",
-        "CaloMergedPi0s": "/Event/Link/Rec/Calo/MergedPi0s",
-        "CaloPhotons": "/Event/Link/Rec/Calo/Photons",
-        "CaloSplitPhotons": "/Event/Link/Rec/Calo/SplitPhotons",
-        "Tracks": "/Event/Link/Rec/Track/Best",
-    }
+    """
+    Return a {TES_path: make_data_with_FetchDataFromFile(TES_path)} dict
+    of locations (`locations.LocationsBrunelMCLinkers`) for MC linker tables
+    created by Brunel.
+    """
     return {
-        key: make_data_with_FetchDataFromFile(loc)
-        for key, loc in locations.items()
+        loc.name: make_data_with_FetchDataFromFile(loc.value)
+        for loc in LocationsBrunelMCLinkers
     }
diff --git a/Phys/DaVinci/python/DaVinci/filters_selectors.py b/Phys/DaVinci/python/DaVinci/filters_selectors.py
new file mode 100644
index 000000000..b301bbb7b
--- /dev/null
+++ b/Phys/DaVinci/python/DaVinci/filters_selectors.py
@@ -0,0 +1,167 @@
+###############################################################################
+# (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.                                       #
+###############################################################################
+"""
+Definitions of:
+
+- `Particle` and `ProtoParticle` filters.
+- Track selectors.
+- Default cuts à la runs 1&2 common particles.
+"""
+from __future__ import absolute_import, division, print_function
+
+from PyConf.tonic import configurable
+from PyConf.Tools import LoKi__Hybrid__ProtoParticleFilter as ProtoParticleFilter
+from PyConf.Tools import LoKi__Hybrid__TrackSelector as TrackSelector
+
+from .hacks import patched_hybrid_tool
+
+#########################
+# Helpers to combine cuts
+#########################
+
+
+def require_all(*cuts):
+    """
+    Return a cut string requiring all (string) arguments.
+
+    Example:
+
+        >>> require_all('PT > {pt_min}', 'DLLK < {dllk_max}')
+        '(PT > {pt_min}) & (DLLK < {dllk_max})'
+    """
+    return " & ".join(["({})".format(c) for c in cuts])
+
+
+def require_any(*cuts):
+    """
+    Return a cut string requiring at least one of the (string) arguments passes.
+
+    Example:
+
+        >>> require_any('M < 8*GeV', 'PT > 3*GeV')
+        '(M < 8*GeV) | (PT > 3*GeV)'
+    """
+    return " | ".join(["({})".format(c) for c in cuts])
+
+
+#######################
+# Protoparticle filters
+#######################
+
+
+@configurable
+def all_protoparticle_filter(Code="PP_ALL", **kwargs):
+    """
+    Get a `LoKi__Hybrid__ProtoParticleFilter` instance
+    that by default selects all protoparticles.
+
+    Args:
+        Code (str): The "Code" argument to pass to the filter tool.
+                    Default = "PP_ALL".
+        kwargs: Keyword arguments accepted by `LoKi__Hybrid__Tool`.
+
+    Returns:
+        `LoKi__Hybrid__ProtoParticleFilter` instance wrapped as a `PyConf.components.Tool`.
+    """
+    return ProtoParticleFilter(
+        Code=Code, Factory=patched_hybrid_tool("PPFactory"), **kwargs)
+
+
+#################
+# Track selectors
+#################
+
+
+@configurable
+def get_all_track_selector(Code="TrALL", **kwargs):
+    """
+    Get a `LoKi__Hybrid__TrackSelector` instance
+    that by default selects all tracks.
+
+    Args:
+        Code (str): The "Code" argument to pass to the tool.
+                    Default = "TrALL".
+        kwargs: Keyword arguments accepted by `LoKi__Hybrid__TrackSelector`.
+
+    Returns:
+        `LoKi__Hybrid__TrackSelector` instance wrapped as a `PyConf.components.Tool`.
+    """
+    return TrackSelector(Code=Code, **kwargs)
+
+
+@configurable
+def get_long_track_selector(Code='TrALL', **kwargs):
+    """
+    Get a `LoKi__Hybrid__TrackSelector` instance
+    that by default selects all long tracks.
+
+    Args:
+        Code (str): The "Code" argument to pass to the tool.
+                    Default = "TrALL & TrLONG".
+        kwargs: Keyword arguments accepted by `LoKi__Hybrid__TrackSelector`.
+
+    Returns:
+        `LoKi__Hybrid__TrackSelector` instance wrapped as a `PyConf.components.Tool`.
+    """
+    return TrackSelector(Code=require_all("TrLONG", Code), **kwargs)
+
+
+@configurable
+def get_down_track_selector(Code='TrALL', **kwargs):
+    """
+    Get a `LoKi__Hybrid__TrackSelector` instance
+    that by default selects all downstream tracks.
+
+    Args:
+        Code (str): The "Code" argument to pass to the tool.
+                    Default = "TrALL & TrDOWNSTREAM".
+        kwargs: Keyword arguments accepted by `LoKi__Hybrid__TrackSelector`.
+
+    Returns:
+        `LoKi__Hybrid__TrackSelector` instance wrapped as a `PyConf.components.Tool`.
+    """
+    return TrackSelector(Code=require_all("TrDOWNSTREAM", Code), **kwargs)
+
+
+@configurable
+def get_upstream_track_selector(Code='TrALL', **kwargs):
+    """
+    Get a `LoKi__Hybrid__TrackSelector` instance
+    that by default selects all upstream tracks.
+
+    Args:
+        Code (str): The "Code" argument to pass to the tool.
+                    Default = "TrALL & TrUPSTREAM".
+        kwargs: Keyword arguments accepted by `LoKi__Hybrid__TrackSelector`.
+
+    Returns:
+        `LoKi__Hybrid__TrackSelector` instance wrapped as a `PyConf.components.Tool`.
+    """
+    return TrackSelector(Code=require_all("TrUPSTREAM", Code), **kwargs)
+
+
+#################################
+# Default track and particle cuts
+#################################
+
+
+def default_track_cuts():
+    """
+    Return a string with the default track cuts.
+    """
+    return require_all("TrCHI2<5", "~TrCLONE")
+
+
+def default_particle_cuts():
+    """
+    Return a string with the default particle standard loose cuts.
+    """
+    return require_all("PT>250*MeV", "MIPCHI2DV(PRIMARY)>4.")
diff --git a/Phys/DaVinci/python/DaVinci/locations.py b/Phys/DaVinci/python/DaVinci/locations.py
new file mode 100644
index 000000000..38a104274
--- /dev/null
+++ b/Phys/DaVinci/python/DaVinci/locations.py
@@ -0,0 +1,133 @@
+###############################################################################
+# (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.                                       #
+###############################################################################
+"""
+Definitions of enums specifying the standard locations of
+packed and unpacked objects, and various linker tables.
+
+.. note::
+    These locations are what has been used in Runs 1 & 2,
+    and may need a revision once the Run 3 event model is finalised
+    and the definition of what gets persisted gets formalised.
+"""
+from __future__ import absolute_import, division, print_function
+
+from enum import Enum
+
+
+class LocationsPackedReco(Enum):
+    """
+    Locations of packed reconstruction objects, stored under "/Event/pRec".
+    """
+    PackedPVs = "/Event/pRec/Vertex/Primary"
+    PackedCaloElectrons = "/Event/pRec/Calo/Electrons"
+    PackedCaloPhotons = "/Event/pRec/Calo/Photons"
+    PackedCaloMergedPi0s = "/Event/pRec/Calo/MergedPi0s"
+    PackedCaloSplitPhotons = "/Event/pRec/Calo/SplitPhotons"
+    PackedMuonPIDs = "/Event/pRec/Muon/MuonPID"
+    PackedRichPIDs = "/Event/pRec/Rich/PIDs"
+    PackedTracks = "/Event/pRec/Track/Best"
+    PackedMuonTracks = "/Event/pRec/Track/Muon"
+    PackedNeutralProtos = "/Event/pRec/ProtoP/Neutrals"
+    PackedChargedProtos = "/Event/pRec/ProtoP/Charged"
+
+
+LocationsUnpackedReco = Enum(
+    "LocationsUnpackedReco",
+    {e.name: e.value.replace("pRec", "Rec")
+     for e in LocationsPackedReco})
+LocationsUnpackedReco.__doc__ = """
+Locations of packed reconstruction objects, stored under "/Event/pRec".
+"""
+
+
+class LocationsPackedSim(Enum):
+    """
+    Locations of packed simulation objects, stored under "/Event/pSim".
+    """
+    PackedMCParticles = "/Event/pSim/MCParticles"
+    PackedMCVertices = "/Event/pSim/MCVertices"
+    PackedMCVPHits = "/Event/pSim/VP/Hits"
+    PackedMCUTHits = "/Event/pSim/UT/Hits"
+    PackedMCFTHits = "/Event/pSim/FT/Hits"
+    PackedMCRichHits = "/Event/pSim/Rich/Hits"
+    PackedMCEcalHits = "/Event/pSim/Ecal/Hits"
+    PackedMCHcalHits = "/Event/pSim/Hcal/Hits"
+    PackedMCMuonHits = "/Event/pSim/Muon/Hits"
+    PackedMCRichDigitSummaries = "/Event/pSim/Rich/DigitSummaries"
+
+
+class LocationsUnpackedSim(Enum):
+    """
+    Locations of unpacked simulation objects, stored under "/Event/MC".
+    """
+    PackedMCParticles = "/Event/MC/Particles"
+    PackedMCVertices = "/Event/MC/Vertices"
+    PackedMCVPHits = "/Event/MC/VP/Hits"
+    PackedMCUTHits = "/Event/MC/UT/Hits"
+    PackedMCFTHits = "/Event/MC/FT/Hits"
+    PackedMCRichHits = "/Event/MC/Rich/Hits"
+    PackedMCEcalHits = "/Event/MC/Ecal/Hits"
+    PackedMCHcalHits = "/Event/MC/Hcal/Hits"
+    PackedMCMuonHits = "/Event/MC/Muon/Hits"
+    PackedMCRichDigitSummaries = "/Event/MC/Rich/DigitSummaries"
+
+
+# Location of MCTrackInfo objects
+LocationMCTrackInfo = "/Event/MC/TrackInfo"
+
+
+class LocationsBooleMCParticleLinkers(Enum):
+    """
+    Locations of MC linker tables to MCParticles created by Boole.
+    """
+    EcalDigits = "/Event/Link/Raw/Ecal/Digits"
+    FTLiteClusters = "/Event/Link/Raw/FT/LiteClusters"
+    HcalDigits = "/Event/Link/Raw/Hcal/Digits"
+    MuonDigits = "/Event/Link/Raw/Muon/Digits"
+    UTClusters = "/Event/Link/Raw/UT/Clusters"
+    VPDigits = "/Event/Link/Raw/VP/Digits"
+
+
+class LocationsBooleMCHitsLinkers(Enum):
+    """
+    Locations for MC linker tables to MCHits created by Boole.
+
+    These locations are only propagated out of Boole for eXtendend DIGI and DST types.
+    """
+    FTLiteClusters = "/Event/Link/Raw/FT/LiteClusters2MCHits"
+    UTClusters = "/Event/Link/Raw/UT/Clusters2MCHits"
+    VPDigits = "/Event/Link/Raw/VP/Digits2MCHits"
+
+
+class LocationsBrunelMCLinkers(Enum):
+    """
+    Locations of MC linker tables created by Brunel.
+    """
+    CaloElectrons = "/Event/Link/Rec/Calo/Electrons"
+    CaloMergedPi0s = "/Event/Link/Rec/Calo/MergedPi0s"
+    CaloPhotons = "/Event/Link/Rec/Calo/Photons"
+    CaloSplitPhotons = "/Event/Link/Rec/Calo/SplitPhotons"
+    Tracks = "/Event/Link/Rec/Track/Best"
+
+
+def enums_as_dict(enums):
+    """
+    Return a {name: value} dict of all enum members.
+
+    Example:
+
+        >>> class MyEnum(Enum):
+                a = 1
+                b = 2
+        >>> enums_as_dict(MyEnum)
+        {'a': 1, 'b': 2}
+    """
+    return {e.name: e.value for e in enums}
diff --git a/Phys/DaVinci/python/DaVinci/optionChecker.py b/Phys/DaVinci/python/DaVinci/optionChecker.py
index 9475f3249..9b21a3b31 100644
--- a/Phys/DaVinci/python/DaVinci/optionChecker.py
+++ b/Phys/DaVinci/python/DaVinci/optionChecker.py
@@ -89,7 +89,7 @@ def print_allowed_option_values(allowedValues, name=None):
         print(set_color("green") +
               "Known job option configurations and allowed values:")
         for name, values in allowedValues.iteritems():
-            print("%s \t : %s" % (name, value), set_color("plain"))
+            print("%s \t : %s" % (name, values), set_color("plain"))
     else:
         print(set_color("green") +
               "Allowed values for DaVinci option %s:" % name)
diff --git a/Phys/DaVinci/python/DaVinci/reco_objects.py b/Phys/DaVinci/python/DaVinci/reco_objects.py
index 87931be7f..d0f599033 100644
--- a/Phys/DaVinci/python/DaVinci/reco_objects.py
+++ b/Phys/DaVinci/python/DaVinci/reco_objects.py
@@ -8,11 +8,16 @@
 # granted to it by virtue of its status as an Intergovernmental Organization  #
 # or submit itself to any jurisdiction.                                       #
 ###############################################################################
+"""
+Configurables to make the various reconstruction objects from the
+packed data on file.
 
-######
-### N.B. THIS FILE IS INTENDED TO AVOID DEPENDENCIES ON MOORE,
-### IS NEEDED FOR TESTING PURPOSES AND NEEDS TO BE REMOVED IN PRODUCTION
-######
+.. note::
+    1) What is defined here relies on data paths used in Runs 1 & 2,
+    and may need a revision once the Run 3 event model is finalised
+    and the definition of what gets persisted gets formalised.
+    2) Code very heavily relies on its Moore equivalent. Thank you, RTA team.
+"""
 
 from PyConf import configurable
 from .data_from_file import reco_unpackers
@@ -54,7 +59,8 @@ def make_tracks():
 def reconstruction(from_file=True):
     """Return reconstruction objects.
 
-    Note it is advised to use this function if more than one object is needed,
+    Note:
+        It is advised to use this function if more than one object is needed,
     rather than the accessors below as it makes the configuration slower.
     """
     # removed reco since it will not be done in DV
diff --git a/Phys/DaVinci/python/DaVinci/standard_particles.py b/Phys/DaVinci/python/DaVinci/standard_particles.py
index 96d6097d7..36e38bcb3 100644
--- a/Phys/DaVinci/python/DaVinci/standard_particles.py
+++ b/Phys/DaVinci/python/DaVinci/standard_particles.py
@@ -19,18 +19,13 @@ from __future__ import absolute_import, division, print_function
 
 from GaudiKernel.SystemOfUnits import GeV, MeV, mm, picosecond
 
-from PyConf.Algorithms import (
-    FunctionalParticleMaker,
-    LHCb__Phys__ParticleMakers__PhotonMaker as PhotonMaker,
-    LHCb__Phys__ParticleMakers__MergedPi0Maker as MergedPi0Maker,
-    Proto2ChargedBasic,
-)
-from PyConf.Tools import (LoKi__Hybrid__ProtoParticleFilter as
-                          ProtoParticleFilter, LoKi__Hybrid__TrackSelector as
-                          TrackSelector)
-
 from PyConf import configurable
 
+from PyConf.Algorithms import (
+    FunctionalParticleMaker, LHCb__Phys__ParticleMakers__PhotonMaker as
+    PhotonMaker, LHCb__Phys__ParticleMakers__MergedPi0Maker as MergedPi0Maker,
+    Proto2ChargedBasic)
+
 from .algorithms_pyconf import (
     require_all,
     ParticleFilter,
@@ -40,7 +35,9 @@ from .algorithms_pyconf import (
     NeutralParticleCombinerWithPVs,
 )
 
-from .hacks import patched_hybrid_tool
+from .selectors import get_all_track_selector, get_long_track_selector, get_down_track_selector
+from .filters import all_protoparticle_filter as standard_protoparticle_filter
+
 from .reco_objects import (
     make_charged_protoparticles as _make_charged_protoparticles, make_pvs as
     _make_pvs, make_neutral_protoparticles as _make_neutral_protoparticles)
@@ -49,32 +46,6 @@ _KAON0_M = 497.611 * MeV  # +/- 0.013, PDG, PR D98, 030001 and 2019 update
 _LAMBDA_M = 1115.683 * MeV  # +/- 0.006, PDG, PR D98, 030001 and 2019 update
 
 
-@configurable
-def get_all_track_selector(Code='TrALL', **kwargs):
-    return TrackSelector(Code=Code, **kwargs)
-
-
-@configurable
-def get_long_track_selector(Code='TrALL', **kwargs):
-    return TrackSelector(Code=require_all('TrLONG', Code), **kwargs)
-
-
-@configurable
-def get_down_track_selector(Code='TrALL', **kwargs):
-    return TrackSelector(Code=require_all('TrDOWNSTREAM', Code), **kwargs)
-
-
-@configurable
-def get_upstream_track_selector(Code='TrALL', **kwargs):
-    return TrackSelector(Code=require_all('TrUPSTREAM', Code), **kwargs)
-
-
-@configurable
-def standard_protoparticle_filter(Code='PP_ALL', **kwargs):
-    return ProtoParticleFilter(
-        Code=Code, Factory=patched_hybrid_tool('PPFactory'), **kwargs)
-
-
 @configurable
 def _make_particles(species,
                     make_protoparticles=_make_charged_protoparticles,
-- 
GitLab