From edd2e397456f808cfaff3198996bade31fe4e924 Mon Sep 17 00:00:00 2001
From: Scott Snyder <scott.snyder@cern.ch>
Date: Mon, 29 Aug 2016 03:41:24 +0200
Subject: [PATCH] clang warnings: missing override keywords.
 (EventUtils-00-00-32)

	* Tagging EventUtils-00-00-32.
	* clang warnings: missing override keywords.

2016-08-29  scott snyder  <snyder@bnl.gov>

	* Tagging EventUtils-00-00-31.
	* endreq -> endmsg.
	* Tagging EventUtils-00-00-30.
	* Coverity 109084.

2016-08-01 Will Buttinger <will@cern.ch>
	* Fix cmake compilation
	* tag EventUtils-00-00-29

2016-06-20  Karsten Koeneke  <karsten.koeneke@cern.ch>

  * Make the selection tools in ParticleSelectionAlg public
  * tag EventUtils-00-00-27

...
(Long ChangeLog diff - truncated)
---
 .../AnalysisCommon/EventUtils/CMakeLists.txt  |   9 +-
 .../EventUtils/cmt/requirements               |  10 +-
 .../EventUtils/src/AddVarAlg.cxx              |   2 +-
 .../AnalysisCommon/EventUtils/src/AddVarAlg.h |   2 +-
 .../EventUtils/src/AddVarTool.h               |   4 +-
 .../AnalysisCommon/EventUtils/src/CutAlg.cxx  |  72 ++-
 .../AnalysisCommon/EventUtils/src/CutAlg.h    |  46 +-
 .../AnalysisCommon/EventUtils/src/CutTool.cxx |  11 +-
 .../AnalysisCommon/EventUtils/src/CutTool.h   |   4 +-
 .../EventUtils/src/EventDecisionAlg.cxx       |  95 ++++
 .../EventUtils/src/EventDecisionAlg.h         |  66 +++
 .../EventUtils/src/EventQualityFilterAlg.cxx  |  52 ++-
 .../EventUtils/src/EventQualityFilterAlg.h    |  65 +--
 .../EventUtils/src/ParticleCombinerTool.cxx   |  73 +--
 .../EventUtils/src/ParticleCombinerTool.h     |   4 +-
 .../EventUtils/src/ParticleRemoverAlg.cxx     | 315 +++++++++++++
 .../EventUtils/src/ParticleRemoverAlg.h       | 114 +++++
 .../EventUtils/src/ParticleRemoverAlg.icc     | 242 ++++++++++
 .../EventUtils/src/ParticleSelectionAlg.cxx   | 419 +++++++++++++-----
 .../EventUtils/src/ParticleSelectionAlg.h     | 215 ++++-----
 .../EventUtils/src/ParticleSelectionAlg.icc   | 188 ++++++++
 .../EventUtils/src/ParticleSelectionTool.cxx  |   1 +
 .../EventUtils/src/ParticleSelectionTool.h    |   4 +-
 .../EventUtils/src/ParticleSortingTool.cxx    |  43 +-
 .../EventUtils/src/ParticleSortingTool.h      |  60 ++-
 .../EventUtils/src/TriggerSelectionAlg.cxx    | 130 ++++++
 .../EventUtils/src/TriggerSelectionAlg.h      |  85 ++++
 .../src/components/EventUtils_entries.cxx     |  24 +-
 28 files changed, 1936 insertions(+), 419 deletions(-)
 create mode 100644 PhysicsAnalysis/AnalysisCommon/EventUtils/src/EventDecisionAlg.cxx
 create mode 100644 PhysicsAnalysis/AnalysisCommon/EventUtils/src/EventDecisionAlg.h
 create mode 100644 PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleRemoverAlg.cxx
 create mode 100644 PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleRemoverAlg.h
 create mode 100644 PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleRemoverAlg.icc
 create mode 100644 PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSelectionAlg.icc
 create mode 100644 PhysicsAnalysis/AnalysisCommon/EventUtils/src/TriggerSelectionAlg.cxx
 create mode 100644 PhysicsAnalysis/AnalysisCommon/EventUtils/src/TriggerSelectionAlg.h

diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/CMakeLists.txt b/PhysicsAnalysis/AnalysisCommon/EventUtils/CMakeLists.txt
index de8fc1a7f68..9e38cea5081 100644
--- a/PhysicsAnalysis/AnalysisCommon/EventUtils/CMakeLists.txt
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/CMakeLists.txt
@@ -7,15 +7,19 @@ atlas_subdir( EventUtils )
 
 # Declare the package's dependencies:
 atlas_depends_on_subdirs( PRIVATE
+                          Control/AthAnalysisBaseComps
                           Control/AthContainers
+                          Control/AthContainersInterfaces
                           Control/AthLinks
                           Control/AthenaBaseComps
+                          Control/AthenaKernel
                           Control/CxxUtils
                           Event/EventInfo
                           Event/xAOD/xAODBTagging
                           Event/xAOD/xAODBase
                           Event/xAOD/xAODCaloEvent
                           Event/xAOD/xAODCore
+                          Event/xAOD/xAODCutFlow
                           Event/xAOD/xAODEgamma
                           Event/xAOD/xAODEventInfo
                           Event/xAOD/xAODJet
@@ -33,14 +37,15 @@ atlas_depends_on_subdirs( PRIVATE
                           Trigger/TrigAnalysis/TrigDecisionTool )
 
 # External dependencies:
+find_package( Boost COMPONENTS filesystem thread system )
 find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread )
 
 # Component(s) in the package:
 atlas_add_component( EventUtils
                      src/*.cxx
                      src/components/*.cxx
-                     INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
-                     LINK_LIBRARIES ${ROOT_LIBRARIES} AthContainers AthLinks AthenaBaseComps CxxUtils EventInfo xAODBTagging xAODBase xAODCaloEvent xAODCore xAODEgamma xAODEventInfo xAODJet xAODMissingET xAODMuon xAODPFlow xAODParticleEvent xAODTau xAODTracking xAODTruth GaudiKernel PATCoreLib ExpressionEvaluationLib TrigDecisionToolLib )
+                     INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}
+                     LINK_LIBRARIES ${ROOT_LIBRARIES} ${Boost_LIBRARIES} AthAnalysisBaseCompsLib AthContainers AthLinks AthenaBaseComps AthenaKernel CxxUtils EventInfo xAODBTagging xAODBase xAODCaloEvent xAODCore xAODCutFlow xAODEgamma xAODEventInfo xAODJet xAODMissingET xAODMuon xAODPFlow xAODParticleEvent xAODTau xAODTracking xAODTruth GaudiKernel PATCoreLib ExpressionEvaluationLib TrigDecisionToolLib )
 
 # Install files from the package:
 atlas_install_python_modules( python/*.py )
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/cmt/requirements b/PhysicsAnalysis/AnalysisCommon/EventUtils/cmt/requirements
index 121353452fd..5cac883e799 100644
--- a/PhysicsAnalysis/AnalysisCommon/EventUtils/cmt/requirements
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/cmt/requirements
@@ -7,21 +7,26 @@ public
 use  AtlasPolicy                AtlasPolicy-*
 
 private
+use  AthAnalysisBaseComps       AthAnalysisBaseComps-*          Control
 use  AthContainers              AthContainers-*                 Control
 use  AthLinks                   AthLinks-*                      Control
 use  AthenaBaseComps            AthenaBaseComps-*               Control
-use  AtlasROOT                  AtlasROOT-*                     External
 use  CxxUtils                   CxxUtils-*                      Control
+use  AthContainersInterfaces    AthContainersInterfaces-*       Control
+use  AthenaKernel               AthenaKernel-*                  Control
+use  AtlasROOT                  AtlasROOT-*                     External
+use  AtlasBoost                 AtlasBoost-*                    External
 use  DerivationFrameworkInterfaces                              DerivationFrameworkInterfaces-* PhysicsAnalysis/DerivationFramework
-use  EventInfo                  EventInfo-*                     Event
 use  ExpressionEvaluation       ExpressionEvaluation-*          PhysicsAnalysis/CommonTools
 use  GaudiInterface             GaudiInterface-*                External
 use  PATCore                    PATCore-*                       PhysicsAnalysis/AnalysisCommon
 use  TrigDecisionTool           TrigDecisionTool-*              Trigger/TrigAnalysis
+use  EventInfo                  EventInfo-*                     Event
 use  xAODBTagging               xAODBTagging-*                  Event/xAOD
 use  xAODBase                   xAODBase-*                      Event/xAOD
 use  xAODCaloEvent              xAODCaloEvent-*                 Event/xAOD
 use  xAODCore                   xAODCore-*                      Event/xAOD
+use  xAODCutFlow                xAODCutFlow-*                   Event/xAOD
 use  xAODEgamma                 xAODEgamma-*                    Event/xAOD
 use  xAODEventInfo              xAODEventInfo-*                 Event/xAOD
 use  xAODJet                    xAODJet-*                       Event/xAOD
@@ -32,6 +37,7 @@ use  xAODParticleEvent          xAODParticleEvent-*             Event/xAOD
 use  xAODTau                    xAODTau-*                       Event/xAOD
 use  xAODTracking               xAODTracking-*                  Event/xAOD
 use  xAODTruth                  xAODTruth-*                     Event/xAOD
+use AthenaBaseComps AthenaBaseComps-* Control
 end_private
 
 
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/AddVarAlg.cxx b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/AddVarAlg.cxx
index db27674119d..4a410005e11 100644
--- a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/AddVarAlg.cxx
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/AddVarAlg.cxx
@@ -29,7 +29,7 @@
 ////////////////
 AddVarAlg::AddVarAlg( const std::string& name,
                       ISvcLocator* pSvcLocator ) :
-  ::AthFilterAlgorithm( name, pSvcLocator ),
+  ::AthAlgorithm( name, pSvcLocator ),
   m_jos("JobOptionsSvc", name),
   m_tool("AddVarTool/AddVarTool", this),
   m_setInCollKey(false),
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/AddVarAlg.h b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/AddVarAlg.h
index 1bc1ab742ca..fbbfe12fc87 100644
--- a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/AddVarAlg.h
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/AddVarAlg.h
@@ -29,7 +29,7 @@ namespace DerivationFramework {
 
 
 class AddVarAlg
-  : public ::AthFilterAlgorithm
+  : public ::AthAlgorithm
 {
 
   ///////////////////////////////////////////////////////////////////
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/AddVarTool.h b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/AddVarTool.h
index 70cf3b52627..2cb652d0ae9 100644
--- a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/AddVarTool.h
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/AddVarTool.h
@@ -52,10 +52,10 @@ public:
   virtual ~AddVarTool();
 
   /// Athena algtool's initialize
-  virtual StatusCode  initialize();
+  virtual StatusCode  initialize() override;
 
   /// Athena algtool's finalize
-  virtual StatusCode  finalize();
+  virtual StatusCode  finalize() override;
 
 
   /// Implement the method from the ISkimmingTool interface
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/CutAlg.cxx b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/CutAlg.cxx
index 05fec3da403..1b4211dd5cc 100644
--- a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/CutAlg.cxx
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/CutAlg.cxx
@@ -16,9 +16,13 @@
 
 // FrameWork includes
 #include "GaudiKernel/Property.h"
-#include "GaudiKernel/IJobOptionsSvc.h"
-#include "DerivationFrameworkInterfaces/ISkimmingTool.h"
-
+#include "ExpressionEvaluation/ExpressionParser.h"
+#include "ExpressionEvaluation/SGxAODProxyLoader.h"
+#include "ExpressionEvaluation/SGNTUPProxyLoader.h"
+#include "ExpressionEvaluation/MultipleProxyLoader.h"
+#include "ExpressionEvaluation/StackElement.h"
+#include "TrigDecisionTool/TrigDecisionTool.h"
+#include "ExpressionEvaluation/TriggerDecisionProxyLoader.h"
 
 
 ///////////////////////////////////////////////////////////////////
@@ -30,18 +34,13 @@
 CutAlg::CutAlg( const std::string& name,
                 ISvcLocator* pSvcLocator ) :
   ::AthFilterAlgorithm( name, pSvcLocator ),
-  m_jos("JobOptionsSvc", name),
-  m_skimTool("CutTool/CutTool", this),
+  m_trigDecisionTool("Trig::TrigDecisionTool/TrigDecisionTool"),
+  m_parser(0),
   m_cut(""),
-  m_setCut(false),
   m_nEventsProcessed(0)
 {
-  declareProperty("JobOptionsSvc",       m_jos, "The JobOptionService instance.");
-
-  declareProperty("SkimTool",            m_skimTool, "The private SkimmingTool" );
-
-  declareProperty("Cut",                 m_cut="",   "The name of the output container" );
-  m_cut.declareUpdateHandler( &CutAlg::setupCut, this );
+  declareProperty("Cut",              m_cut="",           "The name of the output container" );
+  declareProperty("TrigDecisionTool", m_trigDecisionTool, "If you do not use trigger decisions and want to ensure the TrigDecisionTool is not loaded, set this to a blank string");
 }
 
 
@@ -60,36 +59,27 @@ StatusCode CutAlg::initialize()
   ATH_MSG_DEBUG ("Initializing " << name() << "...");
 
   // Print out the used configuration
-  ATH_MSG_DEBUG ( " using JobOptionsSvc = " << m_jos );
-  ATH_MSG_DEBUG ( " using SkimTool      = " << m_skimTool );
-  ATH_MSG_DEBUG ( " using Cut           = " << m_cut );
-
+  ATH_MSG_DEBUG ( " using = " << m_trigDecisionTool );
+  ATH_MSG_DEBUG ( " using = " << m_cut );
 
   // Initialize the counters to zero
   m_nEventsProcessed = 0 ;
 
+  // initialize proxy loaders for expression parsing
+  ExpressionParsing::MultipleProxyLoader *proxyLoaders = new ExpressionParsing::MultipleProxyLoader();
 
-  // Get the JobOptionService
-  // We will use this to set the properties of our private skimming tool
-  // from the properties of this algorithm.
-  ATH_MSG_VERBOSE( "Getting the JobOptionService");
-  ATH_CHECK( m_jos.retrieve() );
-
-  // Get the full name of the private skimTool
-  ATH_MSG_VERBOSE( "Getting the full name of the tool");
-  const std::string& fullToolName = this->name() + "." + m_skimTool.name();
-  ATH_MSG_DEBUG( "Got the full name of the tool: " << fullToolName );
-
-  // Now, set all properties of the private skimTool that were acutally configured
-  if (m_setCut) {
-    ATH_MSG_DEBUG( "Setting property" << m_cut
-                   << " of private tool with name: '" << fullToolName << "'" );
-    ATH_CHECK( m_jos->addPropertyToCatalogue (fullToolName,m_cut) );
+  // initialise TDT explicitly, needed for the tool to properly work with trigger decisions in AthAnalysisBase (until fixed)
+  if( !m_trigDecisionTool.empty() ) {
+    ATH_CHECK( m_trigDecisionTool.retrieve() );
+    proxyLoaders->push_back(new ExpressionParsing::TriggerDecisionProxyLoader(m_trigDecisionTool));
   }
-  ATH_MSG_DEBUG( "Done setting properties of the tool");
 
-  // Get the skimming tool
-  ATH_CHECK( m_skimTool.retrieve() );
+  proxyLoaders->push_back(new ExpressionParsing::SGxAODProxyLoader(evtStore()));
+  proxyLoaders->push_back(new ExpressionParsing::SGNTUPProxyLoader(evtStore()));
+
+  // load the expressions
+  m_parser = new ExpressionParsing::ExpressionParser(proxyLoaders);
+  m_parser->loadExpression( m_cut.value() );
 
   ATH_MSG_DEBUG ( "==> done with initialize " << name() << "..." );
 
@@ -103,8 +93,10 @@ StatusCode CutAlg::finalize()
   ATH_MSG_DEBUG ("Finalizing " << name() << "...");
 
   // Release all tools and services
-  ATH_CHECK( m_jos.release() );
-  ATH_CHECK( m_skimTool.release() );
+  if (m_parser) {
+    delete m_parser;
+    m_parser = 0;
+  }
 
   return StatusCode::SUCCESS;
 }
@@ -118,9 +110,11 @@ StatusCode CutAlg::execute()
 
   // Simple status message at the beginning of each event execute,
   ATH_MSG_DEBUG ( "==> execute " << name() << " on " << m_nEventsProcessed << ". event..." );
+  ATH_MSG_VERBOSE ( "Dumping event store: " << evtStore()->dump() );
 
-  // Call the skimming tool and set its result
-  bool eventPasses = m_skimTool->eventPassesFilter();
+  // Make the pass/fail decision
+  bool eventPasses = true;
+  eventPasses = m_parser->evaluateAsBool();
   this->setFilterPassed( eventPasses );
   ATH_MSG_DEBUG("Event passes/fails: " << eventPasses );
 
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/CutAlg.h b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/CutAlg.h
index 0ec6805d8f1..07e6e2d4030 100644
--- a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/CutAlg.h
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/CutAlg.h
@@ -16,18 +16,17 @@
 
 // FrameWork includes
 #include "GaudiKernel/ToolHandle.h"
-#include "GaudiKernel/ServiceHandle.h"
 #include "AthenaBaseComps/AthFilterAlgorithm.h"
+#include "TrigDecisionTool/TrigDecisionTool.h"
 
-
-// forward declarations
-class IJobOptionsSvc;
-namespace DerivationFramework {
-  class ISkimmingTool;
+// Forward declarations
+namespace ExpressionParsing {
+  class ExpressionParser;
 }
 
 
 
+
 class CutAlg
   : public ::AthFilterAlgorithm
 {
@@ -55,53 +54,26 @@ class CutAlg
   virtual StatusCode  finalize();
 
 
-private:
-  // The update handlers
-
-  /// This internal method will realize if a user sets the 'Cut' property
-  void setupCut( Property& /*prop*/ );
-
 
   ///////////////////////////////////////////////////////////////////
   // Private data:
   ///////////////////////////////////////////////////////////////////
  private:
-  /// The job options service (will be used to forward this algs properties to
-  /// the private tool)
-  ServiceHandle<IJobOptionsSvc> m_jos;
+  /// The trigger decision tool
+  ToolHandle<Trig::TrigDecisionTool> m_trigDecisionTool;
 
