From 9a93721a2be749f741e60224c3690fd9daea2e51 Mon Sep 17 00:00:00 2001
From: Grigore Tarna <grigore.tarna@cern.ch>
Date: Mon, 9 Aug 2021 18:27:40 +0000
Subject: [PATCH] Truth xAOD generator filters

---
 .../GeneratorFilters/xAODElectronFilter.h     |  33 +++
 .../GeneratorFilters/xAODMissingEtFilter.h    |  29 +++
 .../GeneratorFilters/xAODMultiLeptonFilter.h  |  24 ++
 .../GeneratorFilters/xAODMultiMuonFilter.h    |  27 ++
 .../GeneratorFilters/xAODMuonFilter.h         |  26 ++
 .../GeneratorFilters/xAODPhotonFilter.h       |  28 ++
 .../xAODTruthParticleSlimmerElectron.h        |  41 +++
 .../xAODTruthParticleSlimmerMET.h             |  43 +++
 .../xAODTruthParticleSlimmerMuon.h            |  39 +++
 .../xAODTruthParticleSlimmerPhoton.h          |  41 +++
 .../share/common/CreatexAODSlimContainers.py  |  33 +++
 .../src/TauTruthParticleSlimmer.cxx           | 245 +++++++++---------
 .../components/GeneratorFilters_entries.cxx   |  22 ++
 .../src/xAODElectronFilter.cxx                |  44 ++++
 .../src/xAODMissingEtFilter.cxx               |  41 +++
 .../src/xAODMultiLeptonFilter.cxx             |  72 +++++
 .../src/xAODMultiMuonFilter.cxx               |  47 ++++
 .../GeneratorFilters/src/xAODMuonFilter.cxx   |  37 +++
 .../GeneratorFilters/src/xAODPhotonFilter.cxx |  54 ++++
 .../src/xAODTruthParticleSlimmerElectron.cxx  |  96 +++++++
 .../src/xAODTruthParticleSlimmerMET.cxx       | 156 +++++++++++
 .../src/xAODTruthParticleSlimmerMuon.cxx      |  93 +++++++
 .../src/xAODTruthParticleSlimmerPhoton.cxx    |  96 +++++++
 23 files changed, 1246 insertions(+), 121 deletions(-)
 create mode 100644 Generators/GeneratorFilters/GeneratorFilters/xAODElectronFilter.h
 create mode 100644 Generators/GeneratorFilters/GeneratorFilters/xAODMissingEtFilter.h
 create mode 100644 Generators/GeneratorFilters/GeneratorFilters/xAODMultiLeptonFilter.h
 create mode 100644 Generators/GeneratorFilters/GeneratorFilters/xAODMultiMuonFilter.h
 create mode 100644 Generators/GeneratorFilters/GeneratorFilters/xAODMuonFilter.h
 create mode 100644 Generators/GeneratorFilters/GeneratorFilters/xAODPhotonFilter.h
 create mode 100644 Generators/GeneratorFilters/GeneratorFilters/xAODTruthParticleSlimmerElectron.h
 create mode 100644 Generators/GeneratorFilters/GeneratorFilters/xAODTruthParticleSlimmerMET.h
 create mode 100644 Generators/GeneratorFilters/GeneratorFilters/xAODTruthParticleSlimmerMuon.h
 create mode 100644 Generators/GeneratorFilters/GeneratorFilters/xAODTruthParticleSlimmerPhoton.h
 create mode 100644 Generators/GeneratorFilters/share/common/CreatexAODSlimContainers.py
 create mode 100644 Generators/GeneratorFilters/src/xAODElectronFilter.cxx
 create mode 100644 Generators/GeneratorFilters/src/xAODMissingEtFilter.cxx
 create mode 100644 Generators/GeneratorFilters/src/xAODMultiLeptonFilter.cxx
 create mode 100644 Generators/GeneratorFilters/src/xAODMultiMuonFilter.cxx
 create mode 100644 Generators/GeneratorFilters/src/xAODMuonFilter.cxx
 create mode 100644 Generators/GeneratorFilters/src/xAODPhotonFilter.cxx
 create mode 100644 Generators/GeneratorFilters/src/xAODTruthParticleSlimmerElectron.cxx
 create mode 100644 Generators/GeneratorFilters/src/xAODTruthParticleSlimmerMET.cxx
 create mode 100644 Generators/GeneratorFilters/src/xAODTruthParticleSlimmerMuon.cxx
 create mode 100644 Generators/GeneratorFilters/src/xAODTruthParticleSlimmerPhoton.cxx

diff --git a/Generators/GeneratorFilters/GeneratorFilters/xAODElectronFilter.h b/Generators/GeneratorFilters/GeneratorFilters/xAODElectronFilter.h
new file mode 100644
index 000000000000..7ce6aa42860d
--- /dev/null
+++ b/Generators/GeneratorFilters/GeneratorFilters/xAODElectronFilter.h
@@ -0,0 +1,33 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GENERATORFILTERS_XAODELECTRONFILTER_H
+#define GENERATORFILTERS_XAODELECTRONFILTER_H
+
+#include "GeneratorModules/GenFilter.h"
+
+
+/// @brief  Filters and looks for electrons
+///
+/// This class allows the user to search for electrons or positrons. An event
+/// will pass the filter successfully if there is an electron or positron with
+/// p_t and eta in the specified range. Default is pt > 10 GeV and unlimited
+/// eta.  Please note that the parameters (energy, momenta) are in ATLAS units,
+/// i.e. CLHEP::MeV!
+///
+/// @author I Hinchliffe, December 2001
+class xAODElectronFilter : public GenFilter {
+public:
+
+  xAODElectronFilter(const std::string& name, ISvcLocator* pSvcLocator);
+  virtual StatusCode filterEvent();
+
+private:
+
+	double m_Ptmin;
+	double m_EtaRange;
+
+};
+
+#endif
diff --git a/Generators/GeneratorFilters/GeneratorFilters/xAODMissingEtFilter.h b/Generators/GeneratorFilters/GeneratorFilters/xAODMissingEtFilter.h
new file mode 100644
index 000000000000..d031e48fb876
--- /dev/null
+++ b/Generators/GeneratorFilters/GeneratorFilters/xAODMissingEtFilter.h
@@ -0,0 +1,29 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GENERATORFILTERS_XAODMISSINGETFILTER_H
+#define GENERATORFILTERS_XAODMISSINGETFILTER_H
+
+#include "GeneratorModules/GenFilter.h"
+#include "xAODTruth/TruthParticle.h"
+#include "xAODTruth/TruthParticleContainer.h"
+#include "xAODTruth/TruthParticleAuxContainer.h"
+
+
+/// Filters on total missing energy from nus and LSPs
+/// @author Seth Zenz, December 2005
+class xAODMissingEtFilter:public GenFilter {
+public:
+
+  xAODMissingEtFilter(const std::string& name, ISvcLocator* pSvcLocator);
+  virtual StatusCode filterEvent();
+
+ private:
+
+  double m_METmin;
+  bool m_useHadronicNu;
+
+};
+
+#endif
\ No newline at end of file
diff --git a/Generators/GeneratorFilters/GeneratorFilters/xAODMultiLeptonFilter.h b/Generators/GeneratorFilters/GeneratorFilters/xAODMultiLeptonFilter.h
new file mode 100644
index 000000000000..8028e60636de
--- /dev/null
+++ b/Generators/GeneratorFilters/GeneratorFilters/xAODMultiLeptonFilter.h
@@ -0,0 +1,24 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GENERATORFILTERS_XAODMULTILEPTONFILTER_H
+#define GENERATORFILTERS_XAODMULTILEPTONFILTER_H
+
+#include "GeneratorModules/GenFilter.h"
+
+class xAODMultiLeptonFilter : public GenFilter {
+public:
+
+  xAODMultiLeptonFilter(const std::string& name, ISvcLocator* pSvcLocator);
+  virtual StatusCode filterEvent();
+
+private:
+
+  double m_Ptmin;
+  double m_EtaRange;
+  int m_NLeptons;
+
+};
+
+#endif
diff --git a/Generators/GeneratorFilters/GeneratorFilters/xAODMultiMuonFilter.h b/Generators/GeneratorFilters/GeneratorFilters/xAODMultiMuonFilter.h
new file mode 100644
index 000000000000..9d9a3527dea8
--- /dev/null
+++ b/Generators/GeneratorFilters/GeneratorFilters/xAODMultiMuonFilter.h
@@ -0,0 +1,27 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GENERATORFILTERS_XAODMULTIMUONFILTER_H
+#define GENERATORFILTERS_XAODMULTIMUONFILTER_H
+
+#include "GeneratorModules/GenFilter.h"
+
+/// Filters and looks for muons
+/// @author I Hinchliffe,  December 2001
+/// @author G. Watts, Sep 2006
+class xAODMultiMuonFilter : public GenFilter {
+public:
+
+  xAODMultiMuonFilter(const std::string& name, ISvcLocator* pSvcLocator);
+  virtual StatusCode filterEvent();
+
+private:
+
+	double m_Ptmin;
+	double m_EtaRange;
+    int m_NMuons;
+
+};
+
+#endif
\ No newline at end of file
diff --git a/Generators/GeneratorFilters/GeneratorFilters/xAODMuonFilter.h b/Generators/GeneratorFilters/GeneratorFilters/xAODMuonFilter.h
new file mode 100644
index 000000000000..96cb990b90c9
--- /dev/null
+++ b/Generators/GeneratorFilters/GeneratorFilters/xAODMuonFilter.h
@@ -0,0 +1,26 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GENERATORFILTERS_XAODMUONFILTER_H
+#define GENERATORFILTERS_XAODMUONFILTER_H
+
+#include "GeneratorModules/GenFilter.h"
+
+/// Filters and looks for muons
+/// @author I Hinchliffe,  December 2001
+/// @author G. Watts, Sep 2006
+class xAODMuonFilter : public GenFilter {
+public:
+
+  xAODMuonFilter(const std::string& name, ISvcLocator* pSvcLocator);
+  virtual StatusCode filterEvent();
+
+private:
+
+	double m_Ptmin;
+	double m_EtaRange;
+
+};
+
+#endif
diff --git a/Generators/GeneratorFilters/GeneratorFilters/xAODPhotonFilter.h b/Generators/GeneratorFilters/GeneratorFilters/xAODPhotonFilter.h
new file mode 100644
index 000000000000..1eaec2128aef
--- /dev/null
+++ b/Generators/GeneratorFilters/GeneratorFilters/xAODPhotonFilter.h
@@ -0,0 +1,28 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GENERATORFILTERS_XAODPHOTONFILTER_H
+#define GENERATORFILTERS_XAODPHOTONFILTER_H
+
+#include "GeneratorModules/GenFilter.h"
+
+/// Filters and looks for photons
+/// @author I Hinchliffe, May 2004
+/// @author A Buckley, May 2012
+class xAODPhotonFilter : public GenFilter {
+public:
+
+  xAODPhotonFilter(const std::string& name, ISvcLocator* pSvcLocator);
+  virtual StatusCode filterEvent();
+
+private:
+
+  double m_Ptmin;
+  double m_Ptmax;
+  double m_EtaRange;
+  int m_NPhotons;
+
+};
+
+#endif
diff --git a/Generators/GeneratorFilters/GeneratorFilters/xAODTruthParticleSlimmerElectron.h b/Generators/GeneratorFilters/GeneratorFilters/xAODTruthParticleSlimmerElectron.h
new file mode 100644
index 000000000000..6623ab3a5d4f
--- /dev/null
+++ b/Generators/GeneratorFilters/GeneratorFilters/xAODTruthParticleSlimmerElectron.h
@@ -0,0 +1,41 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GENERATORFILTERS_XAODTRUTHPARTICLESLIMMERELECTRON_H
+#define GENERATORFILTERS_XAODTRUTHPARTICLESLIMMERELECTRON_H
+
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "xAODTruth/TruthEvent.h"
+#include "xAODTruth/TruthMetaDataContainer.h"
+
+/// @brief Algorithm to skim the xAOD truth particle container for xAOD electron filter
+///
+/// This algorithm is used to copy and skim the particles from the xAOD TruthParticles container,
+/// keeping just relevant taus from the event.
+/// The design of this class heavily mirrors the DerivationFramework::TruthCollectionMaker.
+///
+/// @author Jeff Dandoy <Jeff.Dandoy@cern.ch>
+class xAODTruthParticleSlimmerElectron : public AthAlgorithm
+{
+public:
+    /// Regular algorithm constructor
+    xAODTruthParticleSlimmerElectron(const std::string &name, ISvcLocator *svcLoc);
+    /// Function initialising the algorithm
+    virtual StatusCode initialize();
+    /// Function executing the algorithm
+    virtual StatusCode execute();
+
+private:
+    /// The key for the output xAOD truth containers
+    std::string m_xaodTruthParticleContainerNameElectron;
+    std::string m_xaodTruthParticleContainerName;
+
+    /// Selection values for keeping taus and leptons
+    double m_el_pt_selection; //in GeV
+    double m_abseta_selection;
+
+}; // class xAODTruthParticleSlimmerElectron
+
+#endif //GENERATORFILTERS_XAODTRUTHPARTICLESLIMMERELECTRON_H
\ No newline at end of file
diff --git a/Generators/GeneratorFilters/GeneratorFilters/xAODTruthParticleSlimmerMET.h b/Generators/GeneratorFilters/GeneratorFilters/xAODTruthParticleSlimmerMET.h
new file mode 100644
index 000000000000..f4fa33c35cb8
--- /dev/null
+++ b/Generators/GeneratorFilters/GeneratorFilters/xAODTruthParticleSlimmerMET.h
@@ -0,0 +1,43 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GENERATORFILTERS_XAODTRUTHPARTICLESLIMMERPHOMET_H
+#define GENERATORFILTERS_XAODTRUTHPARTICLESLIMMERPHOMET_H
+
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "xAODTruth/TruthEvent.h"
+#include "xAODTruth/TruthMetaDataContainer.h"
+
+/// @brief Algorithm to skim the xAOD truth particle container for xAOD MET filter
+///
+/// This algorithm is used to copy and skim the particles from the xAOD TruthParticles container,
+/// keeping just relevant MET particles from the event.
+/// The design of this class heavily mirrors the DerivationFramework::TruthCollectionMaker.
+///
+/// @author Jeff Dandoy <Jeff.Dandoy@cern.ch>
+class xAODTruthParticleSlimmerMET : public AthAlgorithm
+{
+public:
+    /// Regular algorithm constructor
+    xAODTruthParticleSlimmerMET(const std::string &name, ISvcLocator *svcLoc);
+    /// Function initialising the algorithm
+    virtual StatusCode initialize();
+    /// Function executing the algorithm
+    virtual StatusCode execute();
+
+private:
+    /// The key for the output xAOD truth containers
+    std::string m_xaodTruthParticleContainerNameMET;
+    std::string m_xaodTruthParticleContainerName;
+
+    /// Selection values for keeping METs
+    //double m_MET_pt_selection; //in GeV
+
+    bool fromTau( const xAOD::TruthParticle* tp ) const;
+    bool fromWZ( const xAOD::TruthParticle* tp ) const;
+
+}; // class xAODTruthParticleSlimmerMET
+
+#endif //GENERATORFILTERS_XAODTRUTHPARTICLESLIMMERPHOMET_H
\ No newline at end of file
diff --git a/Generators/GeneratorFilters/GeneratorFilters/xAODTruthParticleSlimmerMuon.h b/Generators/GeneratorFilters/GeneratorFilters/xAODTruthParticleSlimmerMuon.h
new file mode 100644
index 000000000000..62ba4fafda52
--- /dev/null
+++ b/Generators/GeneratorFilters/GeneratorFilters/xAODTruthParticleSlimmerMuon.h
@@ -0,0 +1,39 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GENERATORFILTERS_XAODTRUTHPARTICLESLIMMERMUON_H
+#define GENERATORFILTERS_XAODTRUTHPARTICLESLIMMERMUON_H
+
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "xAODTruth/TruthEvent.h"
+#include "xAODTruth/TruthMetaDataContainer.h"
+
+/// @brief Algorithm to skim the xAOD truth particle container for xAOD muons filter
+///
+/// This algorithm is used to copy and skim the particles from the xAOD TruthParticles container,
+/// keeping just relevant muons from the event.
+/// The design of this class heavily mirrors the DerivationFramework::TruthCollectionMaker.
+///
+/// @author Jeff Dandoy <Jeff.Dandoy@cern.ch>
+class xAODTruthParticleSlimmerMuon : public AthAlgorithm
+{
+public:
+    /// Regular algorithm constructor
+    xAODTruthParticleSlimmerMuon(const std::string &name, ISvcLocator *svcLoc);
+    /// Function initialising the algorithm
+    virtual StatusCode initialize();
+    /// Function executing the algorithm
+    virtual StatusCode execute();
+
+private:
+    /// The key for the output xAOD truth containers
+    std::string m_xaodTruthParticleContainerNameMuon;
+    std::string m_xaodTruthParticleContainerName;
+
+    /// Selection values for keeping muons
+
+}; // class xAODTruthParticleSlimmerMuon
+
+#endif //GENERATORFILTERS_XAODTRUTHPARTICLESLIMMERMUON_H
\ No newline at end of file
diff --git a/Generators/GeneratorFilters/GeneratorFilters/xAODTruthParticleSlimmerPhoton.h b/Generators/GeneratorFilters/GeneratorFilters/xAODTruthParticleSlimmerPhoton.h
new file mode 100644
index 000000000000..d4877d840df7
--- /dev/null
+++ b/Generators/GeneratorFilters/GeneratorFilters/xAODTruthParticleSlimmerPhoton.h
@@ -0,0 +1,41 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GENERATORFILTERS_XAODTRUTHPARTICLESLIMMERPHOTON_H
+#define GENERATORFILTERS_XAODTRUTHPARTICLESLIMMERPHOTON_H
+
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "xAODTruth/TruthEvent.h"
+#include "xAODTruth/TruthMetaDataContainer.h"
+
+/// @brief Algorithm to skim the xAOD truth particle container for xAOD photons filter
+///
+/// This algorithm is used to copy and skim the particles from the xAOD TruthParticles container,
+/// keeping just relevant photons from the event.
+/// The design of this class heavily mirrors the DerivationFramework::TruthCollectionMaker.
+///
+/// @author Jeff Dandoy <Jeff.Dandoy@cern.ch>
+class xAODTruthParticleSlimmerPhoton : public AthAlgorithm
+{
+public:
+    /// Regular algorithm constructor
+    xAODTruthParticleSlimmerPhoton(const std::string &name, ISvcLocator *svcLoc);
+    /// Function initialising the algorithm
+    virtual StatusCode initialize();
+    /// Function executing the algorithm
+    virtual StatusCode execute();
+
+private:
+    /// The key for the output xAOD truth containers
+    std::string m_xaodTruthParticleContainerNamePhoton;
+    std::string m_xaodTruthParticleContainerName;
+
+    /// Selection values for keeping photons
+    double m_photon_pt_selection; //in GeV
+    double m_abseta_selection;
+
+}; // class xAODTruthParticleSlimmerPhoton
+
+#endif //GENERATORFILTERS_XAODTRUTHPARTICLESLIMMERPHOTON_H
\ No newline at end of file
diff --git a/Generators/GeneratorFilters/share/common/CreatexAODSlimContainers.py b/Generators/GeneratorFilters/share/common/CreatexAODSlimContainers.py
new file mode 100644
index 000000000000..5d721555f037
--- /dev/null
+++ b/Generators/GeneratorFilters/share/common/CreatexAODSlimContainers.py
@@ -0,0 +1,33 @@
+if not hasattr(prefiltSeq, 'xAODCnv'):
+    from xAODTruthCnv.xAODTruthCnvConf import xAODMaker__xAODTruthCnvAlg
+    prefiltSeq += xAODMaker__xAODTruthCnvAlg('xAODCnv',WriteTruthMetaData=False)
+    prefiltSeq.xAODCnv.AODContainerName = 'GEN_EVENT'
+
+def createxAODSlimmedContainer(container_name,prefiltSeq):
+    if container_name=="TruthElectrons":
+        if not hasattr(prefiltSeq, "xAODTruthParticleSlimmerElectron"):
+            from GeneratorFilters.GeneratorFiltersConf import xAODTruthParticleSlimmerElectron
+            prefiltSeq += xAODTruthParticleSlimmerElectron('xAODTruthParticleSlimmerElectron')
+    elif container_name=="TruthMuons":
+        if not hasattr(prefiltSeq, "xAODTruthParticleSlimmerMuon"):
+            from GeneratorFilters.GeneratorFiltersConf import xAODTruthParticleSlimmerMuon
+            prefiltSeq += xAODTruthParticleSlimmerMuon('xAODTruthParticleSlimmerMuon')
+    elif container_name=="TruthTaus":
+        if not hasattr(prefiltSeq, "TauTruthParticleSlimmer"):
+            from GeneratorFilters.GeneratorFiltersConf import TauTruthParticleSlimmer
+            prefiltSeq += TauTruthParticleSlimmer('TauTruthParticleSlimmer')
+    elif container_name=="TruthPhotons":
+        if not hasattr(prefiltSeq, "xAODTruthParticleSlimmerPhoton"):
+            from GeneratorFilters.GeneratorFiltersConf import xAODTruthParticleSlimmerPhoton
+            prefiltSeq += xAODTruthParticleSlimmerPhoton('xAODTruthParticleSlimmerPhoton')
+    elif container_name=="TruthMET":
+        if not hasattr(prefiltSeq, "xAODTruthParticleSlimmerMET"):
+            from GeneratorFilters.GeneratorFiltersConf import xAODTruthParticleSlimmerMET
+            prefiltSeq += xAODTruthParticleSlimmerMET('xAODTruthParticleSlimmerMET')       
+    else:
+        from AthenaCommon.Logging import logging
+        msg_logger = logging.getLogger("CreatexAODSlimContainers ")       
+        msg_logger.fatal("GeneratorFilters/CreatexAODSlimmedContainers -> container "+container_name+ " not implemented yet!!!")
+        theApp.exit(-1)
+
+
diff --git a/Generators/GeneratorFilters/src/TauTruthParticleSlimmer.cxx b/Generators/GeneratorFilters/src/TauTruthParticleSlimmer.cxx
index 8c52428031a0..ac53e4ed1969 100644
--- a/Generators/GeneratorFilters/src/TauTruthParticleSlimmer.cxx
+++ b/Generators/GeneratorFilters/src/TauTruthParticleSlimmer.cxx
@@ -22,157 +22,160 @@
 
 #include "GeneratorFilters/TauTruthParticleSlimmer.h"
 