-  /// The ToolHandle to the SkimmingTool
-  ToolHandle<DerivationFramework::ISkimmingTool> m_skimTool;
+  /// The expression parser
+  ExpressionParsing::ExpressionParser *m_parser;
 
 
   /// The cut string
   StringProperty m_cut;
 
-  /// This boolean is true if the user sets the 'Cut' property
-  bool m_setCut;
-
-
-
   /// Internal event counter
   unsigned long m_nEventsProcessed;
 
 
 };
 
-// I/O operators
-//////////////////////
-
-///////////////////////////////////////////////////////////////////
-// Inline methods:
-///////////////////////////////////////////////////////////////////
-
-/// This internal method will realize if a user sets the 'Cut' property
-inline void CutAlg::setupCut( Property& /*prop*/ ) {
-  m_setCut = true;
-  return;
-}
-
-
-
 
 #endif //> !EVENTUTILS_CUTALG_H
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/CutTool.cxx b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/CutTool.cxx
index 817bef0b155..87354401b7a 100644
--- a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/CutTool.cxx
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/CutTool.cxx
@@ -43,7 +43,8 @@ CutTool::CutTool( const std::string& type,
 {
   declareInterface< DerivationFramework::ISkimmingTool >(this);
 
-  declareProperty("Cut", m_cut="", "The name of the output container" );
+  declareProperty("Cut", m_cut="", "The cut expression" );
+  declareProperty("TrigDecisionTool",m_trigDecisionTool,"If you do not use trigger decisions and want to ensure the TrigDecisionTool is not loaded, set this to a blank string");
 }
 
 // Destructor
@@ -61,7 +62,13 @@ StatusCode CutTool::initialize()
 
   // initialize proxy loaders for expression parsing
   ExpressionParsing::MultipleProxyLoader *proxyLoaders = new ExpressionParsing::MultipleProxyLoader();
-  proxyLoaders->push_back(new ExpressionParsing::TriggerDecisionProxyLoader(m_trigDecisionTool));
+
+  // initialise TDT explicitly, needed for the tool to properly work with trigger decisions in AthAnalysisBase (until fixed)
+  if( !m_trigDecisionTool.empty() ) {
+    ATH_CHECK( m_trigDecisionTool.retrieve() );
+    proxyLoaders->push_back(new ExpressionParsing::TriggerDecisionProxyLoader(m_trigDecisionTool));
+  }
+
   proxyLoaders->push_back(new ExpressionParsing::SGxAODProxyLoader(evtStore()));
   proxyLoaders->push_back(new ExpressionParsing::SGNTUPProxyLoader(evtStore()));
 
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/CutTool.h b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/CutTool.h
index 0314ee70201..71b77e76439 100644
--- a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/CutTool.h
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/CutTool.h
@@ -48,10 +48,10 @@ class CutTool
   virtual ~CutTool();
 
   /// Athena algtool's initialize
-  virtual StatusCode  initialize();
+  virtual StatusCode  initialize() override;
 
   /// Athena algtool's finalize
-  virtual StatusCode  finalize();
+  virtual StatusCode  finalize() override;
 
 
   /// Implement the method from the ISkimmingTool interface
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/EventDecisionAlg.cxx b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/EventDecisionAlg.cxx
new file mode 100644
index 00000000000..de769b8900b
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/EventDecisionAlg.cxx
@@ -0,0 +1,95 @@
+///////////////////////// -*- C++ -*- /////////////////////////////
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// EventDecisionAlg.cxx
+// Implementation file for class EventDecisionAlg
+// Author: Karsten Koeneke <karsten.koeneke@cern.ch>
+///////////////////////////////////////////////////////////////////
+
+// EventUtils includes
+#include "EventDecisionAlg.h"
+
+// STL includes
+
+// FrameWork includes
+#include "GaudiKernel/Property.h"
+#include "AthenaKernel/IDecisionSvc.h"
+
+
+// Constructors
+////////////////
+EventDecisionAlg::EventDecisionAlg( const std::string& name,
+                                    ISvcLocator* pSvcLocator ) :
+  ::AthFilterAlgorithm( name, pSvcLocator ),
+  m_decSvc("DecisionSvc/DecisionSvc", name),
+  m_streamNames()
+{
+  declareProperty("DecisionService",   m_decSvc,      "The handle to the IDecisionSvc" );
+  declareProperty("OutputStreamNames", m_streamNames, "The names of all output streams to check");
+}
+
+
+// Destructor
+///////////////
+EventDecisionAlg::~EventDecisionAlg()
+{}
+
+
+
+// Athena Algorithm's Hooks
+////////////////////////////
+StatusCode EventDecisionAlg::initialize()
+{
+  ATH_MSG_DEBUG ("Initializing " << name() << "...");
+
+  // Print out the used configuration
+  ATH_MSG_DEBUG ( " using = " << m_decSvc );
+  ATH_MSG_DEBUG ( " using = " << m_streamNames );
+
+  // Retrieve the services
+  ATH_CHECK( m_decSvc.retrieve() );
+
+  ATH_MSG_DEBUG ( "==> done with initialize " << name() << "..." );
+  return StatusCode::SUCCESS;
+}
+
+
+
+StatusCode EventDecisionAlg::finalize()
+{
+  ATH_MSG_DEBUG ("Finalizing " << name() << "...");
+
+  // Release all tools and services
+  ATH_CHECK( m_decSvc.release() );
+
+  return StatusCode::SUCCESS;
+}
+
+
+
+StatusCode EventDecisionAlg::execute()
+{
+  // Simple status message at the beginning of each event execute,
+  ATH_MSG_DEBUG ( "==> execute " << name() );
+  ATH_MSG_VERBOSE ( "Dumping event store: " << evtStore()->dump() );
+
+  // Make the pass/fail decision
+  // Ensure that the even passes if no stream name is given
+  bool eventPasses = true;
+  for ( const std::string& streamName : m_streamNames.value() ){
+    // Ensure that the even passes if no stream name is given
+    eventPasses = false;
+    eventPasses = m_decSvc->isEventAccepted(streamName);
+    if (eventPasses){
+      ATH_MSG_DEBUG("Got an event accept from stream name " << streamName);
+      break;
+    }
+  }
+  this->setFilterPassed( eventPasses );
+  ATH_MSG_DEBUG("Event passes/fails: " << eventPasses );
+
+  return StatusCode::SUCCESS;
+}
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/EventDecisionAlg.h b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/EventDecisionAlg.h
new file mode 100644
index 00000000000..401471df97b
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/EventDecisionAlg.h
@@ -0,0 +1,66 @@
+///////////////////////// -*- C++ -*- /////////////////////////////
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// EventDecisionAlg.h
+// Header file for class EventDecisionAlg
+// Author: Karsten Koeneke <karsten.koeneke@cern.ch>
+///////////////////////////////////////////////////////////////////
+#ifndef EVENTUTILS_EVENTDECISIONALG_H
+#define EVENTUTILS_EVENTDECISIONALG_H 1
+
+// STL includes
+#include <string>
+
+// FrameWork includes
+#include "GaudiKernel/ServiceHandle.h"
+#include "AthenaBaseComps/AthFilterAlgorithm.h"
+
+// forward declarations
+class IDecisionSvc;
+
+
+class EventDecisionAlg
+  : public ::AthFilterAlgorithm
+{
+
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+ public:
+
+  // Copy constructor:
+
+  /// Constructor with parameters:
+  EventDecisionAlg( const std::string& name, ISvcLocator* pSvcLocator );
+
+  /// Destructor:
+  virtual ~EventDecisionAlg();
+
+  /// Athena algorithm's initalize hook
+  virtual StatusCode  initialize();
+
+  /// Athena algorithm's execute hook
+  virtual StatusCode  execute();
+
+  /// Athena algorithm's finalize hook
+  virtual StatusCode  finalize();
+
+
+
+  ///////////////////////////////////////////////////////////////////
+  // Private data:
+  ///////////////////////////////////////////////////////////////////
+ private:
+  // The handle to the IDecisionSvc;
+  ServiceHandle<IDecisionSvc> m_decSvc;
+
+  /// The names of all output streams to check
+  StringArrayProperty m_streamNames;
+
+};
+
+
+#endif //> !EVENTUTILS_EVENTDECISIONALG_H
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/EventQualityFilterAlg.cxx b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/EventQualityFilterAlg.cxx
index 77976dd5dc1..86e11806ff2 100644
--- a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/EventQualityFilterAlg.cxx
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/EventQualityFilterAlg.cxx
@@ -13,14 +13,8 @@
 // SelectionUtils includes
 #include "EventQualityFilterAlg.h"
 
-// STL includes
-
-// FrameWork includes
-#include "GaudiKernel/Property.h"
-
 // EDM includes
-#include "EventInfo/EventInfo.h"
-#include "EventInfo/EventType.h"
+#include "xAODEventInfo/EventInfo.h"
 
 
 ///////////////////////////////////////////////////////////////////
@@ -31,15 +25,20 @@
 ////////////////
 EventQualityFilterAlg::EventQualityFilterAlg( const std::string& name,
                                               ISvcLocator* pSvcLocator ) :
-  ::AthFilterAlgorithm( name, pSvcLocator )
+  ::AthFilterAlgorithm( name, pSvcLocator ),
+  m_useLArError(true),
+  m_useTileError(true),
+  m_useSCTError(true),
+  m_useCoreError(true)
 {
   //
   // Property declaration
   //
-  declareProperty( "VetoLArError",  m_useLArError       = false, "Veto events with a LAr error" );
-  declareProperty( "VetoTileError", m_useTileError      = false, "Veto events with a Tile error" );
-  declareProperty( "VetoCoreError", m_useCoreError      = false, "Veto events with a Core error" );
-  declareProperty( "VetoTileTrips", m_useTileTripReader = false, "Veto events with a Tile trip error" );
+  declareProperty( "VetoLArError",  m_useLArError,  "Veto events with a LAr error" );
+  declareProperty( "VetoTileError", m_useTileError, "Veto events with a Tile error" );
+  declareProperty( "VetoSCTError",  m_useSCTError,  "Veto events with an SCT error" );
+  declareProperty( "VetoCoreError", m_useCoreError, "Veto events with a Core error" );
+  //declareProperty( "VetoTileTrips", m_useTileTripReader, "Veto events with a Tile trip error" );
 }
 
 
@@ -58,6 +57,11 @@ EventQualityFilterAlg::~EventQualityFilterAlg()
 StatusCode EventQualityFilterAlg::initialize()
 {
   ATH_MSG_DEBUG ("Initializing " << name() << "...");
+  ATH_MSG_DEBUG( "Using: " << m_useLArError );
+  ATH_MSG_DEBUG( "Using: " << m_useTileError );
+  ATH_MSG_DEBUG( "Using: " << m_useSCTError );
+  ATH_MSG_DEBUG( "Using: " << m_useCoreError );
+  // ATH_MSG_DEBUG( "Using: " << m_useTileTripReader );
   return StatusCode::SUCCESS;
 }
 
@@ -77,28 +81,28 @@ StatusCode EventQualityFilterAlg::execute()
 
 
   // Get the EventInfo object
-  const EventInfo* eventInfo(NULL);
+  const xAOD::EventInfo* eventInfo = nullptr;
   ATH_CHECK( evtStore()->retrieve(eventInfo) );
 
 
   // Only do the event vetoing on data
-  bool isSim = eventInfo->event_type()->test(EventType::IS_SIMULATION);
-  if ( isSim )
-    {
-      ATH_MSG_DEBUG ("It is an MC event... not vetoing...");
-      setFilterPassed(true);
-      return StatusCode::SUCCESS;
-    }
+  const bool isSim = eventInfo->eventType(xAOD::EventInfo::EventType::IS_SIMULATION);
+  if ( isSim ) {
+    ATH_MSG_DEBUG ("It is an MC event... not vetoing...");
+    this->setFilterPassed(true);
+    return StatusCode::SUCCESS;
+  }
 
 
   // Now make the event decision
   bool passEvent(true);
-  // if ( eventInfo->errorState(EventInfo::LAr)  == EventInfo::Error ){ passEvent = false; }
-  // if ( eventInfo->errorState(EventInfo::Tile) == EventInfo::Error ){ passEvent = false; }
-  // if ( eventInfo->eventFlags(EventInfo::Core) & 0x40000 ){ passEvent = false; }
+  if ( m_useLArError.value()  && eventInfo->errorState(xAOD::EventInfo::LAr)  == xAOD::EventInfo::Error ){ passEvent = false; }
+  if ( m_useTileError.value() && eventInfo->errorState(xAOD::EventInfo::Tile) == xAOD::EventInfo::Error ){ passEvent = false; }
+  if ( m_useSCTError.value()  && eventInfo->errorState(xAOD::EventInfo::SCT) == xAOD::EventInfo::Error ){ passEvent = false; }
+  if ( m_useCoreError.value() && eventInfo->isEventFlagBitSet(xAOD::EventInfo::Core, 18)  ){ passEvent = false; }
 
   // Set the final decision
-  setFilterPassed(passEvent);
+  this->setFilterPassed(passEvent);
 
   return StatusCode::SUCCESS;
 }
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/EventQualityFilterAlg.h b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/EventQualityFilterAlg.h
index 4edb4215435..b62e0516700 100644
--- a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/EventQualityFilterAlg.h
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/EventQualityFilterAlg.h
@@ -4,11 +4,11 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-// EventQualityFilterAlg.h 
+// EventQualityFilterAlg.h
 // Header file for class EventQualityFilterAlg
 // Author: Karsten Koeneke <karsten.koeneke@cern.ch>
 // Description: Algorithm to filter out events with a bad Event errors
-/////////////////////////////////////////////////////////////////// 
+///////////////////////////////////////////////////////////////////
 #ifndef EVENTUTILS_EVENTQUALITYFILTERALG_H
 #define EVENTUTILS_EVENTQUALITYFILTERALG_H 1
 
@@ -22,53 +22,62 @@
 
 class EventQualityFilterAlg
   : public ::AthFilterAlgorithm
-{ 
+{
 
-  /////////////////////////////////////////////////////////////////// 
-  // Public methods: 
-  /////////////////////////////////////////////////////////////////// 
- public: 
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+ public:
 
-  // Copy constructor: 
 
-  /// Constructor with parameters: 
+  /// Constructor with parameters:
   EventQualityFilterAlg( const std::string& name, ISvcLocator* pSvcLocator );
 
-  /// Destructor: 
-  virtual ~EventQualityFilterAlg(); 
+  /// Destructor:
+  virtual ~EventQualityFilterAlg();
 
   // Athena algorithm's Hooks
   virtual StatusCode  initialize();
   virtual StatusCode  execute();
   virtual StatusCode  finalize();
 
-  /////////////////////////////////////////////////////////////////// 
-  // Const methods: 
   ///////////////////////////////////////////////////////////////////
+  // Const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  ///////////////////////////////////////////////////////////////////
+  // Non-const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  ///////////////////////////////////////////////////////////////////
+  // Private data:
+  ///////////////////////////////////////////////////////////////////
+ private:
+
+  /// Flag to turn on/off checking of LAr calorimeter error flag
+  BooleanProperty m_useLArError;
+
+  /// Flag to turn on/off checking of tile calorimter error flag
+  BooleanProperty m_useTileError;
 
-  /////////////////////////////////////////////////////////////////// 
-  // Non-const methods: 
-  /////////////////////////////////////////////////////////////////// 
+  /// Flag to turn on/off checking of SCT error flag
+  BooleanProperty m_useSCTError;
 
-  /////////////////////////////////////////////////////////////////// 
-  // Private data: 
-  /////////////////////////////////////////////////////////////////// 
- private: 
+  /// Flag to turn on/off checking of core error flag
+  BooleanProperty m_useCoreError;
 
-  bool m_useLArError;
-  bool m_useTileError;
-  bool m_useCoreError;
-  bool m_useTileTripReader;
+  // /// Flag to turn on/off checking of tile trip information
+  // BooleanProperty m_useTileTripReader;
 
 
-}; 
+};
 
 // I/O operators
 //////////////////////
 
-/////////////////////////////////////////////////////////////////// 
-// Inline methods: 
-/////////////////////////////////////////////////////////////////// 
+///////////////////////////////////////////////////////////////////
+// Inline methods:
+///////////////////////////////////////////////////////////////////
 
 
 #endif //> !EVENTUTILS_EVENTQUALITYFILTERALG_H
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleCombinerTool.cxx b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleCombinerTool.cxx
index 6fd7766ae5b..a231dd86f46 100644
--- a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleCombinerTool.cxx
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleCombinerTool.cxx
@@ -404,7 +404,7 @@ StatusCode ParticleCombinerTool::addBranches() const
         for ( unsigned int ichoice = 0; ichoice < aUniqueChoice.size(); ichoice++ ) {
           msg(MSG::VERBOSE)  << aUniqueChoice.at(ichoice) << ",";
         }
-        msg(MSG::VERBOSE) << endreq;
+        msg(MSG::VERBOSE) << endmsg;
       }
 
       // Loop over all containers
@@ -424,7 +424,9 @@ StatusCode ParticleCombinerTool::addBranches() const
       } // end the loop over the available containers to build INav4MomLink objects
 
       // Now, actually build the CompositeParticle from the list of ElementLinks to INavigable4Momentum
+      ATH_MSG_DEBUG("building composite particle");
       ATH_CHECK( buildComposite( outContainer, m_anIPartLinkList, metObject ) );
+      ATH_MSG_DEBUG("done");
 
     } // End: while ( anOdometer.increment() )
 