-
 using namespace std;
 
-    
-TauTruthParticleSlimmer::TauTruthParticleSlimmer( const string& name, ISvcLocator* svcLoc )
-: AthAlgorithm( name, svcLoc ), m_classifier("MCTruthClassifier/MCTruthClassifier")
+TauTruthParticleSlimmer::TauTruthParticleSlimmer(const string &name, ISvcLocator *svcLoc)
+    : AthAlgorithm(name, svcLoc), m_classifier("MCTruthClassifier/MCTruthClassifier")
 {
-    declareProperty("xAODTruthParticleContainerName", m_xaodTruthParticleContainerName="TruthParticles" );
-    declareProperty("xAODTruthTauParticleContainerName", m_xaodTruthTauParticleContainerName="TruthTaus" );
-    declareProperty( "ForceRerun", m_forceRerun = false);
-    declareProperty("tau_pt_selection", m_tau_pt_selection=1.*Gaudi::Units::GeV ); //User provides units in MeV!
-    declareProperty("abseta_selection", m_abseta_selection=4.5 );
+  declareProperty("xAODTruthParticleContainerName", m_xaodTruthParticleContainerName = "TruthParticles");
+  declareProperty("xAODTruthTauParticleContainerName", m_xaodTruthTauParticleContainerName = "TruthTaus");
+  declareProperty("ForceRerun", m_forceRerun = false);
+  declareProperty("tau_pt_selection", m_tau_pt_selection = 1. * Gaudi::Units::GeV); //User provides units in MeV!
+  declareProperty("abseta_selection", m_abseta_selection = 4.5);
 }
 
+StatusCode TauTruthParticleSlimmer::initialize()
+{
+  ATH_CHECK(m_classifier.retrieve());
 
-StatusCode TauTruthParticleSlimmer::initialize() {
-    ATH_CHECK(m_classifier.retrieve());
-
-    ATH_MSG_INFO("xAOD input TruthParticleContainer name = " << m_xaodTruthParticleContainerName );
-    ATH_MSG_INFO("xAOD output TruthTauParticleContainer name = " << m_xaodTruthTauParticleContainerName );
-    return StatusCode::SUCCESS;
+  ATH_MSG_INFO("xAOD input TruthParticleContainer name = " << m_xaodTruthParticleContainerName);
+  ATH_MSG_INFO("xAOD output TruthTauParticleContainer name = " << m_xaodTruthTauParticleContainerName);
+  return StatusCode::SUCCESS;
 }
 
-CLHEP::HepLorentzVector TauTruthParticleSlimmer::sumDaughterNeutrinos( const xAOD::TruthParticle* part ) {
-  CLHEP::HepLorentzVector nu( 0, 0, 0, 0);
-  if ( ( (std::abs( part->pdgId() ) == 12 ) || ( std::abs( part->pdgId() ) == 14 ) || ( std::abs( part->pdgId() ) == 16 ))
-       && part->status() != 3) {
+CLHEP::HepLorentzVector TauTruthParticleSlimmer::sumDaughterNeutrinos(const xAOD::TruthParticle *part)
+{
+  CLHEP::HepLorentzVector nu(0, 0, 0, 0);
+  if (((std::abs(part->pdgId()) == 12) || (std::abs(part->pdgId()) == 14) || (std::abs(part->pdgId()) == 16)) && part->status() != 3)
+  {
     nu.setPx(part->px());
     nu.setPy(part->py());
     nu.setPz(part->pz());
     nu.setE(part->e());
   }
-  if (!part->hasDecayVtx()) return nu;
-  
-  for (size_t n=0;n<part->nChildren();++n)
-      nu += sumDaughterNeutrinos(part->child(n));
-  
+  if (!part->hasDecayVtx())
+    return nu;
+
+  for (size_t n = 0; n < part->nChildren(); ++n)
+    nu += sumDaughterNeutrinos(part->child(n));
+
   return nu;
 }
 
+StatusCode TauTruthParticleSlimmer::execute()
+{
 
+  CLHEP::HepLorentzVector nutau;
 
-StatusCode TauTruthParticleSlimmer::execute() {
-    
-     CLHEP::HepLorentzVector nutau;
-    
-    // If the containers already exists then assume that nothing needs to be done
-    if ( evtStore()->contains< xAOD::TruthParticleContainer >(m_xaodTruthTauParticleContainerName) &&
-        !m_forceRerun) {
-        ATH_MSG_WARNING("xAOD Tau Truth Particles are already available in the event");
-        return StatusCode::SUCCESS;
-    }
-    
-
-    // Create new output container
-    xAOD::TruthParticleContainer* xTruthTauParticleContainer = new xAOD::TruthParticleContainer();
-    CHECK( evtStore()->record( xTruthTauParticleContainer, m_xaodTruthTauParticleContainerName ) );
-    xAOD::TruthParticleAuxContainer* xTruthTauParticleAuxContainer = new xAOD::TruthParticleAuxContainer();
-    CHECK( evtStore()->record( xTruthTauParticleAuxContainer, m_xaodTruthTauParticleContainerName + "Aux." ) );
-    xTruthTauParticleContainer->setStore( xTruthTauParticleAuxContainer );
-    ATH_MSG_INFO( "Recorded TruthTauParticleContainer with key: " << m_xaodTruthTauParticleContainerName );
-
-    // Retrieve full TruthParticle container
-    const xAOD::TruthParticleContainer* xTruthParticleContainer;
-    if (evtStore()->retrieve(xTruthParticleContainer, m_xaodTruthParticleContainerName).isFailure()) {
-        ATH_MSG_ERROR("No TruthParticle collection with name " << m_xaodTruthParticleContainerName << " found in StoreGate!");
-        return StatusCode::FAILURE;
-    }
+  // If the containers already exists then assume that nothing needs to be done
+  if (evtStore()->contains<xAOD::TruthParticleContainer>(m_xaodTruthTauParticleContainerName) &&
+      !m_forceRerun)
+  {
+    ATH_MSG_WARNING("xAOD Tau Truth Particles are already available in the event");
+    return StatusCode::SUCCESS;
+  }
 
-    // Set up decorators
-
-    const static SG::AuxElement::Decorator<unsigned int> originDecorator("classifierParticleOrigin");
-    const static SG::AuxElement::Decorator<unsigned int> typeDecorator("classifierParticleType");
-    const static SG::AuxElement::Decorator<unsigned int> outcomeDecorator("classifierParticleOutCome");
-    const static SG::AuxElement::Decorator<unsigned int> classificationDecorator("Classification");
-    const static SG::AuxElement::Decorator<int> parenthadronPIDDecorator("parentHadronID");
-
-   // sum of neutrinos 4-vector in tau decay products
-    const static SG::AuxElement::Decorator< CLHEP::HepLorentzVector > nuDecorator("nuVector");
-    const static SG::AuxElement::Decorator< int > tauTypeDecorator("tauType");
-
-    // Loop over full TruthParticle container
-    unsigned int nParticles = xTruthParticleContainer->size();
-    for (unsigned int iPart=0; iPart<nParticles; ++iPart) {
-      ElementLink<xAOD::TruthParticleContainer> eltp(*xTruthParticleContainer,iPart);
-      const xAOD::TruthParticle* theParticle = (*xTruthParticleContainer)[iPart];
-      
-      int this_absPdgID = theParticle->absPdgId();
-      float this_abseta = theParticle->abseta();
-      float this_pt =  theParticle->pt();
-      int this_status = theParticle->status();
-
-      //Save Taus above 1 GeV, & within detector acceptance (4.5)
-      // we want to avoid status 3 taus
-      if(  this_status !=3 && this_absPdgID == 15 && this_pt >= m_tau_pt_selection && this_abseta < m_abseta_selection ){
-        xAOD::TruthParticle* xTruthParticle = new xAOD::TruthParticle();
-        
-        xTruthTauParticleContainer->push_back( xTruthParticle );
-
-        // Fill with numerical content
-        xTruthParticle->setPdgId(theParticle->pdgId());
-        xTruthParticle->setBarcode(theParticle->barcode());
-        xTruthParticle->setStatus(theParticle->status());
-        xTruthParticle->setM(theParticle->m());
-        xTruthParticle->setPx(theParticle->px());
-        xTruthParticle->setPy(theParticle->py());
-        xTruthParticle->setPz(theParticle->pz());
-        xTruthParticle->setE(theParticle->e());
-
-        const xAOD::TruthParticle* tau = theParticle; 
-        nutau = sumDaughterNeutrinos(tau);
-
-        nuDecorator(*xTruthParticle) = nutau;
-          
-        int tauType = 0; 
-        for (size_t n=0;n<tau->nChildren();++n){
-           if (tau->child(n)->absPdgId() == 12) tauType =1; //Tau decays into an electron
-           else if (tau->child(n)->absPdgId() == 14) tauType =2; //Tau decays into a muon
-           else if (tau->child(n)->absPdgId()  == 15 ) tauType = 11;  //Tau radiates a particle and decays into another tau
-}
-        tauTypeDecorator(*xTruthParticle) = tauType;
+  // Create new output container
+  xAOD::TruthParticleContainer *xTruthTauParticleContainer = new xAOD::TruthParticleContainer();
+  CHECK(evtStore()->record(xTruthTauParticleContainer, m_xaodTruthTauParticleContainerName));
+  xAOD::TruthParticleAuxContainer *xTruthTauParticleAuxContainer = new xAOD::TruthParticleAuxContainer();
+  CHECK(evtStore()->record(xTruthTauParticleAuxContainer, m_xaodTruthTauParticleContainerName + "Aux."));
+  xTruthTauParticleContainer->setStore(xTruthTauParticleAuxContainer);
+  ATH_MSG_INFO("Recorded TruthTauParticleContainer with key: " << m_xaodTruthTauParticleContainerName);
+
+  // Retrieve full TruthParticle container
+  const xAOD::TruthParticleContainer *xTruthParticleContainer;
+  if (evtStore()->retrieve(xTruthParticleContainer, m_xaodTruthParticleContainerName).isFailure())
+  {
+    ATH_MSG_ERROR("No TruthParticle collection with name " << m_xaodTruthParticleContainerName << " found in StoreGate!");
+    return StatusCode::FAILURE;
+  }
 
+  // Set up decorators
+
+  const static SG::AuxElement::Decorator<unsigned int> originDecorator("classifierParticleOrigin");
+  const static SG::AuxElement::Decorator<unsigned int> typeDecorator("classifierParticleType");
+  const static SG::AuxElement::Decorator<unsigned int> outcomeDecorator("classifierParticleOutCome");
+  const static SG::AuxElement::Decorator<unsigned int> classificationDecorator("Classification");
+  const static SG::AuxElement::Decorator<int> parenthadronPIDDecorator("parentHadronID");
+
+  // sum of neutrinos 4-vector in tau decay products
+  const static SG::AuxElement::Decorator<CLHEP::HepLorentzVector> nuDecorator("nuVector");
+  const static SG::AuxElement::Decorator<int> tauTypeDecorator("tauType");
+
+  // Loop over full TruthParticle container
+  unsigned int nParticles = xTruthParticleContainer->size();
+  for (unsigned int iPart = 0; iPart < nParticles; ++iPart)
+  {
+    ElementLink<xAOD::TruthParticleContainer> eltp(*xTruthParticleContainer, iPart);
+    const xAOD::TruthParticle *theParticle = (*xTruthParticleContainer)[iPart];
+
+    int this_absPdgID = theParticle->absPdgId();
+    float this_abseta = theParticle->abseta();
+    float this_pt = theParticle->pt();
+    int this_status = theParticle->status();
+
+    //Save Taus above 1 GeV, & within detector acceptance (4.5)
+    // we want to avoid status 3 taus
+    if (this_status != 3 && this_absPdgID == 15 && this_pt >= m_tau_pt_selection && this_abseta < m_abseta_selection)
+    {
+      xAOD::TruthParticle *xTruthParticle = new xAOD::TruthParticle();
+
+      xTruthTauParticleContainer->push_back(xTruthParticle);
+
+      // Fill with numerical content
+      xTruthParticle->setPdgId(theParticle->pdgId());
+      xTruthParticle->setBarcode(theParticle->barcode());
+      xTruthParticle->setStatus(theParticle->status());
+      xTruthParticle->setM(theParticle->m());
+      xTruthParticle->setPx(theParticle->px());
+      xTruthParticle->setPy(theParticle->py());
+      xTruthParticle->setPz(theParticle->pz());
+      xTruthParticle->setE(theParticle->e());
+
+      const xAOD::TruthParticle *tau = theParticle;
+      nutau = sumDaughterNeutrinos(tau);
+
+      nuDecorator(*xTruthParticle) = nutau;
+
+      int tauType = 0;
+      for (size_t n = 0; n < tau->nChildren(); ++n)
+      {
+        if (tau->child(n)->absPdgId() == 12)
+          tauType = 1; //Tau decays into an electron
+        else if (tau->child(n)->absPdgId() == 14)
+          tauType = 2; //Tau decays into a muon
+        else if (tau->child(n)->absPdgId() == 15)
+          tauType = 11; //Tau radiates a particle and decays into another tau
+      }
+      tauTypeDecorator(*xTruthParticle) = tauType;
 
 #ifdef MCTRUTHCLASSIFIER_CONST
-        IMCTruthClassifier::Info info;
-        std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> classification = 
+      IMCTruthClassifier::Info info;
+      std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> classification =
           m_classifier->particleTruthClassifier(theParticle, &info);
-        unsigned int particleOutCome = info.particleOutCome;
+      unsigned int particleOutCome = info.particleOutCome;
 #else
-        std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> classification = 
+      std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> classification =
           m_classifier->particleTruthClassifier(theParticle);
-        unsigned int particleOutCome = m_classifier->getParticleOutCome();
+      unsigned int particleOutCome = m_classifier->getParticleOutCome();
 #endif
 
-        unsigned int result = (unsigned int)m_classifier->classify(theParticle);
+      unsigned int result = (unsigned int)m_classifier->classify(theParticle);
 
-        int hadron_pdg = (int)m_classifier->getParentHadronID(theParticle);
+      int hadron_pdg = (int)m_classifier->getParentHadronID(theParticle);
 
-        unsigned int particleType = classification.first;
-        unsigned int particleOrigin = classification.second;
-        typeDecorator(*xTruthParticle) = particleType;
-        originDecorator(*xTruthParticle) = particleOrigin;
-        outcomeDecorator(*xTruthParticle) = particleOutCome;  
-
-        classificationDecorator(*xTruthParticle) = result;
-        parenthadronPIDDecorator(*xTruthParticle) = hadron_pdg;
-      }
+      unsigned int particleType = classification.first;
+      unsigned int particleOrigin = classification.second;
+      typeDecorator(*xTruthParticle) = particleType;
+      originDecorator(*xTruthParticle) = particleOrigin;
+      outcomeDecorator(*xTruthParticle) = particleOutCome;
 
+      classificationDecorator(*xTruthParticle) = result;
+      parenthadronPIDDecorator(*xTruthParticle) = hadron_pdg;
+    }
 
-    } //end of loop over particles
+  } //end of loop over particles
 
-    return StatusCode::SUCCESS;
+  return StatusCode::SUCCESS;
 }
-
diff --git a/Generators/GeneratorFilters/src/components/GeneratorFilters_entries.cxx b/Generators/GeneratorFilters/src/components/GeneratorFilters_entries.cxx
index 49c58683721c..f38350132fa5 100644
--- a/Generators/GeneratorFilters/src/components/GeneratorFilters_entries.cxx
+++ b/Generators/GeneratorFilters/src/components/GeneratorFilters_entries.cxx
@@ -12,10 +12,21 @@
 #include "GeneratorFilters/QCDTruthJetFilter.h"
 #include "GeneratorFilters/TauFilter.h"
 #include "GeneratorFilters/xAODTauFilter.h"
+#include "GeneratorFilters/xAODElectronFilter.h"
+#include "GeneratorFilters/xAODMuonFilter.h"
+#include "GeneratorFilters/xAODPhotonFilter.h"
+#include "GeneratorFilters/xAODMultiLeptonFilter.h"
+#include "GeneratorFilters/xAODMultiMuonFilter.h"
+#include "GeneratorFilters/xAODMissingEtFilter.h"
+
 
 // slimmers for 22.6
 #include "GeneratorFilters/PileupTruthParticleSlimmer.h"
 #include "GeneratorFilters/TauTruthParticleSlimmer.h"
+#include "GeneratorFilters/xAODTruthParticleSlimmerElectron.h"
+#include "GeneratorFilters/xAODTruthParticleSlimmerMuon.h"
+#include "GeneratorFilters/xAODTruthParticleSlimmerPhoton.h"
+#include "GeneratorFilters/xAODTruthParticleSlimmerMET.h"
 
 
 
@@ -111,10 +122,21 @@ DECLARE_COMPONENT( MultiElecMuTauFilter )
 DECLARE_COMPONENT( QCDTruthJetFilter )
 DECLARE_COMPONENT( TauFilter )
 DECLARE_COMPONENT( xAODTauFilter )
+DECLARE_COMPONENT( xAODElectronFilter )
+DECLARE_COMPONENT( xAODMuonFilter )
+DECLARE_COMPONENT( xAODPhotonFilter )
+DECLARE_COMPONENT( xAODMultiLeptonFilter)
+DECLARE_COMPONENT( xAODMultiMuonFilter)
+DECLARE_COMPONENT( xAODMissingEtFilter)
+
 
 //slimmers accepted for 22.6
 DECLARE_COMPONENT( PileupTruthParticleSlimmer )
 DECLARE_COMPONENT( TauTruthParticleSlimmer )
+DECLARE_COMPONENT( xAODTruthParticleSlimmerElectron )
+DECLARE_COMPONENT( xAODTruthParticleSlimmerMuon )
+DECLARE_COMPONENT( xAODTruthParticleSlimmerPhoton)
+DECLARE_COMPONENT( xAODTruthParticleSlimmerMET)
 
 
 
diff --git a/Generators/GeneratorFilters/src/xAODElectronFilter.cxx b/Generators/GeneratorFilters/src/xAODElectronFilter.cxx
new file mode 100644
index 000000000000..507181975bda
--- /dev/null
+++ b/Generators/GeneratorFilters/src/xAODElectronFilter.cxx
@@ -0,0 +1,44 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "GeneratorFilters/xAODElectronFilter.h"
+#include "EventInfo/EventStreamInfo.h"
+#include "xAODTruth/TruthParticle.h"
+#include "xAODTruth/TruthParticleContainer.h"
+#include "xAODTruth/TruthParticleAuxContainer.h"
+
+#include "GaudiKernel/ServiceHandle.h"
+
+xAODElectronFilter::xAODElectronFilter(const std::string &name, ISvcLocator *pSvcLocator)
+    : GenFilter(name, pSvcLocator)
+{
+  declareProperty("Ptcut", m_Ptmin = 10000.);
+  declareProperty("Etacut", m_EtaRange = 10.0);
+}
+
+StatusCode xAODElectronFilter::filterEvent() {
+  // Retrieve full TruthParticle container
+  const xAOD::TruthParticleContainer *xTruthParticleContainer;
+  if (evtStore()->retrieve(xTruthParticleContainer, "TruthElectrons").isFailure())
+  {
+    ATH_MSG_ERROR("No TruthParticle collection with name "
+                  << "TruthElectrons"
+                  << " found in StoreGate!");
+    return StatusCode::FAILURE;
+  }
+
+  unsigned int nParticles = xTruthParticleContainer->size();
+  for (unsigned int iPart = 0; iPart < nParticles; ++iPart)
+  {
+    const xAOD::TruthParticle *part = (*xTruthParticleContainer)[iPart];
+
+     //electron
+    if (part->pt() >= m_Ptmin && part->abseta() <= m_EtaRange)
+      return StatusCode::SUCCESS;
+  }
+  
+  setFilterPassed(false);
+  return StatusCode::SUCCESS;
+}
+
diff --git a/Generators/GeneratorFilters/src/xAODMissingEtFilter.cxx b/Generators/GeneratorFilters/src/xAODMissingEtFilter.cxx
new file mode 100644
index 000000000000..93d4b4b00941
--- /dev/null
+++ b/Generators/GeneratorFilters/src/xAODMissingEtFilter.cxx
@@ -0,0 +1,41 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "GeneratorFilters/xAODMissingEtFilter.h"
+#include "TruthUtils/PIDHelpers.h"
+
+
+xAODMissingEtFilter::xAODMissingEtFilter(const std::string& name, ISvcLocator* pSvcLocator)
+  : GenFilter(name,pSvcLocator)
+{
+  declareProperty("METCut",m_METmin = 10000.);
+  // Normally we'd include them, but this is unstable if using EvtGen
+  declareProperty("UseNeutrinosFromHadrons",m_useHadronicNu = false);
+}
+
+
+StatusCode xAODMissingEtFilter::filterEvent() {
+    
+  // Retrieve TruthMET container from xAOD MET slimmer, contains (MC::isGenStable() && MC::isNonInteracting()) particles
+  const xAOD::TruthParticleContainer* xTruthParticleContainer;
+  if (evtStore()->retrieve(xTruthParticleContainer, "TruthMET").isFailure()) {
+      ATH_MSG_ERROR("No TruthParticle collection with name " << "TruthMET" << " found in StoreGate!");
+      return StatusCode::FAILURE;
+  }
+
+  double sumx(0), sumy(0);
+  unsigned int nParticles = xTruthParticleContainer->size();
+  for (unsigned int iPart=0; iPart<nParticles; ++iPart) {
+    const xAOD::TruthParticle* missingETparticle = (*xTruthParticleContainer)[iPart];
+    if (!m_useHadronicNu && MC::PID::isNeutrino(missingETparticle->pdgId()) &&
+    !(missingETparticle->auxdata<bool>("isFromWZ") || missingETparticle->auxdata<bool>("isFromTau")) ) continue;
+    sumx += missingETparticle->px();
+    sumy += missingETparticle->py();
+  }
+
+  double met = std::sqrt(sumx*sumx + sumy*sumy);
+  setFilterPassed(met >= m_METmin);
+  return StatusCode::SUCCESS;
+}
+
diff --git a/Generators/GeneratorFilters/src/xAODMultiLeptonFilter.cxx b/Generators/GeneratorFilters/src/xAODMultiLeptonFilter.cxx
new file mode 100644
index 000000000000..834ec37abd37
--- /dev/null
+++ b/Generators/GeneratorFilters/src/xAODMultiLeptonFilter.cxx
@@ -0,0 +1,72 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "GeneratorFilters/xAODMultiLeptonFilter.h"
+#include "EventInfo/EventStreamInfo.h"
+#include "xAODTruth/TruthParticle.h"
+#include "xAODTruth/TruthParticleContainer.h"
+#include "xAODTruth/TruthParticleAuxContainer.h"
+
+
+xAODMultiLeptonFilter::xAODMultiLeptonFilter(const std::string& name, ISvcLocator* pSvcLocator)
+: GenFilter(name, pSvcLocator)
+{
+  declareProperty("Ptcut", m_Ptmin = 10000.);
+  declareProperty("Etacut", m_EtaRange = 10.0);
+  declareProperty("NLeptons", m_NLeptons = 4);
+}
+
+
+StatusCode xAODMultiLeptonFilter::filterEvent() {
+  
+  // Retrieve TruthElectrons  container
+  const xAOD::TruthParticleContainer* xTruthParticleContainerElectron;
+  if (evtStore()->retrieve(xTruthParticleContainerElectron, "TruthElectrons").isFailure()) {
+      ATH_MSG_ERROR("No TruthParticle collection with name " << "TruthElectrons" << " found in StoreGate!");
+      return StatusCode::FAILURE;
+  }
+  // Retrieve TruthMuons container
+  const xAOD::TruthParticleContainer* xTruthParticleContainerMuon;
+  if (evtStore()->retrieve(xTruthParticleContainerMuon, "TruthMuons").isFailure()) {
+      ATH_MSG_ERROR("No TruthParticle collection with name " << "TruthMuons" << " found in StoreGate!");
+      return StatusCode::FAILURE;
+  }
+  int numLeptons = 0;
+
+  unsigned int nParticlesElectrons = xTruthParticleContainerElectron->size();
+  for (unsigned int iPart=0; iPart<nParticlesElectrons; ++iPart) {
+    const xAOD::TruthParticle* part = (*xTruthParticleContainerElectron)[iPart];
+
+    if (part->status()==1 && part->absPdgId()==11) //electron 
+        if(  part->pt()>= m_Ptmin && part->abseta() <= m_EtaRange )
+        {
+          numLeptons += 1;
+          if (numLeptons >= m_NLeptons)
+          {
+            setFilterPassed(true);
+            return StatusCode::SUCCESS;
+          }
+        }       
+  }
+
+  unsigned int nParticlesMuons = xTruthParticleContainerMuon->size();
+  for (unsigned int iPart=0; iPart<nParticlesMuons; ++iPart) {
+    const xAOD::TruthParticle* part = (*xTruthParticleContainerMuon)[iPart];
+
+    if (part->status()==1 && part->absPdgId()==13) //Muon 
+        if(  part->pt()>= m_Ptmin && part->abseta() <= m_EtaRange )
+        {
+          numLeptons += 1;
+          if (numLeptons >= m_NLeptons)
+          {
+            setFilterPassed(true);
+            return StatusCode::SUCCESS;
+          }
+        }      
+  }
+  
+  setFilterPassed(false);
+  return StatusCode::SUCCESS;
+
+}
diff --git a/Generators/GeneratorFilters/src/xAODMultiMuonFilter.cxx b/Generators/GeneratorFilters/src/xAODMultiMuonFilter.cxx
new file mode 100644
index 000000000000..ce7b8da2e880
--- /dev/null
+++ b/Generators/GeneratorFilters/src/xAODMultiMuonFilter.cxx
@@ -0,0 +1,47 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "GeneratorFilters/xAODMultiMuonFilter.h"
+#include "EventInfo/EventStreamInfo.h"
+#include "xAODTruth/TruthParticle.h"
+#include "xAODTruth/TruthParticleContainer.h"
+#include "xAODTruth/TruthParticleAuxContainer.h"
+
+xAODMultiMuonFilter::xAODMultiMuonFilter(const std::string& name, ISvcLocator* pSvcLocator)
+  : GenFilter(name,pSvcLocator)
+{
+  declareProperty("Ptcut",m_Ptmin = 10000.);
+  declareProperty("Etacut",m_EtaRange = 10.0);
+  declareProperty("NMuons",m_NMuons = 2);
+}
+
+
+StatusCode xAODMultiMuonFilter::filterEvent() {  
+  // Retrieve TruthMuons container
+  const xAOD::TruthParticleContainer* xTruthParticleContainer;
+  if (evtStore()->retrieve(xTruthParticleContainer, "TruthMuons").isFailure()) {
+      ATH_MSG_ERROR("No TruthParticle collection with name " << "TruthMuons" << " found in StoreGate!");
+      return StatusCode::FAILURE;
+  }
+  int numMuons = 0;
+  unsigned int nParticles = xTruthParticleContainer->size();
+  for (unsigned int iPart=0; iPart<nParticles; ++iPart) {
+    const xAOD::TruthParticle* part = (*xTruthParticleContainer)[iPart];
+
+    if (part->status()==1 && part->absPdgId()==13) //muon
+      if(  part->pt()>= m_Ptmin && part->abseta() <= m_EtaRange )
+      {
+        numMuons++;
+        if (numMuons >= m_NMuons)
+        {
+          setFilterPassed(true);
+          return StatusCode::SUCCESS;
+        }
+      }
+  }
+
+  setFilterPassed(false);
+  return StatusCode::SUCCESS;
+
+}
diff --git a/Generators/GeneratorFilters/src/xAODMuonFilter.cxx b/Generators/GeneratorFilters/src/xAODMuonFilter.cxx
new file mode 100644
index 000000000000..f63b96f6984f
--- /dev/null
+++ b/Generators/GeneratorFilters/src/xAODMuonFilter.cxx
@@ -0,0 +1,37 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "GeneratorFilters/xAODMuonFilter.h"
+#include "EventInfo/EventStreamInfo.h"
+#include "xAODTruth/TruthParticle.h"
+#include "xAODTruth/TruthParticleContainer.h"
+#include "xAODTruth/TruthParticleAuxContainer.h"
+
+xAODMuonFilter::xAODMuonFilter(const std::string& name, ISvcLocator* pSvcLocator)
+  : GenFilter(name,pSvcLocator)
+{
+  declareProperty("Ptcut",m_Ptmin = 10000.);
+  declareProperty("Etacut",m_EtaRange = 10.0);
+}
+
+
+StatusCode xAODMuonFilter::filterEvent() {
+  // Retrieve TruthMuons container
+  const xAOD::TruthParticleContainer* xTruthParticleContainer;
+  if (evtStore()->retrieve(xTruthParticleContainer, "TruthMuons").isFailure()) {
+      ATH_MSG_ERROR("No TruthParticle collection with name " << "TruthMuons" << " found in StoreGate!");
+      return StatusCode::FAILURE;
+  }
+
+  unsigned int nParticles = xTruthParticleContainer->size();
+  for (unsigned int iPart=0; iPart<nParticles; ++iPart) {
+    const xAOD::TruthParticle* part = (*xTruthParticleContainer)[iPart];
+
+    if (part->status()==1 && part->absPdgId()==13) //muon
+        if(  part->pt()>= m_Ptmin && part->abseta() <= m_EtaRange )
+            return StatusCode::SUCCESS;
+  }
+  setFilterPassed(false);
+  return StatusCode::SUCCESS;
+}
diff --git a/Generators/GeneratorFilters/src/xAODPhotonFilter.cxx b/Generators/GeneratorFilters/src/xAODPhotonFilter.cxx
new file mode 100644
index 000000000000..5fb0513e1d87
--- /dev/null
+++ b/Generators/GeneratorFilters/src/xAODPhotonFilter.cxx
@@ -0,0 +1,54 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+// Will pass if there are the specified number of photons with pT and eta in the specified range
+#include "GeneratorFilters/xAODPhotonFilter.h"
+#include "EventInfo/EventStreamInfo.h"
+#include "xAODTruth/TruthParticle.h"
+#include "xAODTruth/TruthParticleContainer.h"
+#include "xAODTruth/TruthParticleAuxContainer.h"
+
+xAODPhotonFilter::xAODPhotonFilter(const std::string& name, ISvcLocator* pSvcLocator)
+  : GenFilter(name, pSvcLocator)
+{
+  declareProperty("PtMin", m_Ptmin = 10000.);
+  declareProperty("PtMax", m_Ptmax = 100000000.);
+  declareProperty("EtaCut", m_EtaRange = 2.50);
+  declareProperty("NPhotons", m_NPhotons = 2);
+
+  // Backward compatibility aliases
+  declareProperty("Ptcut", m_Ptmin = 10000.);
+}
+
+
+StatusCode xAODPhotonFilter::filterEvent() {
+  
+  // Retrieve Photon container
+  const xAOD::TruthParticleContainer* xTruthParticleContainer;
+  if (evtStore()->retrieve(xTruthParticleContainer, "TruthPhotons").isFailure()) {
+      ATH_MSG_ERROR("No TruthParticle collection with name " << "TruthPhotons" << " found in StoreGate!");
+      return StatusCode::FAILURE;
+  }
+
+  int NPhotons = 0;
+  unsigned int nParticles = xTruthParticleContainer->size();
+  for (unsigned int iPart=0; iPart<nParticles; ++iPart) {
+    const xAOD::TruthParticle* part = (*xTruthParticleContainer)[iPart];
+
+    if (part->status()==1 && part->absPdgId()==22) //photon
+        if(  part->pt()>= m_Ptmin && part->pt()< m_Ptmax && part->abseta() <= m_EtaRange )
+        {
+          NPhotons++;
+          if (NPhotons >= m_NPhotons)
+          {
+            setFilterPassed(true);
+            return StatusCode::SUCCESS;
+          }
+        }
+            
+  }
+  setFilterPassed(false);
+  return StatusCode::SUCCESS;
+
+}
diff --git a/Generators/GeneratorFilters/src/xAODTruthParticleSlimmerElectron.cxx b/Generators/GeneratorFilters/src/xAODTruthParticleSlimmerElectron.cxx
new file mode 100644
index 000000000000..a6a965850685
--- /dev/null
+++ b/Generators/GeneratorFilters/src/xAODTruthParticleSlimmerElectron.cxx
@@ -0,0 +1,96 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "AthenaKernel/errorcheck.h"
+#include "AthLinks/ElementLink.h"
+
+#include "GeneratorObjects/xAODTruthParticleLink.h"
+
+#include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/DataSvc.h"
+#include "GaudiKernel/PhysicalConstants.h"
+
+#include "EventInfo/EventStreamInfo.h"
+
+#include "xAODTruth/TruthParticle.h"
+#include "xAODTruth/TruthParticleContainer.h"
+#include "xAODTruth/TruthParticleAuxContainer.h"
+
+#include "GeneratorFilters/xAODTruthParticleSlimmerElectron.h"
+
+xAODTruthParticleSlimmerElectron::xAODTruthParticleSlimmerElectron(const std::string &name, ISvcLocator *svcLoc)
+    : AthAlgorithm(name, svcLoc)
+{
+    declareProperty("xAODTruthParticleContainerName", m_xaodTruthParticleContainerName = "TruthParticles");
+    declareProperty("xAODTruthParticleContainerNameElectron", m_xaodTruthParticleContainerNameElectron = "TruthElectrons");
+    declareProperty("el_pt_selection", m_el_pt_selection = 1. * Gaudi::Units::GeV); //User provides units in MeV!
+    declareProperty("abseta_selection", m_abseta_selection = 5.);
+}
+
+StatusCode xAODTruthParticleSlimmerElectron::initialize()
+{
+    ATH_MSG_INFO("xAOD input TruthParticleContainer name = " << m_xaodTruthParticleContainerName);
+    ATH_MSG_INFO("xAOD output TruthParticleContainerElectron name = " << m_xaodTruthParticleContainerNameElectron);
+    return StatusCode::SUCCESS;
+}
+
+StatusCode xAODTruthParticleSlimmerElectron::execute()
+{
+    // If the containers already exists then assume that nothing needs to be done
+    if (evtStore()->contains<xAOD::TruthParticleContainer>(m_xaodTruthParticleContainerNameElectron))
+    {
+        ATH_MSG_WARNING("xAOD Electron Truth Particles are already available in the event");
+        return StatusCode::SUCCESS;
+    }
+
+    // Create new output container
+    xAOD::TruthParticleContainer *xTruthParticleContainerElectron = new xAOD::TruthParticleContainer();
+    CHECK(evtStore()->record(xTruthParticleContainerElectron, m_xaodTruthParticleContainerNameElectron));
+    xAOD::TruthParticleAuxContainer *xTruthParticleAuxContainerElectron = new xAOD::TruthParticleAuxContainer();
+    CHECK(evtStore()->record(xTruthParticleAuxContainerElectron, m_xaodTruthParticleContainerNameElectron + "Aux."));
+    xTruthParticleContainerElectron->setStore(xTruthParticleAuxContainerElectron);
+    ATH_MSG_INFO("Recorded TruthParticleContainerElectron with key: " << m_xaodTruthParticleContainerNameElectron);
+
+    // Retrieve full TruthParticle container
+    const xAOD::TruthParticleContainer *xTruthParticleContainer;
+    if (evtStore()->retrieve(xTruthParticleContainer, m_xaodTruthParticleContainerName).isFailure())
+    {
+        ATH_MSG_ERROR("No TruthParticle collection with name " << m_xaodTruthParticleContainerName << " found in StoreGate!");
+        return StatusCode::FAILURE;
+    }
+
+    // Set up decorators if needed
+
+    // Loop over full TruthParticle container
+    unsigned int nParticles = xTruthParticleContainer->size();
+    for (unsigned int iPart = 0; iPart < nParticles; ++iPart)
+    {
+        const xAOD::TruthParticle *theParticle = (*xTruthParticleContainer)[iPart];
+
+        int this_absPdgID = theParticle->absPdgId();
+        float this_abseta = theParticle->abseta();
+        float this_pt = theParticle->pt();
+        int this_status = theParticle->status();
+
+        //Save Electrons above 1 GeV, & within detector acceptance (4.5)
+        if (this_status == 1 && this_absPdgID == 11 && this_pt >= m_el_pt_selection && this_abseta < m_abseta_selection)
+        {
+            xAOD::TruthParticle *xTruthParticle = new xAOD::TruthParticle();
+            xTruthParticleContainerElectron->push_back( xTruthParticle );
+
+            // Fill with numerical content
+            xTruthParticle->setPdgId(theParticle->pdgId());
+            xTruthParticle->setBarcode(theParticle->barcode());
+            xTruthParticle->setStatus(theParticle->status());
+            xTruthParticle->setM(theParticle->m());
+            xTruthParticle->setPx(theParticle->px());
+            xTruthParticle->setPy(theParticle->py());
+            xTruthParticle->setPz(theParticle->pz());
+            xTruthParticle->setE(theParticle->e());
+        }
+        
+    }
+
+    return StatusCode::SUCCESS;
+}
diff --git a/Generators/GeneratorFilters/src/xAODTruthParticleSlimmerMET.cxx b/Generators/GeneratorFilters/src/xAODTruthParticleSlimmerMET.cxx
new file mode 100644
index 000000000000..0d7e390552aa
--- /dev/null
+++ b/Generators/GeneratorFilters/src/xAODTruthParticleSlimmerMET.cxx
@@ -0,0 +1,156 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "AthenaKernel/errorcheck.h"
+#include "AthLinks/ElementLink.h"
+
+#include "GeneratorObjects/xAODTruthParticleLink.h"
+
+#include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/DataSvc.h"
+#include "GaudiKernel/PhysicalConstants.h"
+
+#include "EventInfo/EventStreamInfo.h"
+
+#include "xAODTruth/TruthParticle.h"
+#include "xAODTruth/TruthParticleContainer.h"
+#include "xAODTruth/TruthParticleAuxContainer.h"
+
+#include "TruthUtils/HepMCHelpers.h"
+#include "TruthUtils/PIDHelpers.h"
+
+#include "GeneratorFilters/xAODTruthParticleSlimmerMET.h"
+
+
+xAODTruthParticleSlimmerMET::xAODTruthParticleSlimmerMET(const std::string &name, ISvcLocator *svcLoc)
+    : AthAlgorithm(name, svcLoc)
+{
+    declareProperty("xAODTruthParticleContainerName", m_xaodTruthParticleContainerName = "TruthParticles");
+    declareProperty("xAODTruthParticleContainerNameMET", m_xaodTruthParticleContainerNameMET = "TruthMET");
+}
+
+StatusCode xAODTruthParticleSlimmerMET::initialize()
+{
+    ATH_MSG_INFO("xAOD input TruthParticleContainer name = " << m_xaodTruthParticleContainerName);
+    ATH_MSG_INFO("xAOD output TruthParticleContainerMET name = " << m_xaodTruthParticleContainerNameMET);
+    return StatusCode::SUCCESS;
+}
+
+StatusCode xAODTruthParticleSlimmerMET::execute()
+{
+    // If the containers already exists then assume that nothing needs to be done
+    if (evtStore()->contains<xAOD::TruthParticleContainer>(m_xaodTruthParticleContainerNameMET))
+    {
+        ATH_MSG_WARNING("xAOD MET Truth Particles are already available in the event");
+        return StatusCode::SUCCESS;
+    }
+
+    // Create new output container
+    xAOD::TruthParticleContainer *xTruthParticleContainerMET = new xAOD::TruthParticleContainer();
+    CHECK(evtStore()->record(xTruthParticleContainerMET, m_xaodTruthParticleContainerNameMET));
+    xAOD::TruthParticleAuxContainer *xTruthParticleAuxContainerMET = new xAOD::TruthParticleAuxContainer();
+    CHECK(evtStore()->record(xTruthParticleAuxContainerMET, m_xaodTruthParticleContainerNameMET + "Aux."));
+    xTruthParticleContainerMET->setStore(xTruthParticleAuxContainerMET);
+    ATH_MSG_INFO("Recorded TruthParticleContainerMET with key: " << m_xaodTruthParticleContainerNameMET);
+
+    // Retrieve full TruthParticle container
+    const xAOD::TruthParticleContainer *xTruthParticleContainer;
+    if (evtStore()->retrieve(xTruthParticleContainer, m_xaodTruthParticleContainerName).isFailure())
+    {
+        ATH_MSG_ERROR("No TruthParticle collection with name " << m_xaodTruthParticleContainerName << " found in StoreGate!");
+        return StatusCode::FAILURE;
+    }
+
+    // Set up decorators if needed
+    const static SG::AuxElement::Decorator<bool> isFromWZDecorator("isFromWZ");
+    const static SG::AuxElement::Decorator<bool> isFromTauDecorator("isFromTau");
+
+    // Loop over full TruthParticle container
+    unsigned int nParticles = xTruthParticleContainer->size();
+    for (unsigned int iPart = 0; iPart < nParticles; ++iPart)
+    {
+        const xAOD::TruthParticle *theParticle = (*xTruthParticleContainer)[iPart];
+
+        // stable and non-interacting, implemented from DerivationFramework 
+        //https://gitlab.cern.ch/atlas/athena/-/blob/master/PhysicsAnalysis/DerivationFramework/DerivationFrameworkMCTruth/python/MCTruthCommon.py#L183
+        // which in turn use the implementation from Reconstruction
+        //https://gitlab.cern.ch/atlas/athena/blob/21.0/Reconstruction/MET/METReconstruction/Root/METTruthTool.cxx#L143
+        if (!MC::isGenStable(theParticle->status(),theParticle->barcode())) continue;
+        if (!MC::isNonInteracting(theParticle->pdgId())) continue;
+
+
+        xAOD::TruthParticle *xTruthParticle = new xAOD::TruthParticle();
+        xTruthParticleContainerMET->push_back( xTruthParticle );
+
+        // Fill with numerical content
+        xTruthParticle->setPdgId(theParticle->pdgId());
+        xTruthParticle->setBarcode(theParticle->barcode());
+        xTruthParticle->setStatus(theParticle->status());
+        xTruthParticle->setM(theParticle->m());
+        xTruthParticle->setPx(theParticle->px());
+        xTruthParticle->setPy(theParticle->py());
+        xTruthParticle->setPz(theParticle->pz());
+        xTruthParticle->setE(theParticle->e());
+
+        //Decorate
+        isFromWZDecorator(*xTruthParticle) = fromWZ(theParticle);
+        isFromTauDecorator(*xTruthParticle) = fromTau(theParticle);
+        
+    }
+
+    return StatusCode::SUCCESS;
+}
+
+bool xAODTruthParticleSlimmerMET::fromWZ( const xAOD::TruthParticle* part ) const
+{
+  // !!! IMPORTANT !!! This is a TEMPORARY function
+  //  it's used in place of code in MCTruthClassifier as long as this package is not dual-use
+  //  when MCTruthClassifier is made dual-use, this function should be discarded.
+  // see ATLJETMET-26
+  //
+  // Loop through parents
+  // Hit a hadron -> return false
+  // Hit a parton -> return true
+  //   This catch is important - we *cannot* look explicitly for the W or Z, because some
+  //    generators do not include the W or Z in the truth record (like Sherpa)
+  //   This code, like the code before it, really assumes one incoming particle per vertex...
+  if (!part->hasProdVtx()) return false;
+
+  unsigned int nIncomingParticles = part->prodVtx()->nIncomingParticles();
+  for (unsigned int iPart = 0; iPart<nIncomingParticles; iPart++)
+  {
+    const xAOD::TruthParticle* incoming_particle = part->prodVtx()->incomingParticle(iPart); 
+    int parent_pdgid = incoming_particle->pdgId();
+    if (MC::PID::isW(parent_pdgid) || MC::PID::isZ(parent_pdgid)) return true;
+    if (MC::PID::isHadron( parent_pdgid ) ) return false;
+    if ( std::abs( parent_pdgid ) < 9 ) return true;
+    if ( parent_pdgid == part->pdgId() ) return fromWZ( incoming_particle );
+  }
+  return false;
+}
+
+bool xAODTruthParticleSlimmerMET::fromTau( const xAOD::TruthParticle* part ) const
+{
+  // !!! IMPORTANT !!! This is a TEMPORARY function
+  //  it's used in place of code in MCTruthClassifier as long as this package is not dual-use
+  //  when MCTruthClassifier is made dual-use, this function should be discarded.
+  // see ATLJETMET-26
+  //
+  // Loop through parents
+  // Find a tau -> return true
+  // Find a hadron or parton -> return false
+  //   This code, like the code before it, really assumes one incoming particle per vertex...
+  if (!part->hasProdVtx()) return false;
+
+  unsigned int nIncomingParticles = part->prodVtx()->nIncomingParticles();
+  for (unsigned int iPart = 0; iPart<nIncomingParticles; iPart++)
+  {
+    const xAOD::TruthParticle* incoming_particle = part->prodVtx()->incomingParticle(iPart); 
+    int parent_pdgid = incoming_particle->pdgId();
+    if ( std::abs( parent_pdgid ) == 15  && fromWZ(incoming_particle)) return true;
+    if (MC::PID::isHadron( parent_pdgid ) || std::abs( parent_pdgid ) < 9 ) return false;
+    if ( parent_pdgid == incoming_particle->pdgId() ) return fromTau( incoming_particle );
+  }
+  return false;
+}
diff --git a/Generators/GeneratorFilters/src/xAODTruthParticleSlimmerMuon.cxx b/Generators/GeneratorFilters/src/xAODTruthParticleSlimmerMuon.cxx
new file mode 100644
index 000000000000..e0368f5735b9
--- /dev/null
+++ b/Generators/GeneratorFilters/src/xAODTruthParticleSlimmerMuon.cxx
@@ -0,0 +1,93 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "AthenaKernel/errorcheck.h"
+#include "AthLinks/ElementLink.h"
+
+#include "GeneratorObjects/xAODTruthParticleLink.h"
+
+#include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/DataSvc.h"
+#include "GaudiKernel/PhysicalConstants.h"
+
+#include "EventInfo/EventStreamInfo.h"
+
+#include "xAODTruth/TruthParticle.h"
+#include "xAODTruth/TruthParticleContainer.h"
+#include "xAODTruth/TruthParticleAuxContainer.h"
+
+#include "GeneratorFilters/xAODTruthParticleSlimmerMuon.h"
+
+xAODTruthParticleSlimmerMuon::xAODTruthParticleSlimmerMuon(const std::string &name, ISvcLocator *svcLoc)
+    : AthAlgorithm(name, svcLoc)
+{
+    declareProperty("xAODTruthParticleContainerName", m_xaodTruthParticleContainerName = "TruthParticles");
+    declareProperty("xAODTruthParticleContainerNameMuon", m_xaodTruthParticleContainerNameMuon = "TruthMuons");
+}
+
+StatusCode xAODTruthParticleSlimmerMuon::initialize()
+{
+    ATH_MSG_INFO("xAOD input TruthParticleContainer name = " << m_xaodTruthParticleContainerName);
+    ATH_MSG_INFO("xAOD output TruthParticleContainerMuon name = " << m_xaodTruthParticleContainerNameMuon);
+    return StatusCode::SUCCESS;
+}
+
+StatusCode xAODTruthParticleSlimmerMuon::execute()
+{
+    // If the containers already exists then assume that nothing needs to be done
+    if (evtStore()->contains<xAOD::TruthParticleContainer>(m_xaodTruthParticleContainerNameMuon))
+    {
+        ATH_MSG_WARNING("xAOD Muon Truth Particles are already available in the event");
+        return StatusCode::SUCCESS;
+    }
+
+    // Create new output container
+    xAOD::TruthParticleContainer *xTruthParticleContainerMuon = new xAOD::TruthParticleContainer();
+    CHECK(evtStore()->record(xTruthParticleContainerMuon, m_xaodTruthParticleContainerNameMuon));
+    xAOD::TruthParticleAuxContainer *xTruthParticleAuxContainerMuon = new xAOD::TruthParticleAuxContainer();
+    CHECK(evtStore()->record(xTruthParticleAuxContainerMuon, m_xaodTruthParticleContainerNameMuon + "Aux."));
+    xTruthParticleContainerMuon->setStore(xTruthParticleAuxContainerMuon);
+    ATH_MSG_INFO("Recorded TruthParticleContainerMuon with key: " << m_xaodTruthParticleContainerNameMuon);
+
+    // Retrieve full TruthParticle container
+    const xAOD::TruthParticleContainer *xTruthParticleContainer;
+    if (evtStore()->retrieve(xTruthParticleContainer, m_xaodTruthParticleContainerName).isFailure())
+    {
+        ATH_MSG_ERROR("No TruthParticle collection with name " << m_xaodTruthParticleContainerName << " found in StoreGate!");
+        return StatusCode::FAILURE;
+    }
+
+    // Set up decorators if needed
+
+    // Loop over full TruthParticle container
+    unsigned int nParticles = xTruthParticleContainer->size();
+    for (unsigned int iPart = 0; iPart < nParticles; ++iPart)
+    {
+        const xAOD::TruthParticle *theParticle = (*xTruthParticleContainer)[iPart];
+
+        int this_absPdgID = theParticle->absPdgId();
+
+        int this_status = theParticle->status();
+
+        //Save Muons 
+        if (this_status == 1 && this_absPdgID == 13 )
+        {
+            xAOD::TruthParticle *xTruthParticle = new xAOD::TruthParticle();
+            xTruthParticleContainerMuon->push_back( xTruthParticle );
+
+            // Fill with numerical content
+            xTruthParticle->setPdgId(theParticle->pdgId());
+            xTruthParticle->setBarcode(theParticle->barcode());
+            xTruthParticle->setStatus(theParticle->status());
+            xTruthParticle->setM(theParticle->m());
+            xTruthParticle->setPx(theParticle->px());
+            xTruthParticle->setPy(theParticle->py());
+            xTruthParticle->setPz(theParticle->pz());
+            xTruthParticle->setE(theParticle->e());
+        }
+        
+    }
+
+    return StatusCode::SUCCESS;
+}
diff --git a/Generators/GeneratorFilters/src/xAODTruthParticleSlimmerPhoton.cxx b/Generators/GeneratorFilters/src/xAODTruthParticleSlimmerPhoton.cxx
new file mode 100644
index 000000000000..aa317e5902cd
--- /dev/null
+++ b/Generators/GeneratorFilters/src/xAODTruthParticleSlimmerPhoton.cxx
@@ -0,0 +1,96 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "AthenaKernel/errorcheck.h"
+#include "AthLinks/ElementLink.h"
+
+#include "GeneratorObjects/xAODTruthParticleLink.h"
+
+#include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/DataSvc.h"
+#include "GaudiKernel/PhysicalConstants.h"
+
+#include "EventInfo/EventStreamInfo.h"
+
+#include "xAODTruth/TruthParticle.h"
+#include "xAODTruth/TruthParticleContainer.h"
+#include "xAODTruth/TruthParticleAuxContainer.h"
+
+#include "GeneratorFilters/xAODTruthParticleSlimmerPhoton.h"
+
+xAODTruthParticleSlimmerPhoton::xAODTruthParticleSlimmerPhoton(const std::string &name, ISvcLocator *svcLoc)
+    : AthAlgorithm(name, svcLoc)
+{
+    declareProperty("xAODTruthParticleContainerName", m_xaodTruthParticleContainerName = "TruthParticles");
+    declareProperty("xAODTruthParticleContainerNamePhoton", m_xaodTruthParticleContainerNamePhoton = "TruthPhotons");
+    declareProperty("photon_pt_selection", m_photon_pt_selection = 1. * Gaudi::Units::GeV); //User provides units in MeV!
+    declareProperty("abseta_selection", m_abseta_selection = 5.);
+}
+
+StatusCode xAODTruthParticleSlimmerPhoton::initialize()
+{
+    ATH_MSG_INFO("xAOD input TruthParticleContainer name = " << m_xaodTruthParticleContainerName);
+    ATH_MSG_INFO("xAOD output TruthParticleContainerPhoton name = " << m_xaodTruthParticleContainerNamePhoton);
+    return StatusCode::SUCCESS;
+}
+
+StatusCode xAODTruthParticleSlimmerPhoton::execute()
+{
+    // If the containers already exists then assume that nothing needs to be done
+    if (evtStore()->contains<xAOD::TruthParticleContainer>(m_xaodTruthParticleContainerNamePhoton))
+    {
+        ATH_MSG_WARNING("xAOD Photon Truth Particles are already available in the event");
+        return StatusCode::SUCCESS;
+    }
+
+    // Create new output container
+    xAOD::TruthParticleContainer *xTruthParticleContainerPhoton = new xAOD::TruthParticleContainer();
+    CHECK(evtStore()->record(xTruthParticleContainerPhoton, m_xaodTruthParticleContainerNamePhoton));
+    xAOD::TruthParticleAuxContainer *xTruthParticleAuxContainerPhoton = new xAOD::TruthParticleAuxContainer();
+    CHECK(evtStore()->record(xTruthParticleAuxContainerPhoton, m_xaodTruthParticleContainerNamePhoton + "Aux."));
+    xTruthParticleContainerPhoton->setStore(xTruthParticleAuxContainerPhoton);
+    ATH_MSG_INFO("Recorded TruthParticleContainerPhoton with key: " << m_xaodTruthParticleContainerNamePhoton);
+
+    // Retrieve full TruthParticle container
+    const xAOD::TruthParticleContainer *xTruthParticleContainer;
+    if (evtStore()->retrieve(xTruthParticleContainer, m_xaodTruthParticleContainerName).isFailure())
+    {
+        ATH_MSG_ERROR("No TruthParticle collection with name " << m_xaodTruthParticleContainerName << " found in StoreGate!");
+        return StatusCode::FAILURE;
+    }
+
+    // Set up decorators if needed
+
+    // Loop over full TruthParticle container
+    unsigned int nParticles = xTruthParticleContainer->size();
+    for (unsigned int iPart = 0; iPart < nParticles; ++iPart)
+    {
+        const xAOD::TruthParticle *theParticle = (*xTruthParticleContainer)[iPart];
+
+        int this_absPdgID = theParticle->absPdgId();
+        float this_abseta = theParticle->abseta();
+        float this_pt = theParticle->pt();
+        int this_status = theParticle->status();
+
+        //Save photons above 1 GeV, & within detector acceptance (5)
+        if (this_status == 1 && this_absPdgID == 22 && this_pt >= m_photon_pt_selection && this_abseta < m_abseta_selection)
+        {
+            xAOD::TruthParticle *xTruthParticle = new xAOD::TruthParticle();
+            xTruthParticleContainerPhoton->push_back( xTruthParticle );
+
+            // Fill with numerical content
+            xTruthParticle->setPdgId(theParticle->pdgId());
+            xTruthParticle->setBarcode(theParticle->barcode());
+            xTruthParticle->setStatus(theParticle->status());
+            xTruthParticle->setM(theParticle->m());
+            xTruthParticle->setPx(theParticle->px());
+            xTruthParticle->setPy(theParticle->py());
+            xTruthParticle->setPz(theParticle->pz());
+            xTruthParticle->setE(theParticle->e());
+        }
+        
+    }
+
+    return StatusCode::SUCCESS;
+}
-- 
GitLab