@@ -492,22 +494,29 @@ StatusCode ParticleCombinerTool::buildComposite( xAOD::CompositeParticleContaine
 
   bool ParticlesAreValid = true;
 
+  ATH_MSG_VERBOSE("Now in buildComposite with outContainer size=" << outContainer->size()
+                  << ", anIPartLinkList size=" << anIPartLinkList.size() << ", and a met object with address=" << metObject );
+  
   //Loop over all ElementLinks to INavigable4Momenta and get the INavigable4Momenta
   for ( const xAOD::IParticleLink& aParticleLink  :  anIPartLinkList ) {
+    ATH_MSG_VERBOSE("buildComposite: Looping over a particle link");
     // Check if this ElementLink is valid
     if ( aParticleLink.isValid() ) {
       // Get the particle from the ElementLink
       const xAOD::IParticle* aParticle = *aParticleLink;
+      ATH_MSG_VERBOSE("buildComposite: Particle is valid");
 
       if (aParticle) {
+        ATH_MSG_VERBOSE("buildComposite: Have a particle");
         // determine if the particle has any daughter in common with
         // a previous particle in the composite:
         for ( const xAOD::IParticleLink* otherPartLink  :  theParticleLinks ) {
+          ATH_MSG_VERBOSE("Looking for shared daughters");
           // Now, make the check for having any constituent shared.
           // Note that we don't need to check if the otherPartLink is valid
           // since this happened already when we filled that vector
-          if ( shareSameConstituents( aParticle, **otherPartLink ) ) {
-            ATH_MSG_DEBUG ( "Found aParticle overlaps with another INavigable4Momentum in the composite!" );
+          if ( this->shareSameConstituents( aParticle, **otherPartLink ) ) {
+            ATH_MSG_DEBUG ( "buildComposite: Found aParticle overlaps with another INavigable4Momentum in the composite!" );
             ParticlesAreValid &= false;
             break;
           }
@@ -515,29 +524,34 @@ StatusCode ParticleCombinerTool::buildComposite( xAOD::CompositeParticleContaine
 
         // push the particle onto the candidate's input list
         if ( ParticlesAreValid ) {
+          ATH_MSG_VERBOSE("buildComposite: Particles are valid");
           theParticleLinks.push_back( &aParticleLink );
         }
       }
       else {
-        ATH_MSG_DEBUG ( "Found non-valid particle at an ElementLink location!" );
+        ATH_MSG_DEBUG ( "buildComposite: Found non-valid particle at an ElementLink location!" );
         ParticlesAreValid &= false;
       } // check if aParticle exists at all
     }
     else {
-      ATH_MSG_DEBUG ( "Found non-valid ElementLink for a particle!" );
+      ATH_MSG_DEBUG ( "buildComposite: Found non-valid ElementLink for a particle!" );
       ParticlesAreValid &= false;
     } // check the link to a particle
 
     if ( false == ParticlesAreValid ) {
+      ATH_MSG_VERBOSE("buildComposite: particles are not valid");
       break;
     }
   } // End: loop over vector of ElementLinks
 
 
+  ATH_MSG_VERBOSE("buildComposite: Done looping over vector of ElementLinks");
+  
   //-----------------------------------------
   // Do the combination
   //-----------------------------------------
   if ( ParticlesAreValid ) {
+    ATH_MSG_VERBOSE("buildComposite: Particles are valid");  
     // Sort the constituents in decending pt order, if requested
     if ( m_sortConstit.value() ) {
       std::sort( anIPartLinkList.begin(), anIPartLinkList.end(),
@@ -545,6 +559,7 @@ StatusCode ParticleCombinerTool::buildComposite( xAOD::CompositeParticleContaine
                    return CxxUtils::fpcompare::greater( (*a)->pt(), (*b)->pt() );
                  } );
     }
+    ATH_MSG_VERBOSE("buildComposite: Particles are sorted");
 
     // Actually create the composite particle
     //--------------------------------------------------------------
@@ -554,22 +569,24 @@ StatusCode ParticleCombinerTool::buildComposite( xAOD::CompositeParticleContaine
     xAOD::CompositeParticle* compPart = new xAOD::CompositeParticle();
     compPart->makePrivateStore();
     for ( const xAOD::IParticleLink& aParticleLink  :  anIPartLinkList ) {
+      ATH_MSG_VERBOSE("buildComposite: Adding constituet");
       chargeSum += this->getCharge( aParticleLink, hasCharge );
       compPart->addPart( aParticleLink );
     }
     // Add also the missing ET object to the composite particle, if we have one
     if (metObject) {
+      ATH_MSG_VERBOSE("buildComposite: Adding met object");
       compPart->setMissingET(metObject);
     }
     // Set the PDG ID for this composite particle
     compPart->setPdgId( m_pdgId.value() );
     // Set the charge (if we were able to calculate it) for this composite particle
     if ( hasCharge ) {
-      ATH_MSG_VERBOSE("Setting the charge of the current composite particle to " << chargeSum );
+      ATH_MSG_VERBOSE("buildComposite: Setting the charge of the current composite particle to " << chargeSum );
       compPart->setCharge(chargeSum);
     }
     else {
-      ATH_MSG_DEBUG("Couldn't set the charge of the composite particle");
+      ATH_MSG_DEBUG("buildComposite: Couldn't set the charge of the composite particle");
     }
 
     // Check if this composite particle has been found before
@@ -608,20 +625,19 @@ StatusCode ParticleCombinerTool::buildComposite( xAOD::CompositeParticleContaine
       // AK: Commented the conditional statements until "passAll" is actually
       //     used here. To silence a Coverity warning.
 //      if ( passAll ) {
-        outContainer->push_back( compPart );
-//      }
-//      else {
-//        delete compPart;
-//      }
+      ATH_MSG_VERBOSE("buildComposite: Adding composite particle to container");
+      outContainer->push_back( compPart );
     }
     else {
-      // Output message
-      ATH_MSG_DEBUG ( "Found this composite particle already before..." );
+      ATH_MSG_VERBOSE("buildComposite: deleting composite particle");
       delete compPart;
-    } // End: if compositeParticleAlreadyFound
-
+    }
+    
+    ATH_MSG_VERBOSE("buildComposite: End: if compositeParticleAlreadyFound");
+    
   } // End: Saveguard check if all particles are valide
 
+  ATH_MSG_VERBOSE("Returning from buildComposite");
   return StatusCode::SUCCESS;
 }
 
@@ -776,12 +792,13 @@ bool ParticleCombinerTool::isEqual( const xAOD::IParticle* part1,
 // composite particles, that they don't share the same constitutents
 //=============================================================================
 bool ParticleCombinerTool::shareSameConstituents( const xAOD::IParticle* part1,
-                                                  const xAOD::IParticle* part2 ) const
+                                                    const xAOD::IParticle* part2 ) const
 {
   const xAOD::CompositeParticle* compPart1 =
     dynamic_cast<const xAOD::CompositeParticle*> (part1) ;
   const xAOD::CompositeParticle* compPart2 =
     dynamic_cast<const xAOD::CompositeParticle*> (part2) ;
+  ATH_MSG_VERBOSE("in shareSameConstituents('IParticle','IParticle')");
 
   // Neither of the two is a composite particle
   if ( !compPart1 && !compPart2 ) {
@@ -789,17 +806,17 @@ bool ParticleCombinerTool::shareSameConstituents( const xAOD::IParticle* part1,
   }
   // One of them is a composite
   else if ( compPart1 && !compPart2 ) {
-    return shareSameConstituents( part2, compPart1 );
+    return this->shareSameConstituents( part2, compPart1 );
   }
   else if ( !compPart1 && compPart2 ) {
-    return shareSameConstituents( part1, compPart2 );
+    return this->shareSameConstituents( part1, compPart2 );
   }
   // Both are composite candidates
   // AK: By this time only one options remains: That both of them are composite
   //     particles. So it's not necessary to do any more checks. This silences
   //     a Covery warning.
   else {
-    return shareSameConstituents( compPart1, compPart2 );
+    return this->shareSameConstituents( compPart1, compPart2 );
   }
 }
 
@@ -815,7 +832,8 @@ bool ParticleCombinerTool::shareSameConstituents( const xAOD::IParticle* part1,
 {
   // Default return
   bool isConstituent = false;
-
+  ATH_MSG_VERBOSE("in shareSameConstituents('IParticle','CompositeParticle')");
+  
   // Loop over all constituents of the composite particle to be tested
   const std::size_t nConstit = compPart2->nParts();
   for( std::size_t i=0; i<nConstit; ++i ) {
@@ -851,18 +869,21 @@ bool ParticleCombinerTool::shareSameConstituents( const xAOD::CompositeParticle*
 {
   // Default return
   bool isConstituent = false;
+  ATH_MSG_VERBOSE("in shareSameConstituents('CompositeParticle','CompositeParticle')");
 
   // Loop over all constituents of the composite particle to be tested
   const std::size_t nConstit1 = compPart1->nParts();
   const std::size_t nConstit2 = compPart2->nParts();
   for( std::size_t i=0; i<nConstit1; ++i ) {
     const xAOD::IParticle* part1 = compPart1->part(i);
-
+    ATH_MSG_VERBOSE("looking at compositeParticle1 constituent " << i << "/" << nConstit1);
+    
     // Check if this constituent itself is a composite particle
     const xAOD::CompositeParticle* constitCP1 =
       dynamic_cast<const xAOD::CompositeParticle*> (part1) ;
 
-    for( std::size_t j=0; i<nConstit2; ++j ) {
+    for( std::size_t j=0; j<nConstit2; ++j ) {
+      ATH_MSG_VERBOSE("looking at compositeParticle2 constituent " << j << "/" << nConstit2);
       const xAOD::IParticle* part2 = compPart2->part(j);
 
       // Check if this constituent itself is a composite particle
@@ -873,13 +894,13 @@ bool ParticleCombinerTool::shareSameConstituents( const xAOD::CompositeParticle*
         isConstituent = this->isEqual( part1, part2 );
       }
       if ( !constitCP1 && constitCP2 ) {
-        isConstituent = shareSameConstituents( part1, constitCP2 );
+        isConstituent = this->shareSameConstituents( part1, constitCP2 );
       }
       if ( constitCP1 && !constitCP2 ) {
-        isConstituent = shareSameConstituents( part2, constitCP1 );
+        isConstituent = this->shareSameConstituents( part2, constitCP1 );
       }
       if ( constitCP1 && constitCP2 ) {
-        isConstituent = shareSameConstituents( constitCP1, constitCP2 );
+        isConstituent = this->shareSameConstituents( constitCP1, constitCP2 );
       }
       if ( isConstituent ) {
         return true;
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleCombinerTool.h b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleCombinerTool.h
index 052441347a1..a521ae857da 100644
--- a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleCombinerTool.h
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleCombinerTool.h
@@ -61,10 +61,10 @@ public:
 
 public:
   /** Gaudi Service Interface method implementations - initialize */
-  StatusCode initialize() ;
+  virtual StatusCode initialize() override;
 
   /** Gaudi Service Interface method implementations - finalize */
-  StatusCode finalize() ;
+  virtual StatusCode finalize() override;
 
   /// Implement the method from the IAugmentationTool interface
   virtual StatusCode addBranches() const final override;
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleRemoverAlg.cxx b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleRemoverAlg.cxx
new file mode 100644
index 00000000000..4dcc740a171
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleRemoverAlg.cxx
@@ -0,0 +1,315 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// EventUtils includes
+#include "ParticleRemoverAlg.h"
+
+#include "AthContainers/AuxTypeRegistry.h"
+#include "AthContainersInterfaces/IAuxTypeVectorFactory.h"
+
+#include "xAODBase/IParticleContainer.h"
+#include "xAODBase/IParticle.h"
+#include "xAODCore/AuxContainerBase.h"
+#include "xAODCore/ShallowCopy.h"
+#include "xAODEgamma/PhotonContainer.h"
+#include "xAODEgamma/ElectronContainer.h"
+#include "xAODMuon/MuonContainer.h"
+#include "xAODTau/TauJetContainer.h"
+#include "xAODJet/JetContainer.h"
+#include "xAODPFlow/PFOContainer.h"
+#include "xAODTracking/NeutralParticleContainer.h"
+#include "xAODTracking/TrackParticleContainer.h"
+#include "xAODParticleEvent/ParticleContainer.h"
+#include "xAODCaloEvent/CaloClusterContainer.h"
+#include "xAODTruth/TruthParticleContainer.h"
+#include "xAODParticleEvent/CompositeParticleContainer.h"
+
+// boost includes
+#include <boost/algorithm/string/predicate.hpp>
+
+
+ParticleRemoverAlg::ParticleRemoverAlg( const std::string& name, ISvcLocator* pSvcLocator )
+  : AthAlgorithm( name, pSvcLocator ),
+  m_inCont(""),
+  m_separator("___"),
+  m_outCont(""),
+  m_suffixes(),
+  m_viewContNames(),
+  m_resetViewConts(true),
+  m_outPrefix(""),
+  m_inContNameList(),
+  m_outContNameList(),
+  m_inContList(),
+  m_outContList(),
+  m_inViewContNameListList(),
+  m_outViewContNameListList(),
+  m_contType(UNKNOWN)
+{
+  //
+  // Property declaration
+  //
+  declareProperty("Input",  m_inCont, "Input container name" );
+  declareProperty("Output", m_outCont,
+                  "The name of the output container with the deep copy of input objects" );
+
+  declareProperty("Separator", m_separator,
+                  "The string seperator between the output container name and the sytematic variation (default='___')" );
+
+  declareProperty("Suffixes", m_suffixes,
+                  "The names of all suffixes for the input and output container names" );
+
+  declareProperty("SelectedViewContainers", m_viewContNames,
+                  "The names of all view containers that contain particles that we want to retain" );
+
+  declareProperty("RemapViewContainers", m_resetViewConts,
+                  "Boolean to decide if the existing view containers should be re-mapped (default: true)" );
+
+  declareProperty("OutputViewContainerPrefix", m_outPrefix,
+                  "Prefix to be used for all created output view containers" );
+}
+
+
+ParticleRemoverAlg::~ParticleRemoverAlg() {}
+
+
+StatusCode ParticleRemoverAlg::initialize()
+{
+  ATH_MSG_DEBUG ("Initializing " << name() << "...");
+
+  // Print the configuration to the log file
+  ATH_MSG_DEBUG( "Using: " << m_inCont );
+  ATH_MSG_DEBUG( "Using: " << m_outCont );
+  ATH_MSG_DEBUG( "Using: " << m_separator );
+  ATH_MSG_DEBUG( "Using: " << m_suffixes );
+  ATH_MSG_DEBUG( "Using: " << m_viewContNames );
+  ATH_MSG_DEBUG( "Using: " << m_resetViewConts );
+  ATH_MSG_DEBUG( "Using: " << m_outPrefix );
+
+  // Perform some sanity checks on the given container names
+  if ( m_inCont.value().empty() || m_outCont.value().empty() || m_viewContNames.value().empty() ) {
+    ATH_MSG_ERROR("Wrong user setup! You need to give a valid name for both the Input, Output, and SelectedViewContainers!");
+    return StatusCode::FAILURE;
+  }
+
+  // Abort on an unchecked systematics code
+  // CP::SystematicCode::enableFailure();
+
+  // Build the vector of all input and output container names
+  const std::size_t totSize = 1 + m_suffixes.value().size(); // the '1' comes from the InputContainer
+  m_inContNameList.resize(totSize);
+  m_inContList.resize(totSize);
+  m_outContNameList.resize(totSize);
+  m_inContNameList[0]  = m_inCont.value();
+  m_outContNameList[0] = m_outCont.value();
+  for ( std::size_t i=1; i<totSize; ++i ) {
+    const std::string& currentSuffix = m_suffixes.value()[i-1];
+    ATH_MSG_VERBOSE("Using current suffix " << currentSuffix << " to search for matching containers");
+    if (boost::starts_with( currentSuffix, m_separator.value() )) {
+      m_inContNameList[i]  = m_inCont.value()  + currentSuffix;
+      m_outContNameList[i] = m_outCont.value() + currentSuffix;
+    }
+    else {
+      m_inContNameList[i]  = m_inCont.value()  + m_separator.value() + currentSuffix;
+      m_outContNameList[i] = m_outCont.value() + m_separator.value() + currentSuffix;
+    }
+  }
+  // Print out the matches that we found
+  if ( msgLvl(MSG::VERBOSE) ) {
+    for ( std::size_t i=0; i<m_inContNameList.size(); ++i ){
+      ATH_MSG_VERBOSE("Matched input number " << i << " with input name " << m_inContNameList[i] << " to output name " << m_outContNameList[i]);
+    }
+  }
+
+
+
+  // Now, also try to map all the view container names to the input (shallow
+  // copy) containers. Set up with that the correct mapping of the new output
+  // view container names.
+  // Assume that all names where we have a suffix, but where we cannot match it
+  // to a suffix of the input container, it belongs to the origninal one.
+  if ( m_resetViewConts.value() || !(m_outPrefix.value().empty()) ){
+    ATH_MSG_VERBOSE("Going to iterate over " << totSize << " elements");
+    m_inViewContNameListList.reserve(totSize);
+    m_outViewContNameListList.reserve(totSize);
+    for ( std::size_t i=0; i<totSize; ++i ) {
+      ATH_MSG_VERBOSE("At " << i << "-th element");
+      if (i==0){
+        // This is the master container without any "___" in its name
+        std::vector<std::string> inViewNames;
+        std::vector<std::string> outViewNames;
+        for ( const std::string& inViewName : m_viewContNames.value() ){
+          ATH_MSG_VERBOSE("Looking at input view container name: " << inViewName);
+          std::size_t pos = inViewName.find(m_separator.value());
+          if ( pos == std::string::npos ){ // the separator is not found
+            ATH_MSG_VERBOSE("No seperator found");
+            inViewNames.push_back(inViewName);
+            outViewNames.push_back( m_outPrefix.value() + inViewName );
+            ATH_MSG_VERBOSE("Added input name " << inViewNames.back() << " and output name " << outViewNames.back());
+          }
+          else {
+            pos += m_separator.value().length();
+            const std::string foundSuffix = inViewName.substr(pos, std::string::npos);
+            ATH_MSG_VERBOSE("Seperator found and suffix found: " << foundSuffix);
+            // the separator is found, but the found suffix doesn't match any of the provided ones
+            if ( std::find( m_suffixes.value().begin(), m_suffixes.value().end(), foundSuffix) == m_suffixes.value().end() ){
+              inViewNames.push_back(inViewName);
+              outViewNames.push_back( m_outPrefix.value() + inViewName );
+              ATH_MSG_VERBOSE("Added2 input name " << inViewNames.back() << " and output name " << outViewNames.back());
+            }
+          }
+        }
+        m_inViewContNameListList.push_back(inViewNames);
+        m_outViewContNameListList.push_back(outViewNames);
+      }
+      else {
+        const std::string& currentSuffix = m_suffixes.value()[i-1];
+        ATH_MSG_VERBOSE("Looking at current suffix: " << currentSuffix);
+        std::vector<std::string> inViewNames;
+        std::vector<std::string> outViewNames;
+        for ( const std::string& inViewName : m_viewContNames.value() ){
+          ATH_MSG_VERBOSE("Looking at current input view container name: " << inViewName);
+          if ( inViewName.find(m_separator.value()+currentSuffix) != std::string::npos ){ // the suffix is found
+            inViewNames.push_back(inViewName);
+            outViewNames.push_back( m_outPrefix.value() + inViewName );
+            ATH_MSG_VERBOSE("Added3 input name " << inViewNames.back() << " and output name " << outViewNames.back());
+          }
+        }
+        m_inViewContNameListList.push_back(inViewNames);
+        m_outViewContNameListList.push_back(outViewNames);
+      }
+    } // End: loop over all containers
+  }
+  // Some sanity printouts
+  if ( msgLvl(MSG::VERBOSE) ) {
+    ATH_MSG_VERBOSE("Printing final input and output names...");
+    for ( std::size_t i=0; i<m_inViewContNameListList.size(); ++i ){
+      ATH_MSG_VERBOSE("    At i=" << i << "-th element");
+      const std::vector<std::string>& inViewNameList  = m_inViewContNameListList[i];
+      const std::vector<std::string>& outViewNameList = m_outViewContNameListList[i];
+      ATH_MSG_VERBOSE("    Have " << inViewNameList.size() << " in view elements and " << outViewNameList.size() << " out view elements");
+      for ( std::size_t j=0; j<inViewNameList.size(); ++j ){
+        ATH_MSG_VERBOSE("        At j=" << j << "-th element");
+        const std::string& inName  = inViewNameList[j];
+        const std::string& outName = outViewNameList[j];
+        ATH_MSG_VERBOSE("        Have input name " << inName << " paired with out name " << outName);
+      }
+    }
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+
+
+StatusCode ParticleRemoverAlg::finalize()
+{
+  ATH_MSG_DEBUG ("Finalizing " << name() << "...");
+
+  return StatusCode::SUCCESS;
+}
+
+
+
+StatusCode ParticleRemoverAlg::execute()
+{
+  ATH_MSG_DEBUG ("Executing " << name() << "...");
+  // Let's first clear some stuff
+  m_inContList.clear();
+  m_inContList.resize(m_inContNameList.size());
+  m_outContList.clear();
+
+  // Figure out what type the input container has, if we didn't do it yet
+  if ( m_contType == UNKNOWN ){
+    if ( evtStore()->contains<xAOD::PhotonContainer>(m_inCont.value()) ){ m_contType = PHOTON; }
+    else if ( evtStore()->contains<xAOD::ElectronContainer>(m_inCont.value()) ){ m_contType = ELECTRON; }
+    else if ( evtStore()->contains<xAOD::MuonContainer>(m_inCont.value()) ){ m_contType = MUON; }
+    else if ( evtStore()->contains<xAOD::TauJetContainer>(m_inCont.value()) ){ m_contType = TAU; }
+    else if ( evtStore()->contains<xAOD::JetContainer>(m_inCont.value()) ){ m_contType = JET; }
+    else if ( evtStore()->contains<xAOD::TruthParticleContainer>(m_inCont.value()) ){ m_contType = TRUTHPARTICLE; }
+    else if ( evtStore()->contains<xAOD::CompositeParticleContainer>(m_inCont.value()) ){ m_contType = COMPOSITEPARTICLE; }
+    else if ( evtStore()->contains<xAOD::PFOContainer>(m_inCont.value()) ){ m_contType = PARITCLEFLOW; }
+    else if ( evtStore()->contains<xAOD::NeutralParticleContainer>(m_inCont.value()) ){ m_contType = NEUTRALPARTICLE; }
+    else if ( evtStore()->contains<xAOD::TrackParticleContainer>(m_inCont.value()) ){ m_contType = TRACKPARTICLE; }
+    else if ( evtStore()->contains<xAOD::ParticleContainer>(m_inCont.value()) ){ m_contType = PARTICLE; }
+    else if ( evtStore()->contains<xAOD::CaloClusterContainer>(m_inCont.value()) ){ m_contType = CALOCLUSTER; }
+  }
+  if ( m_contType == UNKNOWN ){
+    ATH_MSG_FATAL("We couldn't determine the type of the container... abort!");
+    return StatusCode::FAILURE;
+  }
+
+  // Open the input container
+  for ( std::size_t i=0; i<m_inContNameList.size(); ++i ) {
+    ATH_CHECK( evtStore()->retrieve( m_inContList[i], m_inContNameList.at(i) ));
+  }
+
+  // Make a quick check that all input containers have the same size
+  const std::size_t inContSize = m_inContList[0]->size();
+  for ( const xAOD::IParticleContainer* inCont : m_inContList ){
+    if ( inContSize != inCont->size() ){
+      ATH_MSG_FATAL("The input container and its shallow copies don't have the same size! Aborting...");
+      return StatusCode::FAILURE;
+    }
+  }
+
+  // Create a vector of bools with the same size as the input container. This
+  // will be used to say if we want to keep that particular object.
+  // All entries will be initialized to false.
+  std::vector<bool> keepParticleVec (inContSize, false);
+  // Now, loop over all view containers and flag the particles that we want to
+  // keep with true in the above vector of bools.
+  for ( const std::string& viewContName : m_viewContNames.value() ){
+    const xAOD::IParticleContainer* inViewCont = nullptr;
+    ATH_CHECK( evtStore()->retrieve( inViewCont, viewContName ) );
+    // Make a quick check that the provided view containers are not larger
+    if ( inViewCont->size() > inContSize ){
+      ATH_MSG_FATAL("One of the input view containers is larger than the input container... aborting.");
+      return StatusCode::FAILURE;
+    }
+    for ( const xAOD::IParticle* part : *inViewCont ){
+      const std::size_t idx = part->index();
+      keepParticleVec[idx] = true;
+    }
+  }
+
+  // Do the heavy lifting of actually creating the new and reduced output container(s)
+  if ( m_contType == PHOTON ){
+    ATH_CHECK( this->removeParticles<xAOD::PhotonContainer>(keepParticleVec) );
+  }
+  else if ( m_contType == ELECTRON ){
+    ATH_CHECK( this->removeParticles<xAOD::ElectronContainer>(keepParticleVec) );
+  }
+  else if ( m_contType == MUON ){
+    ATH_CHECK( this->removeParticles<xAOD::MuonContainer>(keepParticleVec) );
+  }
+  else if ( m_contType == TAU ){
+    ATH_CHECK( this->removeParticles<xAOD::TauJetContainer>(keepParticleVec) );
+  }
+  else if ( m_contType == JET ){
+    ATH_CHECK( this->removeParticles<xAOD::JetContainer>(keepParticleVec) );
+  }
+  else if ( m_contType == TRUTHPARTICLE ){
+    ATH_CHECK( this->removeParticles<xAOD::TruthParticleContainer>(keepParticleVec) );
+  }
+  else if ( m_contType == COMPOSITEPARTICLE ){
+    ATH_CHECK( this->removeParticles<xAOD::CompositeParticleContainer>(keepParticleVec) );
+  }
+  else if ( m_contType == PARITCLEFLOW ){
+    ATH_CHECK( this->removeParticles<xAOD::PFOContainer>(keepParticleVec) );
+  }
+  else if ( m_contType == NEUTRALPARTICLE ){
+    ATH_CHECK( this->removeParticles<xAOD::NeutralParticleContainer>(keepParticleVec) );
+  }
+  else if ( m_contType == TRACKPARTICLE ){
+    ATH_CHECK( this->removeParticles<xAOD::TrackParticleContainer>(keepParticleVec) );
+  }
+  else if ( m_contType == PARTICLE ){
+    ATH_CHECK( this->removeParticles<xAOD::ParticleContainer>(keepParticleVec) );
+  }
+  else if ( m_contType == CALOCLUSTER ){
+    ATH_CHECK( this->removeParticles<xAOD::CaloClusterContainer>(keepParticleVec) );
+  }
+
+  return StatusCode::SUCCESS;
+}
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleRemoverAlg.h b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleRemoverAlg.h
new file mode 100644
index 00000000000..bbef8d8161f
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleRemoverAlg.h
@@ -0,0 +1,114 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef EVENTUTILS_PARTICLEREMOVERALG_H
+#define EVENTUTILS_PARTICLEREMOVERALG_H 1
+
+#include "AthenaBaseComps/AthAlgorithm.h"
+
+#include "xAODBase/IParticleContainer.h"
+
+
+
+class ParticleRemoverAlg: public ::AthAlgorithm {
+ public:
+  /// Standard constructor
+  ParticleRemoverAlg( const std::string& name, ISvcLocator* pSvcLocator );
+
+  /// Standard destructor
+  virtual ~ParticleRemoverAlg();
+
+  /// Standard Gaudi initialize method called once before the event loop
+  virtual StatusCode  initialize();
+
+  /// Standard Gaudi execute method called once for every event
+  virtual StatusCode  execute();
+
+  /// Standard Gaudi finalize method called once after the event loop
+  virtual StatusCode  finalize();
+
+ private:
+   /// Private function to perform the actualy work
+   template<class CONT>
+   StatusCode removeParticles( const std::vector<bool>& keepParticleVec );
+
+ private:
+
+  /// @name The properties that can be defined via the python job options
+  /// @{
+
+  /// The input container name
+  StringProperty m_inCont;
+
+  /// The string separator between the output container name and the sytematic variation (default="___")
+  StringProperty m_separator;
+
+  /// The output container name
+  StringProperty m_outCont;
+
+  /// The names of all suffixes for the input and output container names
+  StringArrayProperty m_suffixes;
+
+  /// The names of all view containers that contain particles that we want to retain
+  StringArrayProperty m_viewContNames;
+
+  /// Boolean to decide if the existing view containers should be re-mapped (default: true)
+  BooleanProperty m_resetViewConts;
+
+  /// Prefix to be used for all created output view containers
+  StringProperty m_outPrefix;
+
+  /// @}
+
+
+  /// @name Internal members
+  /// @{
+
+  /// Vector of all input container names
+  std::vector<std::string> m_inContNameList;
+
+  /// Vector of all output container names
+  std::vector<std::string> m_outContNameList;
+
+  /// Vector of all input containers
+  std::vector< const xAOD::IParticleContainer* > m_inContList;
+
+  /// Vector of all output containers
+  std::vector< xAOD::IParticleContainer* > m_outContList;
+
+  /// Vector of all input view container names
+  std::vector< std::vector<std::string> > m_inViewContNameListList;
+
+  /// Vector of all output view container names
+  std::vector< std::vector<std::string> > m_outViewContNameListList;
+
+
+  /// An enumaration for the actual container type
+  enum contType_t {
+    UNKNOWN,
+    PHOTON,
+    ELECTRON,
+    MUON,
+    TAU,
+    JET,
+    PARITCLEFLOW,
+    NEUTRALPARTICLE,
+    TRACKPARTICLE,
+    TRUTHPARTICLE,
+    COMPOSITEPARTICLE,
+    PARTICLE,
+    CALOCLUSTER
+  };
+
+  /// The variable that holds the value that we find for the input container
+  contType_t m_contType;
+
+  /// @}
+
+};
+
+// Include the templated code here. This must be done from this header file.
+#include "ParticleRemoverAlg.icc"
+
+#endif //> !EVENTUTILS_PARTICLEREMOVERALG_H
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleRemoverAlg.icc b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleRemoverAlg.icc
new file mode 100644
index 00000000000..5a1c5f5f37c
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleRemoverAlg.icc
@@ -0,0 +1,242 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include "xAODBase/IParticle.h"
+#include "AthContainers/AuxTypeRegistry.h"
+#include "AthContainersInterfaces/IAuxTypeVectorFactory.h"
+#include "xAODCore/AuxContainerBase.h"
+#include "xAODCore/ShallowCopy.h"
+#include "AthContainers/ConstDataVector.h"
+
+// boost includes
+#include <boost/algorithm/string/predicate.hpp>
+
+
+
+template<class CONT>
+StatusCode ParticleRemoverAlg::removeParticles( const std::vector<bool>& keepParticleVec )
+{
+  ATH_MSG_DEBUG ("removeParticles(...) " << name() << "...");
+
+  // Get the type of particle that the current container CONT has
+  typedef typename CONT::base_value_type PART;
+
+  // First, get the size of the current input container
+  const std::size_t inContSize = m_inContList[0]->size();
+
+  // Create a new output container and its associated auxiliary container
+  CONT* outCont = new CONT(SG::OWN_ELEMENTS);
+  outCont->reserve(inContSize);
+  ATH_CHECK( evtStore()->record ( outCont, m_outContNameList.at(0) ) );
+  xAOD::AuxContainerBase* outAuxContainer = new xAOD::AuxContainerBase();
+  outAuxContainer->reserve(inContSize);
+  ATH_CHECK( evtStore()->record( outAuxContainer, m_outContNameList.at(0) + "Aux." ) );
+  outCont->setStore( outAuxContainer );
+  m_outContList.push_back(outCont);
+
+  // Create a vector for the original indices of the input particles in their container
+  std::vector< std::size_t > inPartIdxList;
+  inPartIdxList.reserve(inContSize);
+  // Also, create a map from the old index to the new one using a vector with
+  // the same size as the old input containers has.
+  std::vector<int> oldToNewIndex;
+  oldToNewIndex.reserve(inContSize);
+
+  // Now, copy the elements that we want to keep from the input container to the
+  // output container.
+  for ( std::size_t i=0; i<inContSize; ++i ){
+    if ( keepParticleVec[i] == false ){
+      oldToNewIndex.push_back(-1);
+      continue; // we don't want to keep this particle
+    }
+    const xAOD::IParticle* inPart = m_inContList[0]->at(i);
+    const std::size_t inPartIdx = inPart->index();
+    // Now, copy over the input particle to the output particle
+    // (use a pre-processor macro for this repeated task)
+    PART* outPart = new PART();
+    outCont->push_back(outPart);
+    *outPart = *(static_cast<const PART*>(inPart));
+    // Store also the orignial index for this particle
+    inPartIdxList.push_back(inPartIdx);
+    oldToNewIndex.push_back( inPartIdxList.size() - 1 );
+  }
+
+  // Get the size of the output container
+  const std::size_t outContSize = outCont->size();
+
+  // Get the global registry for all aux data:
+  SG::AuxTypeRegistry& reg = SG::AuxTypeRegistry::instance();
+
+
+  // Now, do also the selection for all shallow copy containers, i.e., create
+  // new ones for the outCont that we just created and copy the values
+  // from the original input shallow copy containers over to these new ones
+  for ( std::size_t contIdx=1; contIdx<m_outContNameList.size(); ++contIdx ) {
+    // Get the original electron shallow copy container
+    const auto* originalShallowCopyCont = m_inContList.at(contIdx);
+    ATH_MSG_VERBOSE("Got input ShallowCopyContainer with name: " << m_inContNameList.at(contIdx));
+
+    // Create the current shallow copy container and record it to StoreGate
+    auto outContShallowCopy = xAOD::shallowCopyContainer( *outCont );
+    ATH_CHECK( evtStore()->record( outContShallowCopy.first,  m_outContNameList.at(contIdx) ) );
+    ATH_CHECK( evtStore()->record( outContShallowCopy.second, m_outContNameList.at(contIdx) + "Aux." ) );
+    ATH_MSG_VERBOSE("Recorded new output ShallowCopyContainer with name: " << m_outContNameList.at(contIdx));
+
+    // Also add the output shallow copy to the list of output containers
+    m_outContList.push_back(outContShallowCopy.first);
+
+    // Copy the variables that are stored in the input ShallowCopyContainer
+    // locally (i.e., NOT only present in the master container, but where the
+    // variable lives in the ShallowCopyContainer) from there
+    // If the input had size zero, we are done
+    if ( originalShallowCopyCont->size() == 0 ) {
+      ATH_MSG_VERBOSE("Input ShallowCopy container has size zero... we are done");
+      continue;
+    }
+
+    // Get the auxIDs, i.e., the identifiers from the input ShallowCopyContainer
+    const xAOD::ShallowAuxContainer* originalShallowCopyAuxCont
+      = dynamic_cast<const xAOD::ShallowAuxContainer*>(originalShallowCopyCont->getStore());
+    if ( !originalShallowCopyAuxCont ) {
+      ATH_MSG_ERROR("We don't seem to have a ShallowAuxContainer");
+      return StatusCode::FAILURE;
+    }
+    const SG::IAuxStore* auxStore = originalShallowCopyAuxCont->getStore();
+    if (!auxStore) {
+      ATH_MSG_FATAL("Could not get the aux store of the original ShallowCopyContainer");
+      return StatusCode::FAILURE;
+    }
+    const SG::auxid_set_t& auxIDs = auxStore->getAuxIDs();
+    ATH_MSG_DEBUG("We have " << auxIDs.size() << " variables to copy over for this ShallowCopyContainer");
+
+    // Iterate over all auxIDs and copy each one over
+    for ( auto auxid : auxIDs ) {
+      ATH_MSG_VERBOSE("We are now at auxID=" << auxid );
+
+      // Get the type of this variable:
+      const std::type_info* type = reg.getType( auxid );
+      if ( ! type ) {
+        ATH_MSG_FATAL("Could not get the type of auxid: " << auxid );
+        return StatusCode::FAILURE;
+      }
+      ATH_MSG_VERBOSE("Got the type with name: " << type->name() );
+
+      // First let's get the vector factory of this variable:
+      const SG::IAuxTypeVectorFactory* factory =
+      SG::AuxTypeRegistry::instance().getFactory( *type );
+      if ( ! factory ) {
+        ATH_MSG_FATAL("Could not get the vector factory for type: " << type->name() );
+        return StatusCode::FAILURE;
+      }
+      ATH_MSG_VERBOSE("Got the vector factory for type: " << type->name() );
+
+
+      // If the parent doesn't have this variable, then we're done already:
+      const void* originalShallowAuxDataVector = auxStore->getData( auxid );
+      if ( ! originalShallowAuxDataVector ) {
+        ATH_MSG_WARNING("Could not get the aux data vector of the original ShallowCopyContainer for auxid=" << auxid
+                        << ". The input container had size " << originalShallowCopyCont->size()
+                        << ", and the output container had size " << outContSize );
+        continue;
+        //return StatusCode::FAILURE;
+      }
+      ATH_MSG_VERBOSE("This auxID=" << auxid << " is part of the ShallowCopyAuxStore...");
+
+      // Create the variable in the dynamic store of the new ShallowCopyContainer
+      void* outContAuxDataVec = outContShallowCopy.second->getData( auxid, outContSize, outContSize );
+
+
+      // Then, loop over these, get the index of the corresponding object in the
+      // input shallow copy container and copy the variables that are stored there
+      // locally (i.e., NOT only present in the master container, but where the
+      // variable lives in the ShallowCopyContainer) from there
+      for ( std::size_t i=0; i<outContSize; ++i ) {
+        // Get the original shallow copy particle
+        const std::size_t inIdx = inPartIdxList.at(i);
+        factory->copy( outContAuxDataVec, i, originalShallowAuxDataVector, inIdx );
+      }
+
+    } // End: Loop over all aux-ids
+
+  } // End: loop over output shallow copy containers
+
+
+  // Now, also create the new view containers that point to the objects in the
+  // new, reduced, containers that we just produced above (both the master
+  // container and all its shallow copy containers).
+  /// This will only be done if we have a valid prefix.
+  if ( !(m_outPrefix.value().empty()) ){
+    ATH_MSG_DEBUG("Will now also go and create new output view containers with the prefix " << m_outPrefix.value() );
+    for ( std::size_t i=0; i<m_inViewContNameListList.size(); ++i ){
+      const std::vector<std::string>& inViewNames  = m_inViewContNameListList[i];
+      const std::vector<std::string>& outViewNames = m_outViewContNameListList[i];
+      const xAOD::IParticleContainer* currentOutCont = m_outContList[i];
+      for ( std::size_t j=0; j<inViewNames.size(); ++j ){
+        const std::string& inViewName  = inViewNames[j];
+        const std::string& outViewName = outViewNames[j];
+        ATH_MSG_VERBOSE("Going to create a new view container with name '" << outViewName
+                        << "' from original view container with name '" << inViewName << "'" );
+        const xAOD::IParticleContainer* inViewCont = nullptr;
+        ATH_CHECK( evtStore()->retrieve( inViewCont, inViewName ) );
+        ConstDataVector<CONT>* outViewCont = new ConstDataVector<CONT>(SG::VIEW_ELEMENTS);
+        outViewCont->reserve(inViewCont->size());
+        ATH_CHECK( evtStore()->record ( outViewCont, outViewName ) );
+        for ( const xAOD::IParticle* inViewPart : *inViewCont ){
+          const std::size_t oldIdx = inViewPart->index();
+          const std::size_t newIdx = oldToNewIndex[oldIdx];
+          const xAOD::IParticle* outPart = (*currentOutCont)[newIdx];
+          outViewCont->push_back(static_cast<const PART*>(outPart));
+        }
+      }
+    }
+  }
+
+
+  // Now, also try to re-bend the existing view containers to point to the new
+  // containers.
+  if (m_resetViewConts.value()){
+    ATH_MSG_DEBUG("Will now also go and try to re-map the input view containers to the new containers");
+    for ( std::size_t i=0; i<m_inViewContNameListList.size(); ++i ){
+      const std::vector<std::string>& inViewNames  = m_inViewContNameListList[i];
+      const xAOD::IParticleContainer* currentOutCont = m_outContList[i];
+      for ( std::size_t j=0; j<inViewNames.size(); ++j ){
+        const std::string& inViewName  = inViewNames[j];
+        ATH_MSG_VERBOSE("Going to re-map existing view container with name '" << inViewName << "'" );
+        const CONT* inViewCont = nullptr;
+        ATH_CHECK( evtStore()->retrieve( inViewCont, inViewName ) );
+        ATH_MSG_DEBUG("Got the input view container with name: " << inViewName << " and size: " << inViewCont->size() );
+        ConstDataVector<CONT>* outViewCont = new ConstDataVector<CONT>(SG::VIEW_ELEMENTS);
+        outViewCont->reserve(inViewCont->size());
+        for ( std::size_t partIdx=0; partIdx<inViewCont->size(); ++partIdx ){
+          const PART* inViewPart = inViewCont->at(partIdx);
+          const SG::AuxVectorData* oldCont = inViewPart->container();
+          const std::size_t oldIdx = inViewPart->index();
+          const std::size_t newIdx = oldToNewIndex[oldIdx];
+          const xAOD::IParticle* outPart = (*currentOutCont)[newIdx];
+          outViewCont->push_back(static_cast<const PART*>(outPart));
+          ATH_MSG_VERBOSE("Did re-map particle from old index " << oldIdx
+                          << " to new index " << inViewCont->at(partIdx)->index()
+                          << " and old container " << oldCont
+                          << " to new container " << inViewCont->at(partIdx)->container() );
+        }
+        ATH_MSG_DEBUG("Going to overwrite view container with name: " << inViewName << " and size: " << outViewCont->size() );
+        for ( const PART* part : *outViewCont ){
+          ATH_MSG_VERBOSE("Have an old pointer adress of: " << part );
+          ATH_MSG_VERBOSE("Have an old particle with pt= " << 0.001*(part->pt()) );
+        }
+        ATH_CHECK( evtStore()->overwrite( outViewCont, inViewName ) );
+        ATH_MSG_DEBUG("Did overwrite view container with name:      " << inViewName << " and size: " << outViewCont->size() );
+        for ( const PART* part : *outViewCont ){
+          ATH_MSG_VERBOSE("Have a new pointer adress of: " << part );
+          ATH_MSG_VERBOSE("Have a new particle with pt= " << 0.001*(part->pt()) );
+        }
+      }
+    }
+  }
+
+  return StatusCode::SUCCESS;
+}
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSelectionAlg.cxx b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSelectionAlg.cxx
index 58e97ac28b6..8b1ed66e746 100644
--- a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSelectionAlg.cxx
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSelectionAlg.cxx
@@ -18,7 +18,45 @@
 #include "GaudiKernel/Property.h"
 #include "GaudiKernel/IJobOptionsSvc.h"
 #include "DerivationFrameworkInterfaces/IAugmentationTool.h"
-
+#include "ExpressionEvaluation/ExpressionParser.h"
+#include "ExpressionEvaluation/SGxAODProxyLoader.h"
+#include "ExpressionEvaluation/MultipleProxyLoader.h"
+#include "ExpressionEvaluation/StackElement.h"
+// #include "TrigDecisionTool/TrigDecisionTool.h"
+// #include "ExpressionEvaluation/TriggerDecisionProxyLoader.h"
+
+// EDM includes
+#include "EventInfo/EventStreamInfo.h"
+#include "xAODBase/IParticleContainer.h"
+#include "xAODBase/IParticle.h"
+#include "xAODCore/AuxContainerBase.h"
+#include "xAODEgamma/PhotonContainer.h"
+#include "xAODEgamma/PhotonAuxContainer.h"
+#include "xAODEgamma/ElectronContainer.h"
+#include "xAODEgamma/ElectronAuxContainer.h"
+#include "xAODMuon/MuonContainer.h"
+#include "xAODMuon/MuonAuxContainer.h"
+#include "xAODTau/TauJetContainer.h"
+#include "xAODTau/TauJetAuxContainer.h"
+#include "xAODJet/JetContainer.h"
+#include "xAODJet/JetAuxContainer.h"
+#include "xAODPFlow/PFOContainer.h"
+#include "xAODPFlow/PFOAuxContainer.h"
+#include "xAODTracking/NeutralParticleContainer.h"
+#include "xAODTracking/NeutralParticleAuxContainer.h"
+#include "xAODTracking/TrackParticleContainer.h"
+#include "xAODTracking/TrackParticleAuxContainer.h"
+#include "xAODParticleEvent/ParticleContainer.h"
+#include "xAODParticleEvent/ParticleAuxContainer.h"
+#include "xAODCaloEvent/CaloClusterContainer.h"
+#include "xAODCaloEvent/CaloClusterAuxContainer.h"
+#include "xAODTruth/TruthParticleContainer.h"
+#include "xAODTruth/TruthParticleAuxContainer.h"
+#include "xAODParticleEvent/CompositeParticleContainer.h"
+#include "xAODParticleEvent/CompositeParticleAuxContainer.h"
+#include "xAODCutFlow/CutBookkeeper.h"
+#include "xAODCutFlow/CutBookkeeperContainer.h"
+#include "xAODCutFlow/CutBookkeeperAuxContainer.h"
 
 
 ///////////////////////////////////////////////////////////////////
@@ -29,55 +67,47 @@
 ////////////////
 ParticleSelectionAlg::ParticleSelectionAlg( const std::string& name,
                                             ISvcLocator* pSvcLocator ) :
-  ::AthAlgorithm( name, pSvcLocator ),
-  m_jos("JobOptionsSvc", name),
-  m_tool("ParticleSelectionTool/ParticleSelectionTool", this),
+  ::AthAnalysisAlgorithm( name, pSvcLocator ),
+  m_selTools(),     // makes these tools public
+  m_selWVtxTools(), // makes these tools public
+  m_evtInfoName("EventInfo"),
+  m_inPrimVtxCont("PrimaryVertices"),
   m_inCollKey(""),
-  m_setInCollKey(false),
   m_outCollKey(""),
-  m_setOutCollKey(false),
-  m_outCollType(""),
-  m_setOutCollType(false),
-  m_writeSplitAux(false),
-  m_setWriteSplitAux(false),
-  m_outOwnPolicyName("OWN_ELEMENTS"),
-  m_setOwnPolicy(false),
-  m_outLinkCollKey(""),
-  m_setOutLinkCollKey(false),
+  m_writeSplitAux(true),
+  m_outOwnPolicyName("VIEW_ELEMENTS"),
   m_selection(""),
-  m_setSelection(false),
-  m_nEventsProcessed(0)
+  m_doCutFlow(false),
+  m_cutBKCName(name),
+  m_parser(nullptr),
+  // m_trigDecisionTool("Trig::TrigDecisionTool/TrigDecisionTool"),
+  m_nEventsProcessed(0),
+  m_outOwnPolicy(SG::VIEW_ELEMENTS),
+  m_contType(UNKNOWN),
+  m_cutBKStartIdx(0),
+  m_selToolIdxOffset(),
+  m_selWPVToolIdxOffset(),
+  m_idxSelParster(0)
 {
-  declareProperty("JobOptionsSvc",       m_jos, "The JobOptionService instance.");
-
-  declareProperty("SelectionTool",       m_tool, "The private tool that will select the particles within a container" );
-
-  declareProperty("InputContainer",      m_inCollKey="",   "Input container name" );
-  m_inCollKey.declareUpdateHandler( &ParticleSelectionAlg::setupInputContainer, this );
-
-  declareProperty("OutputContainer",     m_outCollKey="",
-                  "The name of the output container with the deep copy of selected xAOD::IParticles" );
-  m_outCollKey.declareUpdateHandler( &ParticleSelectionAlg::setupOutputContainer, this );
-
-  declareProperty("OutputContainerType", m_outCollType="",
-                  "The type of the output container, e.g., 'xAOD::JetContainer'" );
-  m_outCollType.declareUpdateHandler( &ParticleSelectionAlg::setupOutputContainerType, this );
-
-  declareProperty("WriteSplitOutputContainer", m_writeSplitAux=false,
-                  "Decide if we want to write a fully-split AuxContainer such that we can remove any variables" );
-  m_writeSplitAux.declareUpdateHandler( &ParticleSelectionAlg::setupWriteSplitOutputContainer, this );
-
-  declareProperty("OutputContainerOwnershipPolicy", m_outOwnPolicyName="OWN_ELEMENTS",
-                  "Defines the ownership policy of the output container (default: 'OWN_ELEMENTS'; also allowed: 'VIEW_ELEMENTS')" );
-  m_outOwnPolicyName.declareUpdateHandler( &ParticleSelectionAlg::setupOutputContainerOwnPolicy, this );
-
-  declareProperty("OutputLinkContainer", m_outLinkCollKey="",
-                  "The name of the output container of ElementLinks to the selected xAOD::IParticles" );
-  m_outLinkCollKey.declareUpdateHandler( &ParticleSelectionAlg::setupOutputLinkContainer, this );
-
-  declareProperty("Selection",           m_selection="",
-                  "The selection string that defines which xAOD::IParticles to select from the container" );
-  m_selection.declareUpdateHandler( &ParticleSelectionAlg::setupSelection, this );
+  declareProperty("EventInfo",                 m_evtInfoName,   "Input container name");
+  declareProperty("PrimaryVertexContainer",    m_inPrimVtxCont, "The input primary vertex container name");
+  declareProperty("InputContainer",            m_inCollKey,     "Input container name");
+  declareProperty("OutputContainer",           m_outCollKey,
+                  "The name of the output container with the deep copy of selected xAOD::IParticles");
+  declareProperty("WriteSplitOutputContainer", m_writeSplitAux,
+                  "Decide if we want to write a fully-split AuxContainer such that we can remove any variables");
+  declareProperty("OutputContainerOwnershipPolicy", m_outOwnPolicyName,
+                  "Defines the ownership policy of the output container (default: 'OWN_ELEMENTS'; also allowed: 'VIEW_ELEMENTS')");
+
+  declareProperty("SelectionToolList",       m_selTools,     "The list of IAsgSelectionTools");
+  declareProperty("SelectionWithPVToolList", m_selWVtxTools, "The list of IAsgSelectionWithVertexTools");
+  declareProperty("Selection",               m_selection,
+                  "The selection string that defines which xAOD::IParticles to select from the container");
+
+  declareProperty("DoCutBookkeeping",       m_doCutFlow,
+                  "If true (deault: false), do the bookkeeping of how many particles passed which selection cuts");
+  declareProperty("CutBookkeeperContainer", m_cutBKCName,
+                  "The name of the resulting xAOD::CutBookkeeperContainer");
 }
 
 
@@ -96,75 +126,44 @@ StatusCode ParticleSelectionAlg::initialize()
   ATH_MSG_DEBUG ("Initializing " << name() << "...");
 
   // Print out the used configuration
-  ATH_MSG_DEBUG ( " using = " << m_jos );
-  ATH_MSG_DEBUG ( " using = " << m_tool );
   ATH_MSG_DEBUG ( " using = " << m_inCollKey );
   ATH_MSG_DEBUG ( " using = " << m_outCollKey );
-  ATH_MSG_DEBUG ( " using = " << m_outCollType );
   ATH_MSG_DEBUG ( " using = " << m_writeSplitAux );
   ATH_MSG_DEBUG ( " using = " << m_outOwnPolicyName );
-  ATH_MSG_DEBUG ( " using = " << m_outLinkCollKey );
   ATH_MSG_DEBUG ( " using = " << m_selection );
+  ATH_MSG_DEBUG ( " using DoCutBookkeeping = " << m_doCutFlow );
+  ATH_MSG_DEBUG ( " using = " << m_cutBKCName );
+
+  // initialize proxy loaders for expression parsing
+  if ( !(m_selection.value().empty()) ){
+    ExpressionParsing::MultipleProxyLoader *proxyLoaders = new ExpressionParsing::MultipleProxyLoader();
+    // proxyLoaders->push_back(new ExpressionParsing::TriggerDecisionProxyLoader(m_trigDecisionTool));
+    proxyLoaders->push_back(new ExpressionParsing::SGxAODProxyLoader(evtStore()));
+    // load the expressions
+    m_parser = new ExpressionParsing::ExpressionParser(proxyLoaders);
+    m_parser->loadExpression( m_selection.value() );
+  }
 
+  // initialize the counters
+  m_nEventsProcessed = 0;
 
-  // Initialize the counters to zero
-  m_nEventsProcessed = 0 ;
-
-
-  // Get the JobOptionService
-  // We will use this to set the properties of our private skimming tool
-  // from the properties of this algorithm.
-  ATH_MSG_VERBOSE( "Getting the JobOptionService");
-  ATH_CHECK( m_jos.retrieve() );
-
-  // Get the full name of the private skimTool
-  ATH_MSG_VERBOSE( "Getting the full name of the tool");
-  const std::string& fullToolName = this->name() + "." + m_tool.name();
-  ATH_MSG_DEBUG( "Got the full name of the tool: " << fullToolName );
-
-  // Now, set all properties of the private skimTool that were acutally configured
-  if (m_setInCollKey) {
-    ATH_MSG_DEBUG( "Setting property" << m_inCollKey
-                   << " of private tool with name: '" << fullToolName << "'" );
-    ATH_CHECK( m_jos->addPropertyToCatalogue (fullToolName,m_inCollKey) );
+  // Determine the ownership policy of the output container
+  if ( m_outOwnPolicyName.value() == "OWN_ELEMENTS" ) {
+    m_outOwnPolicy = SG::OWN_ELEMENTS;
   }
-  if (m_setOutCollKey) {
-    ATH_MSG_DEBUG( "Setting property" << m_outCollKey
-                   << " of private tool with name: '" << fullToolName << "'" );
-    ATH_CHECK( m_jos->addPropertyToCatalogue (fullToolName,m_outCollKey) );
+  else if ( m_outOwnPolicyName.value() == "VIEW_ELEMENTS" ) {
+    m_outOwnPolicy = SG::VIEW_ELEMENTS;
   }
-  if (m_setOutCollType) {
-    ATH_MSG_DEBUG( "Setting property" << m_outCollType
-                   << " of private tool with name: '" << fullToolName << "'" );
-    ATH_CHECK( m_jos->addPropertyToCatalogue (fullToolName,m_outCollType) );
+  else {
+    ATH_MSG_ERROR("Unrecognized ownership policy for the output container: " << m_outOwnPolicyName );
+    return StatusCode::FAILURE;
   }
-  if (m_setWriteSplitAux) {
-    ATH_MSG_DEBUG( "Setting property" << m_writeSplitAux
-                   << " of private tool with name: '" << fullToolName << "'" );
-    ATH_CHECK( m_jos->addPropertyToCatalogue (fullToolName,m_writeSplitAux) );
-  }
-  if (m_setOwnPolicy) {
-    ATH_MSG_DEBUG( "Setting property" << m_outOwnPolicyName
-                   << " of private tool with name: '" << fullToolName << "'" );
-    ATH_CHECK( m_jos->addPropertyToCatalogue (fullToolName,m_outOwnPolicyName) );
-  }
-  if (m_setOutLinkCollKey) {
-    ATH_MSG_DEBUG( "Setting property" << m_outLinkCollKey
-                   << " of private tool with name: '" << fullToolName << "'" );
-    ATH_CHECK( m_jos->addPropertyToCatalogue (fullToolName,m_outLinkCollKey) );
-  }
-  if (m_setSelection) {
-    ATH_MSG_DEBUG( "Setting property" << m_selection
-                   << " of private tool with name: '" << fullToolName << "'" );
-    ATH_CHECK( m_jos->addPropertyToCatalogue (fullToolName,m_selection) );
-  }
-  ATH_MSG_DEBUG( "Done setting properties of the tool");
 
-  // Get the skimming tool
-  ATH_CHECK( m_tool.retrieve() );
+  // Retrieve all tools
+  ATH_CHECK( m_selTools.retrieve() );
+  ATH_CHECK( m_selWVtxTools.retrieve() );
 
   ATH_MSG_DEBUG ( "==> done with initialize " << name() << "..." );
-
   return StatusCode::SUCCESS;
 }
 
@@ -175,24 +174,230 @@ StatusCode ParticleSelectionAlg::finalize()
   ATH_MSG_DEBUG ("Finalizing " << name() << "...");
 
   // Release all tools and services
-  ATH_CHECK( m_jos.release() );
-  ATH_CHECK( m_tool.release() );
+  ATH_CHECK( m_selTools.release() );
+  ATH_CHECK( m_selWVtxTools.release() );
+
+  // Clean up the memory
+  if (m_parser) {
+    delete m_parser;
+    m_parser = 0;
+  }
 
   return StatusCode::SUCCESS;
 }
 
 
 
+StatusCode ParticleSelectionAlg::beginRun()
+{
+  ATH_MSG_DEBUG ("BeginRun " << name() << "...");
+
+  // Nothing to be done here, if cut-flow bookkeeping was not requested
+  if (!m_doCutFlow){ return StatusCode::SUCCESS; }
+
+  // Get some properties from the input meta data
+  std::string inputStreamName = "Stream";
+  const CLID clid = ClassID_traits<EventStreamInfo>::ID();
+  std::vector<std::string> streamNameList;
+  inputMetaStore()->keys(clid, streamNameList);
+  if ( streamNameList.size() >=1 ){ inputStreamName = streamNameList[0]; }
+  // Get the processing cycle number that we need to set for us
+  int maxInputCycle = -1;
+  if ( inputMetaStore()->contains<xAOD::CutBookkeeperContainer>(m_cutBKCName.value()) ){
+    xAOD::CutBookkeeperContainer* inCutBKCont = nullptr;
+    ATH_CHECK( inputMetaStore()->retrieve(inCutBKCont, m_cutBKCName.value() ) );
+    if (inCutBKCont){
+      maxInputCycle = inCutBKCont->maxCycle();
+    }
+  }
+  if (maxInputCycle<0){ maxInputCycle = 0; }
+  else { maxInputCycle += 1; }
+
+  // Check if we already have a container in the output meta-data store
+  xAOD::CutBookkeeperContainer* cutBKCont = nullptr;
+  if ( outputMetaStore()->contains<xAOD::CutBookkeeperContainer>(m_cutBKCName.value()) ){
+    ATH_CHECK( inputMetaStore()->retrieve(cutBKCont, m_cutBKCName.value() ) );
+    // Set the index where we will start having our CutBookkeepers in this container
+    m_cutBKStartIdx = cutBKCont->size();
+  }
+  else {
+    // Create and register the container that will hold the cut-flow information
+    cutBKCont = new xAOD::CutBookkeeperContainer();
+    // Take care of the peculiarities of the new xAOD EDM, i.e., create the needed AuxStore
+    xAOD::CutBookkeeperAuxContainer* cutBKAuxCont = new xAOD::CutBookkeeperAuxContainer();
+    cutBKCont->setStore( cutBKAuxCont ); //gives it a new associated aux container
+    ATH_CHECK( outputMetaStore()->record( cutBKCont, m_cutBKCName.value() ) );
+    ATH_CHECK( outputMetaStore()->record( cutBKAuxCont, m_cutBKCName.value()+"Aux." ) );
+    ATH_MSG_VERBOSE( "Recorded xAOD::CutBookkeeperContainer " << m_cutBKCName.value() << "Aux." );
+  }
+
+  //------------- for the AsgSelectionTools --------------
+  // Now, register one CutBookkeeper per cut that will be applied.
+  // For each of the registered tools, get the TAccept and ask it for all known cuts.
+  for ( std::size_t toolIdx=0; toolIdx < m_selTools.size(); ++toolIdx ){
+    const auto& tool = m_selTools[toolIdx];
+    // Fill the index bookkeeping at what index in the CutBookkeeperContainer
+    // the CutBookkeepers for this tool start.
+    m_selToolIdxOffset.push_back( cutBKCont->size() );
+    // Get some needed quantities
+    const std::string toolName = tool->name();
+    const Root::TAccept& tAccept = tool->getTAccept();
+    const unsigned int nCuts = tAccept.getNCuts();
+    for ( unsigned int iCut=0; iCut<nCuts; ++iCut ){
+      // Get the name and description of this cut
+      const std::string cutName  = (tAccept.getCutName(iCut)).Data();
+      const std::string cutDescr = (tAccept.getCutDescription(iCut)).Data();
+      // Create a new xAOD::CutBookkeeper and add it to the container
+      xAOD::CutBookkeeper* cutBK = new xAOD::CutBookkeeper();
+      cutBKCont->push_back(cutBK);
+      // Now, set its properties
+      cutBK->setName(toolName+"_"+cutName);
+      cutBK->setDescription(cutDescr);
+      cutBK->setCutLogic(xAOD::CutBookkeeper::CutLogic::REQUIRE); // Each cut must be passed, thus REQUIRE, i.e, logical AND
+      cutBK->setInputStream(inputStreamName);
+      cutBK->setCycle(maxInputCycle);
+    }
+  }
+
+  //------------- for the AsgSelectionWithVertexTools --------------
+  // Now, register one CutBookkeeper per cut that will be applied.
+  // For each of the registered tools, get the TAccept and ask it for all known cuts.
+  for ( std::size_t toolIdx=0; toolIdx < m_selWVtxTools.size(); ++toolIdx ){
+    const auto& tool = m_selWVtxTools[toolIdx];
+    // Fill the index bookkeeping at what index in the CutBookkeeperContainer
+    // the CutBookkeepers for this tool start.
+    m_selWPVToolIdxOffset.push_back( cutBKCont->size() );
+    // Get some needed quantities
+    const std::string toolName = tool->name();
+    const Root::TAccept& tAccept = tool->getTAccept();
+    const unsigned int nCuts = tAccept.getNCuts();
+    for ( unsigned int iCut=0; iCut<nCuts; ++iCut ){
+      // Get the name and description of this cut
+      const std::string cutName  = (tAccept.getCutName(iCut)).Data();
+      const std::string cutDescr = (tAccept.getCutDescription(iCut)).Data();
+      // Create a new xAOD::CutBookkeeper and add it to the container
+      xAOD::CutBookkeeper* cutBK = new xAOD::CutBookkeeper();
+      cutBKCont->push_back(cutBK);
+      // Now, set its properties
+      cutBK->setName(toolName+"_"+cutName);
+      cutBK->setDescription(cutDescr);
+      cutBK->setCutLogic(xAOD::CutBookkeeper::CutLogic::REQUIRE); // Each cut must be passed, thus REQUIRE, i.e, logical AND
+      cutBK->setInputStream(inputStreamName);
+      cutBK->setCycle(maxInputCycle);
+    }
+  }
+
+  //------------- for the ExpressionParsing in this algorithm --------------
+  if ( !(m_selection.value().empty()) ){
+    // Create a new xAOD::CutBookkeeper and add it to the container
+    xAOD::CutBookkeeper* cutBK = new xAOD::CutBookkeeper();
+    cutBKCont->push_back(cutBK);
+    // Now, set its properties
+    cutBK->setName(this->name());
+    cutBK->setDescription(m_selection.value());
+    cutBK->setCutLogic(xAOD::CutBookkeeper::CutLogic::REQUIRE); // Each cut must be passed, thus REQUIRE, i.e, logical AND
+    cutBK->setInputStream(inputStreamName);
+    cutBK->setCycle(maxInputCycle);
+    m_idxSelParster = cutBK->index();
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+
+
+
 StatusCode ParticleSelectionAlg::execute()
 {
   // Increase the event counter
   ++m_nEventsProcessed;
-
   // Simple status message at the beginning of each event execute,
   ATH_MSG_DEBUG ( "==> execute " << name() << " on " << m_nEventsProcessed << ". event..." );
 
-  // Call the tool and record resulting containers into StoreGate
-  ATH_CHECK( m_tool->addBranches() );
+
+  // Figure out what type the input container has, if we didn't do it yet
+  if ( m_contType == UNKNOWN ){
+    if ( evtStore()->contains<xAOD::PhotonContainer>(m_inCollKey.value()) ){ m_contType = PHOTON; }
+    else if ( evtStore()->contains<xAOD::ElectronContainer>(m_inCollKey.value()) ){ m_contType = ELECTRON; }
+    else if ( evtStore()->contains<xAOD::MuonContainer>(m_inCollKey.value()) ){ m_contType = MUON; }
+    else if ( evtStore()->contains<xAOD::TauJetContainer>(m_inCollKey.value()) ){ m_contType = TAU; }
+    else if ( evtStore()->contains<xAOD::JetContainer>(m_inCollKey.value()) ){ m_contType = JET; }
+    else if ( evtStore()->contains<xAOD::TruthParticleContainer>(m_inCollKey.value()) ){ m_contType = TRUTHPARTICLE; }
+    else if ( evtStore()->contains<xAOD::CompositeParticleContainer>(m_inCollKey.value()) ){ m_contType = COMPOSITEPARTICLE; }
+    else if ( evtStore()->contains<xAOD::PFOContainer>(m_inCollKey.value()) ){ m_contType = PARITCLEFLOW; }
+    else if ( evtStore()->contains<xAOD::NeutralParticleContainer>(m_inCollKey.value()) ){ m_contType = NEUTRALPARTICLE; }
+    else if ( evtStore()->contains<xAOD::TrackParticleContainer>(m_inCollKey.value()) ){ m_contType = TRACKPARTICLE; }
+    else if ( evtStore()->contains<xAOD::ParticleContainer>(m_inCollKey.value()) ){ m_contType = PARTICLE; }
+    else if ( evtStore()->contains<xAOD::CaloClusterContainer>(m_inCollKey.value()) ){ m_contType = CALOCLUSTER; }
+  }
+  if ( m_contType == UNKNOWN ){
+    ATH_MSG_FATAL("We couldn't determine the type of the container... abort!");
+    return StatusCode::FAILURE;
+  }
+
+  // Get the input container and create the output containers
+  const xAOD::IParticleContainer* inContainer = nullptr;
+  ATH_CHECK( evtStore()->retrieve( inContainer, m_inCollKey.value() ) );
+  ATH_MSG_DEBUG ( "Input collection = " << m_inCollKey.value()
+                  << " retrieved from StoreGate which has " << inContainer->size() << " entries." );
+
+  // --------------------------------------------------------------------------
+  // Do the expression parsing once per event already here
+  // --------------------------------------------------------------------------
+  std::vector<int> resultVec;
+  resultVec.reserve(inContainer->size());
+  if ( !(m_selection.value().empty()) ){
+    resultVec = m_parser->evaluateAsVector();
+    // Check that the lengths of the input container and the result vector are the same
+    if ( inContainer && inContainer->size() != resultVec.size() ) {
+      ATH_MSG_ERROR("We got an input container, but its size (" << inContainer->size()
+                    << ") doesn't match the size of the result vector: " << resultVec.size() );
+      return StatusCode::FAILURE;
+    }
+    ATH_MSG_VERBOSE("Have a container of size " << inContainer->size()
+                    << " and a result vector of size " << resultVec.size() );
+  } // End: If expression parsing was requested in the first place
+
+
+  // --------------------------------------------------------------------------
+  // Do the heavy lifting of actually creating the new and reduced output container(s)
+  // --------------------------------------------------------------------------
+  if ( m_contType == PHOTON ){
+    ATH_CHECK( (this->selectParticles<xAOD::PhotonContainer,xAOD::PhotonAuxContainer>(inContainer,resultVec)) );
+  }
+  else if ( m_contType == ELECTRON ){
+    ATH_CHECK( (this->selectParticles<xAOD::ElectronContainer,xAOD::ElectronAuxContainer>(inContainer,resultVec)) );
+  }
+  else if ( m_contType == MUON ){
+    ATH_CHECK( (this->selectParticles<xAOD::MuonContainer,xAOD::MuonAuxContainer>(inContainer,resultVec)) );
+  }
+  else if ( m_contType == TAU ){
+    ATH_CHECK( (this->selectParticles<xAOD::TauJetContainer,xAOD::TauJetAuxContainer>(inContainer,resultVec)) );
+  }
+  else if ( m_contType == JET ){
+    ATH_CHECK( (this->selectParticles<xAOD::JetContainer,xAOD::JetAuxContainer>(inContainer,resultVec)) );
+  }
+  else if ( m_contType == TRUTHPARTICLE ){
+    ATH_CHECK( (this->selectParticles<xAOD::TruthParticleContainer,xAOD::TruthParticleAuxContainer>(inContainer,resultVec)) );
+  }
+  else if ( m_contType == COMPOSITEPARTICLE ){
+    ATH_CHECK( (this->selectParticles<xAOD::CompositeParticleContainer,xAOD::CompositeParticleAuxContainer>(inContainer,resultVec)) );
+  }
+  else if ( m_contType == PARITCLEFLOW ){
+    ATH_CHECK( (this->selectParticles<xAOD::PFOContainer,xAOD::PFOAuxContainer>(inContainer,resultVec)) );
+  }
+  else if ( m_contType == NEUTRALPARTICLE ){
+    ATH_CHECK( (this->selectParticles<xAOD::NeutralParticleContainer,xAOD::NeutralParticleAuxContainer>(inContainer,resultVec)) );
+  }
+  else if ( m_contType == TRACKPARTICLE ){
+    ATH_CHECK( (this->selectParticles<xAOD::TrackParticleContainer,xAOD::TrackParticleAuxContainer>(inContainer,resultVec)) );
+  }
+  else if ( m_contType == PARTICLE ){
+    ATH_CHECK( (this->selectParticles<xAOD::ParticleContainer,xAOD::ParticleAuxContainer>(inContainer,resultVec)) );
+  }
+  else if ( m_contType == CALOCLUSTER ){
+    ATH_CHECK( (this->selectParticles<xAOD::CaloClusterContainer,xAOD::CaloClusterAuxContainer>(inContainer,resultVec)) );
+  }
 
   return StatusCode::SUCCESS;
 }
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSelectionAlg.h b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSelectionAlg.h
index 84c0885f0b7..e332ae73b3c 100644
--- a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSelectionAlg.h
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSelectionAlg.h
@@ -13,23 +13,30 @@
 
 // STL includes
 #include <string>
+#include <vector>
 
 // FrameWork includes
 #include "GaudiKernel/ToolHandle.h"
-#include "GaudiKernel/ServiceHandle.h"
-#include "AthenaBaseComps/AthAlgorithm.h"
-
-
-// forward declarations
-class IJobOptionsSvc;
-namespace DerivationFramework {
-  class IAugmentationTool;
+// #include "GaudiKernel/ServiceHandle.h"
+// #include "AthenaBaseComps/AthAlgorithm.h"
+#include "AthAnalysisBaseComps/AthAnalysisAlgorithm.h"
+#include "xAODBase/IParticleContainer.h"
+//#include "TrigDecisionTool/TrigDecisionTool.h"
+#include "PATCore/IAsgSelectionTool.h"
+#include "PATCore/IAsgSelectionWithVertexTool.h"
+
+// // Forward declarations
+// namespace Trig{
+//   class TrigDecisionTool;
+// }
+// Forward declarations
+namespace ExpressionParsing {
+  class ExpressionParser;
 }
 
 
-
 class ParticleSelectionAlg
-  : public ::AthAlgorithm
+  : public ::AthAnalysisAlgorithm
 {
 
   ///////////////////////////////////////////////////////////////////
@@ -49,6 +56,10 @@ class ParticleSelectionAlg
   /// Athena algorithm's initalize hook
   virtual StatusCode  initialize();
 
+  /// Athena algorithm's beginRun hook
+  /// (called once before running over the events, after initialize)
+  virtual StatusCode  beginRun();
+
   /// Athena algorithm's execute hook
   virtual StatusCode  execute();
 
@@ -56,150 +67,114 @@ class ParticleSelectionAlg
   virtual StatusCode  finalize();
 
 
-private:
-  // The update handlers
-
-  /// This internal method will realize if a user sets the 'InputContainer' property
-  void setupInputContainer( Property& /*prop*/ );
-
-  /// This internal method will realize if a user sets the 'OutputContainer' property
-  void setupOutputContainer( Property& /*prop*/ );
-
-  /// This internal method will realize if a user sets the 'OutputContainerType' property
-  void setupOutputContainerType( Property& /*prop*/ );
-
-  /// This internal method will realize if a user sets the 'WriteSplitOutputContainer' property
-  void setupWriteSplitOutputContainer( Property& /*prop*/ );
-
-  /// This internal method will realize if a user sets the 'OutputContainerOwnershipPolicy' property
-  void setupOutputContainerOwnPolicy( Property& /*prop*/ );
-
-  /// This internal method will realize if a user sets the 'OutputLinkContainer' property
-  void setupOutputLinkContainer( Property& /*prop*/ );
-
-  /// This internal method will realize if a user sets the 'Selection' property
-  void setupSelection( Property& /*prop*/ );
+ private:
+  /// Private function to perform the actualy work
+  template<class CONT, class AUXCONT>
+  StatusCode selectParticles(const xAOD::IParticleContainer* inContainer,
+                             const std::vector<int>& resultVec) const;
 
 
   ///////////////////////////////////////////////////////////////////
   // Private data:
   ///////////////////////////////////////////////////////////////////
  private:
-  /// The job options service (will be used to forward this algs properties to
-  /// the private tool)
-  ServiceHandle<IJobOptionsSvc> m_jos;
+  /// The list of IAsgSelectionTools
+  ToolHandleArray<IAsgSelectionTool> m_selTools;
 
-  /// The ToolHandle to the SkimmingTool
-  ToolHandle<DerivationFramework::IAugmentationTool> m_tool;
+  /// The list of IAsgSelectionWithVertexTools
+  ToolHandleArray<IAsgSelectionWithVertexTool> m_selWVtxTools;
 
-  /// Input container name
-  StringProperty m_inCollKey;
+  /// Name of the EventInfo object
+  StringProperty m_evtInfoName;
 
-  /// This boolean is true if the user sets the 'InputContainer' property
-  bool m_setInCollKey;
+  /// Name of the PrimaryVertex container
+  StringProperty m_inPrimVtxCont;
 
+  /// Input container name
+  StringProperty m_inCollKey;
 
   /// Output collection name (deep copies of the original ones)
   StringProperty m_outCollKey;
 
-  /// This boolean is true if the user sets the 'OutputContainer' property
-  bool m_setOutCollKey;
-
-
-  /// The type of the output container, e.g., 'xAOD::JetContainer'
-  StringProperty m_outCollType;
-
-  /// This boolean is true if the user sets the 'OutputContainerType' property
-  bool m_setOutCollType;
-
-
   /// Decide if we want to write a fully-split AuxContainer such that we can remove any variables
   BooleanProperty m_writeSplitAux;
 
-  /// This boolean is true if the user sets the 'WriteSplitOutputContainer' property
-  bool m_setWriteSplitAux;
-
-
   /// Defines the ownership policy of the output container
-  /// (default: 'OWN_ELEMENTS'; also allowed: 'VIEW_ELEMENTS')"
+  /// (default: 'VIEW_ELEMENTS'; also allowed: 'OWN_ELEMENTS')".
+  /// TO see what this means, go here:
+  /// https://twiki.cern.ch/twiki/bin/view/AtlasComputing/SoftwareTutorialxAODAnalysisInAthena#Understanding_the_different_type
   StringProperty m_outOwnPolicyName;
 
-  /// This boolean is true if the user sets the 'OutputContainerOwnershipPolicy' property
-  bool m_setOwnPolicy;
-
-
-  /// Output link collection name (ElementLinks to selected IParticles)
-  StringProperty m_outLinkCollKey;
-
-  /// This boolean is true if the user sets the 'OutputLinkContainer' property
-  bool m_setOutLinkCollKey;
-
-
   /// The selection string that will select which xAOD::IParticles to keep from
   /// an xAOD::IParticleContainer
   StringProperty m_selection;
 
-  /// This boolean is true if the user sets the 'Selection' property
-  bool m_setSelection;
-
-
-
-  /// Internal event counter
-  unsigned long m_nEventsProcessed;
-
-
-};
-
-// I/O operators
-//////////////////////
+  /// If true (deault: false), do the bookkeeping of how many particles passed
+  /// which selection cuts
+  bool m_doCutFlow;
 
-///////////////////////////////////////////////////////////////////
-// Inline methods:
-///////////////////////////////////////////////////////////////////
+  /// The name of the resulting xAOD::CutBookkeeperContainer.
+  /// If an empty name is given (default), the name of the algorithm instance is used.
+  StringProperty m_cutBKCName;
 
-/// This internal method will realize if a user sets the 'InputContainer' property
-inline void ParticleSelectionAlg::setupInputContainer( Property& /*prop*/ ) {
-  m_setInCollKey = true;
-  return;
-}
 
-/// This internal method will realize if a user sets the 'OutputContainer' property
-inline void ParticleSelectionAlg::setupOutputContainer( Property& /*prop*/ ) {
-  m_setOutCollKey = true;
-  return;
-}
 
-/// This internal method will realize if a user sets the 'OutputContainerType' property
-inline void ParticleSelectionAlg::setupOutputContainerType( Property& /*prop*/ ) {
-  m_setOutCollType = true;
-  return;
-}
+  /// @name Internal members
+  /// @{
 
-/// This internal method will realize if a user sets the 'WriteSplitOutputContainer' property
-inline void ParticleSelectionAlg::setupWriteSplitOutputContainer( Property& /*prop*/ ) {
-  m_setWriteSplitAux = true;
-  return;
-}
+  /// The expression parser
+  ExpressionParsing::ExpressionParser *m_parser;
 
-/// This internal method will realize if a user sets the 'OutputContainerOwnPolicy' property
-inline void ParticleSelectionAlg::setupOutputContainerOwnPolicy( Property& /*prop*/ ) {
-  m_setOwnPolicy = true;
-  return;
-}
+  // /// The trigger decision tool
+  // ToolHandle<Trig::TrigDecisionTool> m_trigDecisionTool;
 
-/// This internal method will realize if a user sets the 'OutputLinkContainer' property
-inline void ParticleSelectionAlg::setupOutputLinkContainer( Property& /*prop*/ ) {
-  m_setOutLinkCollKey = true;
-  return;
-}
+  /// Internal event counter
+  unsigned long m_nEventsProcessed;
 
-/// This internal method will realize if a user sets the 'Selection' property
-inline void ParticleSelectionAlg::setupSelection( Property& /*prop*/ ) {
-  m_setSelection = true;
-  return;
-}
+  /// The internally used translation for the ownership policy
+  SG::OwnershipPolicy m_outOwnPolicy;
+
+  /// An enumaration for the actual container type
+  enum contType_t {
+    UNKNOWN,
+    PHOTON,
+    ELECTRON,
+    MUON,
+    TAU,
+    JET,
+    PARITCLEFLOW,
+    NEUTRALPARTICLE,
+    TRACKPARTICLE,
+    TRUTHPARTICLE,
+    COMPOSITEPARTICLE,
+    PARTICLE,
+    CALOCLUSTER
+  };
+
+  /// The variable that holds the value that we find for the input container
+  contType_t m_contType;
+
+  /// The starting index of where in the CutBookkeeperContainer our new CutBookkeepers start
+  std::size_t m_cutBKStartIdx;
+
+  /// The list of pairs of the tool index of the AsgSelectionTools and the
+  /// starting index of the corresponding CutBookKeeper inside the CutBookkeeperContainer.
+  std::vector<std::size_t> m_selToolIdxOffset;
+
+  /// The list of pairs of the tool index of the AsgSelectionWithVertexTools and the
+  /// starting index of the corresponding CutBookKeeper inside the CutBookkeeperContainer.
+  std::vector<std::size_t> m_selWPVToolIdxOffset;
+
+  /// Store the index of the CutBookKeeper in the CutBookkeeperContainer for the
+  /// selection using the ExpressionParser
+  std::size_t m_idxSelParster;
+
+  /// @}
 
+};
 
+// Include the templated code here. This must be done from this header file.
+#include "ParticleSelectionAlg.icc"
 
 
 #endif //> !EVENTUTILS_PARTICLESELECTIONALG_H
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSelectionAlg.icc b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSelectionAlg.icc
new file mode 100644
index 00000000000..7e88f764b4e
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSelectionAlg.icc
@@ -0,0 +1,188 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include "xAODBase/IParticle.h"
+#include "xAODCore/AuxContainerBase.h"
+#include "AthContainers/ConstDataVector.h"
+#include "xAODEventInfo/EventInfo.h"
+#include "xAODTracking/VertexContainer.h"
+#include "xAODTracking/Vertex.h"
+#include "xAODCutFlow/CutBookkeeperContainer.h"
+#include "PATCore/TAccept.h"
+
+
+
+template<class CONT, class AUXCONT>
+StatusCode ParticleSelectionAlg::selectParticles(const xAOD::IParticleContainer* inContainer,
+                                                 const std::vector<int>& resultVec) const
+{
+  ATH_MSG_DEBUG ("selectParticlesStepTwo<CONT,AUXCONT>(...) " << name() << "...");
+
+  // Get the type of particle that the current container CONT has
+  typedef typename CONT::base_value_type PART;
+
+  // Create a new output container and its associated auxiliary container
+  CONT* outCont = nullptr;
+  ConstDataVector<CONT>* outContConst = nullptr;
+
+  if ( m_outOwnPolicy == SG::OWN_ELEMENTS ) {
+    outCont = new CONT( m_outOwnPolicy );
+    ATH_CHECK( evtStore()->record ( outCont, m_outCollKey.value() ) );
+    if ( m_writeSplitAux.value() ) {
+      xAOD::AuxContainerBase* outAuxContainer = new xAOD::AuxContainerBase();
+      ATH_CHECK( evtStore()->record( outAuxContainer, m_outCollKey.value() + "Aux." ) );
+      outCont->setStore( outAuxContainer );
+      ATH_MSG_VERBOSE("Recorded xAOD::AuxContainerBase for container: " << m_outCollKey.value() );
+    }
+    else {
+      AUXCONT* outAuxContainer = new AUXCONT();
+      ATH_CHECK( evtStore()->record( outAuxContainer, m_outCollKey.value() + "Aux." ) );
+      outCont->setStore( outAuxContainer );
+      ATH_MSG_VERBOSE("Recorded AuxContainer for container: " << m_outCollKey.value() );
+    }
+  }
+  else {
+    outContConst = new ConstDataVector<CONT>( m_outOwnPolicy );
+    ATH_CHECK( evtStore()->record ( outContConst, m_outCollKey.value() ) );
+    ATH_MSG_VERBOSE("Recorded ConstDataVector for container: " << m_outCollKey.value() );
+  }
+  // ATH_MSG_VERBOSE("StoreGate dump: " << evtStore()->dump() );
+
+  // Get the CutBookkeeperContainer, if cut-flow bookkeeping was requested
+  double eventWeight = 1.0;
+  xAOD::CutBookkeeperContainer* cutBKCont = nullptr;
+  const xAOD::EventInfo* evtInfo = nullptr;
+  if (m_doCutFlow){
+    ATH_CHECK( outputMetaStore()->retrieve(cutBKCont, m_cutBKCName.value() ) );
+    // Also, get the event info as we need to get the MC-weight for this event
+    ATH_CHECK( evtStore()->retrieve( evtInfo, m_evtInfoName.value() ));
+    const bool isSim = evtInfo->eventType(xAOD::EventInfo::EventType::IS_SIMULATION);
+    if (isSim){
+      eventWeight = static_cast<double>( evtInfo->mcEventWeight() );
+      ATH_MSG_VERBOSE("Got MC event weight of " << eventWeight );
+    }
+  }
+
+
+  // Now, loop over the input container and check which particles to write out
+  ATH_MSG_DEBUG("Input container has size " << inContainer->size() );
+  for ( std::size_t i=0; i<inContainer->size(); ++i ) {
+    const xAOD::IParticle* partBase = inContainer->at(i);
+    const PART* part = static_cast<const PART*>(partBase);
+
+    // ================================
+    // Apply the selection tools
+    // ================================
+    // The default object pass value. As soon as one cut is not passed, then
+    // the remainder of the cuts will not even be tried
+    bool passEverything = true;
+
+    //------------- for the AsgSelectionTools --------------
+    // Loop over all selection tools
+    ATH_MSG_VERBOSE("Loop over all selection tools");
+    for ( std::size_t toolIdx=0; toolIdx < m_selTools.size(); ++toolIdx ){
+      if (passEverything){
+        ATH_MSG_VERBOSE("Now going to try AsgSelectionTools number " << toolIdx );
+        const Root::TAccept& tAccept = m_selTools[toolIdx]->accept(part);
+        if (!m_doCutFlow){ passEverything &= static_cast<bool>(tAccept); }
+        else {
+          const std::size_t cbkStartIdx = m_selToolIdxOffset[toolIdx];
+          const unsigned int nCuts = tAccept.getNCuts();
+          for ( unsigned int iCut=0; iCut<nCuts; ++iCut ){
+            passEverything &= tAccept.getCutResult(iCut);
+            if (passEverything){
+              const std::size_t currentCBKIdx = cbkStartIdx + iCut;
+              xAOD::CutBookkeeper* cutBK = cutBKCont->at(currentCBKIdx);
+              cutBK->addNAcceptedEvents(1);
+              cutBK->addSumOfEventWeights(eventWeight);
+              cutBK->addSumOfEventWeightsSquared(eventWeight*eventWeight);
+            }
+          }
+        } // Done doing detailed particle cut-flow for this tool
+        ATH_MSG_VERBOSE("AsgSelectionTools number " << toolIdx << " passed/failed: " << passEverything );
+      }
+    }
+
+    //------------- for the AsgSelectionWithVertexTools --------------
+    // If we have at least one, we have to get the primary vertex
+    if ( m_selWVtxTools.size() ){
+      // Get the primary vertex container
+      const xAOD::VertexContainer* primVtxCont = nullptr;
+      ATH_CHECK( evtStore()->retrieve( primVtxCont, m_inPrimVtxCont.value() ) );
+      const xAOD::Vertex* primVtx = nullptr;
+      for ( const xAOD::Vertex* vtx  :  *primVtxCont ) {
+        // Get THE primary vertex
+        if ( vtx->vertexType() == xAOD::VxType::PriVtx ) {
+          primVtx = vtx;
+          break;
+        }
+      }
+      if ( !primVtx ) {
+        ATH_MSG_WARNING("Couldn't find a primary vertex in this event!");
+      }
+      // Now, we go ahead and loop over the tools
+      ATH_MSG_VERBOSE("Loop over all selection with vertex tools: " << passEverything);
+      for ( std::size_t toolIdx=0; toolIdx < m_selWVtxTools.size(); ++toolIdx ){
+        if (passEverything){
+          ATH_MSG_VERBOSE("Now going to try AsgSelectionWithVertexTools number " << toolIdx );
+          const Root::TAccept& tAccept = m_selWVtxTools[toolIdx]->accept(part,primVtx);
+          if (!m_doCutFlow){ passEverything &= static_cast<bool>(tAccept); }
+          else {
+            const std::size_t cbkStartIdx = m_selWPVToolIdxOffset[toolIdx];
+            const unsigned int nCuts = tAccept.getNCuts();
+            for ( unsigned int iCut=0; iCut<nCuts; ++iCut ){
+              passEverything &= tAccept.getCutResult(iCut);
+              if (passEverything){
+                const std::size_t currentCBKIdx = cbkStartIdx + iCut;
+                xAOD::CutBookkeeper* cutBK = cutBKCont->at(currentCBKIdx);
+                cutBK->addNAcceptedEvents(1);
+                cutBK->addSumOfEventWeights(eventWeight);
+                cutBK->addSumOfEventWeightsSquared(eventWeight*eventWeight);
+              }
+            }
+          } // Done doing detailed particle cut-flow for this tool
+          ATH_MSG_VERBOSE("AsgSelectionWithVertexTools number " << toolIdx << " passed/failed: " << passEverything );
+        }
+      }// Done looping over the selection tools
+    } // End: if ( m_selWVtxTools.size() ){
+
+    //------------- for the ExpressionParsing in this algorithm --------------
+    ATH_MSG_VERBOSE("Looking at expression parser result: " << passEverything);
+    if ( passEverything && !(resultVec.empty()) ){
+      // If this particle is not accepted by the expression parser, go to the next one
+      ATH_MSG_VERBOSE("Now going to try expression '" << m_selection.value() << "'" );
+      passEverything &= static_cast<bool>(resultVec.at(i));
+      ATH_MSG_VERBOSE("Expression '" << m_selection.value() << "' passed/failed: " << passEverything
+                      << ", particle index=" << part->index() <<", pt=" << 0.001*(part->pt()) << " GeV, eta="
+                      << part->eta() << ", phi=" << part->phi() );
+      if (passEverything && m_doCutFlow){
+        xAOD::CutBookkeeper* cutBK = cutBKCont->at(m_idxSelParster);
+        cutBK->addNAcceptedEvents(1);
+        cutBK->addSumOfEventWeights(eventWeight);
+        cutBK->addSumOfEventWeightsSquared(eventWeight*eventWeight);
+      }
+    }
+
+    // Now, if all cuts are passed, write out the current particle to the
+    // output container
+    if (passEverything){
+      ATH_MSG_VERBOSE("Going to fill output container with particle with pt=" << 0.001*(part->pt())
+                      << " GeV, eta=" << part->eta() );
+      if ( m_outOwnPolicy == SG::OWN_ELEMENTS ) {
+        PART* newPart = new PART();
+        outCont->push_back(newPart);
+        *newPart = *part;
+      }
+      else {
+        outContConst->push_back(part);
+      }
+    }
+
+  } // End: Loop over input particles
+
+  return StatusCode::SUCCESS;
+}
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSelectionTool.cxx b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSelectionTool.cxx
index e50264e3906..117a4d9c4cb 100644
--- a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSelectionTool.cxx
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSelectionTool.cxx
@@ -89,6 +89,7 @@ ParticleSelectionTool::ParticleSelectionTool( const std::string& type,
   m_outCollKey(""),
   m_outCollType(""),
   m_writeSplitAux(false),
+  m_outOwnPolicy(SG::VIEW_ELEMENTS),
   m_outLinkCollKey(""),
   m_selection(""),
   m_contID(0),
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSelectionTool.h b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSelectionTool.h
index 8ed3441cf40..38ef486aa79 100644
--- a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSelectionTool.h
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSelectionTool.h
@@ -54,10 +54,10 @@ public:
   virtual ~ParticleSelectionTool();
 
   /// Athena algtool's initialize
-  virtual StatusCode  initialize();
+  virtual StatusCode  initialize() override;
 
   /// Athena algtool's finalize
-  virtual StatusCode  finalize();
+  virtual StatusCode  finalize() override;
 
 
   /// Implement the method from the ISkimmingTool interface
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingTool.cxx b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingTool.cxx
index f966284daa0..66e180f0977 100644
--- a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingTool.cxx
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingTool.cxx
@@ -34,6 +34,7 @@
 #include "xAODParticleEvent/CompositeParticleContainer.h"
 #include "xAODParticleEvent/ParticleContainer.h"
 #include "xAODCaloEvent/CaloClusterContainer.h"
+#include "AthContainers/ConstDataVector.h"
 
 
 
@@ -101,7 +102,7 @@ StatusCode ParticleSortingTool::initialize()
     m_sortID = 7;
   }
   if ( m_sortDescending.value() ) { m_sortID *= -1; }
-  
+
   return StatusCode::SUCCESS;
 }
 
@@ -130,6 +131,20 @@ else if ( evtStore()->contains<CONTAINERTYPE>( m_inCollKey.value() ) ) {
 }
 
 
+// Declare a short pre-processor macro to deal with the different container types
+#define OVERWRITE_AND_SORT_CONTAINER( CONTAINERTYPE )                                                \
+else if ( evtStore()->contains<CONTAINERTYPE>( m_inCollKey.value() ) ) {                             \
+  ATH_MSG_DEBUG("Trying to copy, sort, and overwrite container of type "#CONTAINERTYPE );            \
+  const CONTAINERTYPE* inCont;                                                                       \
+  ATH_CHECK( evtStore()->retrieve( inCont, m_inCollKey.value() ) );                                  \
+  ConstDataVector<CONTAINERTYPE>* outCont = new ConstDataVector<CONTAINERTYPE>( SG::VIEW_ELEMENTS ); \
+  for ( const CONTAINERTYPE::base_value_type* inPart : *inCont ){                                    \
+    outCont->push_back(inPart);                                                                      \
+  }                                                                                                  \
+  ATH_CHECK( evtStore()->overwrite( outCont, m_inCollKey.value() ) );                                \
+  ATH_CHECK( this->doSortConst<CONTAINERTYPE>(outCont) );                                            \
+}
+
 
 
 StatusCode ParticleSortingTool::addBranches() const
@@ -145,7 +160,31 @@ StatusCode ParticleSortingTool::addBranches() const
     ATH_MSG_DEBUG("Got an empty 'OutputCollection' property. "
                   << "Trying to retrieve a non-const version of the 'InputContainer'...");
     xAOD::IParticleContainer* inCont = evtStore()->tryRetrieve<xAOD::IParticleContainer>( m_inCollKey.value() );
-    ATH_CHECK( this->doSort(inCont) );
+    if (inCont){ ATH_CHECK( this->doSort(inCont) ); }
+    else {
+      ATH_MSG_DEBUG("We couldn't retrieve a non-const version of the input container... try const.");
+      const xAOD::IParticleContainer* inCont2 = nullptr;
+      ATH_CHECK( evtStore()->retrieve( inCont2, m_inCollKey.value()) );
+      // Now, do the copy and sorting and overwriting of all known container types
+      if (false) {
+      }
+      OVERWRITE_AND_SORT_CONTAINER(xAOD::MuonContainer)
+      OVERWRITE_AND_SORT_CONTAINER(xAOD::ElectronContainer)
+      OVERWRITE_AND_SORT_CONTAINER(xAOD::PhotonContainer)
+      OVERWRITE_AND_SORT_CONTAINER(xAOD::TauJetContainer)
+      OVERWRITE_AND_SORT_CONTAINER(xAOD::JetContainer)
+      OVERWRITE_AND_SORT_CONTAINER(xAOD::PFOContainer)
+      OVERWRITE_AND_SORT_CONTAINER(xAOD::NeutralParticleContainer)
+      OVERWRITE_AND_SORT_CONTAINER(xAOD::TrackParticleContainer)
+      OVERWRITE_AND_SORT_CONTAINER(xAOD::TruthParticleContainer)
+      OVERWRITE_AND_SORT_CONTAINER(xAOD::CompositeParticleContainer)
+      OVERWRITE_AND_SORT_CONTAINER(xAOD::ParticleContainer)
+      OVERWRITE_AND_SORT_CONTAINER(xAOD::CaloClusterContainer)
+      else {
+        ATH_MSG_ERROR("Couln't find the provided intput container in store gate for later overwriting");
+        return StatusCode::FAILURE;
+      }
+    }
   }
   else {
     ATH_MSG_DEBUG("Got a non-empty 'OutputCollection' property. "
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingTool.h b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingTool.h
index 5101324aefa..8700fabf0ce 100644
--- a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingTool.h
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/ParticleSortingTool.h
@@ -23,6 +23,7 @@
 // EDM inlcudes
 #include "xAODBase/IParticle.h"
 #include "xAODBase/IParticleContainer.h"
+#include "AthContainers/ConstDataVector.h"
 
 
 
@@ -47,10 +48,10 @@ public:
   virtual ~ParticleSortingTool();
 
   /// Athena algtool's initialize
-  virtual StatusCode  initialize();
+  virtual StatusCode  initialize() override;
 
   /// Athena algtool's finalize
-  virtual StatusCode  finalize();
+  virtual StatusCode  finalize() override;
 
 
   /// Implement the method from the ISkimmingTool interface
@@ -64,6 +65,10 @@ private:
   /// Helper method that implements the call to the right sort function
   StatusCode doSort( xAOD::IParticleContainer* cont ) const;
 
+  /// Helper method to sort a ConstDataVector
+  template<class CONTAINERTYPE>
+  StatusCode doSortConst( ConstDataVector<CONTAINERTYPE>* cont ) const;
+
   /// The method to compare the particle's pt
   bool comparePt( const xAOD::IParticle* partA, const xAOD::IParticle* partB ) const;
 
@@ -125,4 +130,55 @@ inline bool ParticleSortingTool::compareDouble( double a, double b ) const
   else { return CxxUtils::fpcompare::less(a,b); }
 }
 
+
+template<class CONTAINERTYPE>
+StatusCode ParticleSortingTool::doSortConst( ConstDataVector<CONTAINERTYPE>* cont ) const
+{
+  if ( !cont ) {
+    ATH_MSG_ERROR("No ConstDataVector to be sorted");
+    return StatusCode::FAILURE;
+  }
+  // Actually do the sorting, using a C++11 lambda function construct
+  // to be able to use the member function here
+  if ( abs(m_sortID) == 1 ) {
+    cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) {
+                  return this->comparePt(a,b);
+                } );
+  }
+  else if ( abs(m_sortID) == 2 ) {
+    cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) {
+                  return this->compareEta(a,b);
+                } );
+  }
+  else if ( abs(m_sortID) == 3 ) {
+    cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) {
+                  return this->comparePhi(a,b);
+                } );
+  }
+  else if ( abs(m_sortID) == 4 ) {
+    cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) {
+                  return this->compareMass(a,b);
+                } );
+  }
+  else if ( abs(m_sortID) == 5 ) {
+    cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) {
+                  return this->compareEnergy(a,b);
+                } );
+  }
+  else if ( abs(m_sortID) == 6 ) {
+    cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) {
+                  return this->compareRapidity(a,b);
+                } );
+  }
+  else if ( abs(m_sortID) == 7 ) {
+    cont->sort( [this](const xAOD::IParticle* a, const xAOD::IParticle* b) {
+                  return this->compareAuxData(a,b);
+                } );
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+
+
 #endif //> !EVENTUTILS_PARTICLESORTINGTOOL_H
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/TriggerSelectionAlg.cxx b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/TriggerSelectionAlg.cxx
new file mode 100644
index 00000000000..e5ad7aca704
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/TriggerSelectionAlg.cxx
@@ -0,0 +1,130 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//  includes
+#include "TriggerSelectionAlg.h"
+
+// Tool includes
+#include "TrigDecisionTool/TrigDecisionTool.h"
+#include "xAODEventInfo/EventInfo.h"
+
+
+TriggerSelectionAlg::TriggerSelectionAlg( const std::string& name, ISvcLocator* pSvcLocator ):
+  AthFilterAlgorithm( name, pSvcLocator ),
+  m_trigDecisionTool("Trig::TrigDecisionTool/TrigDecisionTool"),
+  m_triggerList(),
+  m_decoEvtInfo(true),
+  m_evtInfoName("EventInfo"),
+  m_varPrefix("pass_"),
+  m_storePrescaleInfo(false),
+  m_varNameList()
+{
+  declareProperty("TrigDecisionTool",  m_trigDecisionTool, "The TrigDecisionTool" );
+  declareProperty("TriggerList",       m_triggerList, "The list of triggers to cut on" );
+  declareProperty("DecorateEventInfo", m_decoEvtInfo,
+                  "Decide if we also want to decorate the xAOD::EventInfo object with the pass/fail information" );
+  declareProperty("EventInfoName",     m_evtInfoName, "Name of the xAOD::EventInfo object that we want to decorate" );
+  declareProperty("VarNamePrefix",     m_varPrefix, "Prefix used for the decoration variables" );
+  declareProperty("StorePrescaleInfo", m_storePrescaleInfo,
+                  "Decide if we also want to decorate the xAOD::EventInfo object with the full-chain prescale information" );
+}
+
+
+TriggerSelectionAlg::~TriggerSelectionAlg() {}
+
+
+StatusCode TriggerSelectionAlg::initialize()
+{
+  ATH_MSG_DEBUG ("Initializing " << name() << "...");
+
+  // Print the configuration to the log file
+  ATH_MSG_DEBUG( "Using: " << m_trigDecisionTool );
+  ATH_MSG_DEBUG( "Using: " << m_triggerList );
+  ATH_MSG_DEBUG( "Using: " << m_decoEvtInfo );
+  ATH_MSG_DEBUG( "Using: " << m_evtInfoName );
+  ATH_MSG_DEBUG( "Using: " << m_varPrefix );
+  ATH_MSG_DEBUG( "Using: " << m_storePrescaleInfo );
+
+  // Retrieve the TrigDecisionTool
+  ATH_CHECK(m_trigDecisionTool.retrieve());
+
+  // Create the list of decoration variables
+  for ( const std::string& trigName : m_triggerList.value() ){
+    m_varNameList.push_back( m_varPrefix.value() + trigName );
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+
+StatusCode TriggerSelectionAlg::finalize()
+{
+  ATH_MSG_DEBUG("Finalizing " << name() << "...");
+
+  // Release all tools
+  ATH_CHECK( m_trigDecisionTool.release() );
+
+  return StatusCode::SUCCESS;
+}
+
+
+StatusCode TriggerSelectionAlg::execute()
+{
+  ATH_MSG_DEBUG("Executing " << name() << "...");
+
+  // Get the xAOD::EventInfo object, if requested
+  const xAOD::EventInfo* evtInfo = nullptr;
+  if ( m_decoEvtInfo.value() ){
+    ATH_CHECK( evtStore()->retrieve( evtInfo, m_evtInfoName.value() ) );
+  }
+
+  // Create a results Vector
+  std::vector<bool> trigResultsVec( m_triggerList.value().size(), false );
+  std::vector<float> trigPrescalesVec( m_triggerList.value().size(), 0. );
+
+  //Check if event passes trigger selection
+  bool eventPasses = false;
+  if( !(m_triggerList.value().empty()) ) {
+    for( std::size_t i=0; i<m_triggerList.value().size(); ++i ) {
+      if( m_trigDecisionTool->isPassed(m_triggerList.value().at(i)) ) {
+        trigResultsVec[i] = true;
+        eventPasses = true;
+        ATH_MSG_VERBOSE("Name of passed trigger: " << m_triggerList.value().at(i));
+        if ( !(m_decoEvtInfo.value()) ){
+          break; // Found a trigger which we passed, nothing more to do here
+        }
+      }
+      //We sometimes want to keep track of the chain prescale
+      if (m_storePrescaleInfo) {
+	trigPrescalesVec[i] = m_trigDecisionTool->getPrescale(m_triggerList.value().at(i));
+        ATH_MSG_VERBOSE("Retrieved prescale of " << trigPrescalesVec[i] << " for trigger: " << m_triggerList.value().at(i));
+      }
+    }
+  }
+
+  // Decorate the EventInfo, if requested
+  if ( m_decoEvtInfo.value() ){
+    const size_t decoSize = trigResultsVec.size();
+    if ( decoSize != m_varNameList.size() ){
+      ATH_MSG_FATAL("Different number of trigger results and variable names");
+      return StatusCode::FAILURE;
+    }
+    // We also want to decorate the xAOD::EventInfo object with the results
+    for( std::size_t i=0; i<decoSize; ++i ) {
+      SG::AuxElement::Decorator<char> decoPassTrig(m_varNameList[i]);
+      decoPassTrig(*evtInfo) = static_cast<char>(trigResultsVec[i]);
+      //We sometimes want to keep track of the chain prescale
+      if (m_storePrescaleInfo) {
+	SG::AuxElement::Decorator<float> decoPrescaleTrig("prescale_"+m_triggerList.value().at(i));
+	decoPrescaleTrig(*evtInfo) = static_cast<float>(trigPrescalesVec[i]);
+      }
+    }
+  }
+
+  // Say if this event should be accepted or not
+  this->setFilterPassed( eventPasses );
+  ATH_MSG_DEBUG("Event passes trigger selection: " << eventPasses );
+
+  return StatusCode::SUCCESS;
+}
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/TriggerSelectionAlg.h b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/TriggerSelectionAlg.h
new file mode 100644
index 00000000000..7154df7e760
--- /dev/null
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/TriggerSelectionAlg.h
@@ -0,0 +1,85 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef EVENTUTILS_TRIGGERSELECTIONALG_H
+#define EVENTUTILS_TRIGGERSELECTIONALG_H 1
+
+// STL includes
+#include <string>
+
+// FrameWork includes
+#include "AthenaBaseComps/AthFilterAlgorithm.h"
+#include "GaudiKernel/ToolHandle.h"
+
+// EDM includes
+#include "AthContainers/AuxElement.h"
+
+// Forward declarations
+namespace Trig{
+  class TrigDecisionTool;
+}
+
+
+class TriggerSelectionAlg
+  : public ::AthFilterAlgorithm
+{
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+  public:
+
+    /// Constructor with parameters:
+    TriggerSelectionAlg( const std::string& name, ISvcLocator* pSvcLocator );
+
+    /// Destructor:
+    virtual ~TriggerSelectionAlg();
+
+    /// Athena algorithm's initalize hook
+    virtual StatusCode  initialize();
+
+    /// Athena algorithm's execute hook
+    virtual StatusCode  execute();
+
+    /// Athena algorithm's finalize hook
+    virtual StatusCode  finalize();
+
+
+  private:
+
+    /// @name The properties that can be defined via the python job options
+    /// @{
+
+    /// The ToolHandle for the TrigDecisionTool
+    ToolHandle<Trig::TrigDecisionTool> m_trigDecisionTool;
+
+    /// The list of triggers to cut on
+    StringArrayProperty m_triggerList;
+
+    /// Decide if we also want to decorate the xAOD::EventInfo object with the pass/fail information
+    BooleanProperty m_decoEvtInfo;
+
+    /// Name of the xAOD::EventInfo object that we want to decorate
+    StringProperty m_evtInfoName;
+
+    /// Prefix used for the decoration variables
+    StringProperty m_varPrefix;
+
+    /// Decide if we also want to decorate the xAOD::EventInfo object with the (full-chain) prescale information
+    BooleanProperty m_storePrescaleInfo;
+
+    /// @}
+
+    /// @name Other private members
+    /// @{
+
+    /// The list of all variables names
+    std::vector<std::string> m_varNameList;
+
+    /// @}
+
+};
+
+
+
+#endif //> !EVENTUTILS_TRIGGERSELECTIONALG_H
diff --git a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/components/EventUtils_entries.cxx b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/components/EventUtils_entries.cxx
index aef3acf2942..9a2df65720a 100644
--- a/PhysicsAnalysis/AnalysisCommon/EventUtils/src/components/EventUtils_entries.cxx
+++ b/PhysicsAnalysis/AnalysisCommon/EventUtils/src/components/EventUtils_entries.cxx
@@ -11,7 +11,9 @@
 #include "../ParticleCombinerTool.h"
 #include "../ParticleCombinerAlg.h"
 #include "../EventQualityFilterAlg.h"
-//#include "../SkimDecisionRunPeriodAwareFilterAlg.h"
+#include "../ParticleRemoverAlg.h"
+#include "../TriggerSelectionAlg.h"
+#include "../EventDecisionAlg.h"
 
 DECLARE_TOOL_FACTORY( ParticleSortingTool )
 DECLARE_ALGORITHM_FACTORY( ParticleSortingAlg )
@@ -24,20 +26,6 @@ DECLARE_ALGORITHM_FACTORY( ParticleSelectionAlg )
 DECLARE_TOOL_FACTORY( ParticleCombinerTool )
 DECLARE_ALGORITHM_FACTORY( ParticleCombinerAlg )
 DECLARE_ALGORITHM_FACTORY( EventQualityFilterAlg )
-//DECLARE_ALGORITHM_FACTORY( SkimDecisionRunPeriodAwareFilterAlg )
-
-DECLARE_FACTORY_ENTRIES( EventUtils )
-{
-  DECLARE_TOOL( ParticleSortingTool );
-  DECLARE_ALGORITHM( ParticleSortingAlg );
-  DECLARE_TOOL( AddVarTool );
-  DECLARE_ALGORITHM( AddVarAlg );
-  DECLARE_TOOL( CutTool );
-  DECLARE_ALGORITHM( CutAlg );
-  DECLARE_TOOL( ParticleSelectionTool );
-  DECLARE_ALGORITHM( ParticleSelectionAlg );
-  DECLARE_TOOL( ParticleCombinerTool );
-  DECLARE_ALGORITHM( ParticleCombinerAlg );
-  DECLARE_ALGORITHM( EventQualityFilterAlg );
-  //DECLARE_ALGORITHM( SkimDecisionRunPeriodAwareFilterAlg );
-}
+DECLARE_ALGORITHM_FACTORY( ParticleRemoverAlg )
+DECLARE_ALGORITHM_FACTORY( TriggerSelectionAlg )
+DECLARE_ALGORITHM_FACTORY( EventDecisionAlg )
-- 
GitLab