diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/EgammaTrackParticleThinning.h b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/EgammaTrackParticleThinning.h
new file mode 100644
index 0000000000000000000000000000000000000000..a85ef6d633e5a4fa8d63030c7a8fdc18efe6996f
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/EgammaTrackParticleThinning.h
@@ -0,0 +1,55 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// EgammaTrackParticleThinning.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef DERIVATIONFRAMEWORK_EGAMMATRACKPARTICLETHINNING_H
+#define DERIVATIONFRAMEWORK_EGAMMATRACKPARTICLETHINNING_H
+
+#include <string>
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "DerivationFrameworkInterfaces/IThinningTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "DerivationFrameworkInDet/TracksInCone.h"
+#include "xAODEgamma/EgammaContainer.h"
+
+namespace ExpressionParsing {
+  class ExpressionParser;
+}
+
+class IThinningSvc;
+
+namespace DerivationFramework {
+
+  class EgammaTrackParticleThinning : public AthAlgTool, public IThinningTool {
+    public: 
+      EgammaTrackParticleThinning(const std::string& t, const std::string& n, const IInterface* p);
+      ~EgammaTrackParticleThinning();
+      StatusCode initialize();
+      StatusCode finalize();
+      virtual StatusCode doThinning() const;
+
+    private:
+      ServiceHandle<IThinningSvc> m_thinningSvc;
+      mutable unsigned int m_ntot, m_ntotGSF, m_npass, m_nGSFPass;
+      std::string m_sgKey;
+      std::string m_inDetSGKey;
+      std::string m_gsfSGKey;
+      std::string m_selectionString;
+      bool m_bestMatchOnly;
+      float m_coneSize;
+      bool m_and;
+      ExpressionParsing::ExpressionParser *m_parser;
+      void setPhotonMasks(std::vector<bool>&, std::vector<bool>&, const xAOD::EgammaContainer*&, const xAOD::TrackParticleContainer*&, const xAOD::TrackParticleContainer*&, const bool&) const;
+      void setPhotonMasks(std::vector<bool>&, std::vector<bool>&, std::vector<const xAOD::Egamma*>&, const xAOD::TrackParticleContainer*&, const xAOD::TrackParticleContainer*&, const bool&) const;
+      void setElectronMasks(std::vector<bool>&, std::vector<bool>&, const xAOD::EgammaContainer*&, const xAOD::TrackParticleContainer*&, const xAOD::TrackParticleContainer*&, const bool&) const;
+      void setElectronMasks(std::vector<bool>&, std::vector<bool>&, std::vector<const xAOD::Egamma*>&, const xAOD::TrackParticleContainer*&, const xAOD::TrackParticleContainer*&, const bool&) const;
+
+  };
+}
+
+#endif // DERIVATIONFRAMEWORK_EGAMMATRACKPARTICLETHINNING_H
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/JetTrackParticleThinning.h b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/JetTrackParticleThinning.h
new file mode 100644
index 0000000000000000000000000000000000000000..0a0226a5c983d6632995b78c784d5055040e95ff
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/JetTrackParticleThinning.h
@@ -0,0 +1,43 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// JetTrackParticleThinning.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef DERIVATIONFRAMEWORK_JETTRACKPARTICLETHINNING_H
+#define DERIVATIONFRAMEWORK_JETTRACKPARTICLETHINNING_H
+
+#include <string>
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "DerivationFrameworkInterfaces/IThinningTool.h"
+#include "GaudiKernel/ToolHandle.h"
+
+namespace ExpressionParsing {
+  class ExpressionParser;
+}
+
+class IThinningSvc;
+
+namespace DerivationFramework {
+
+  class JetTrackParticleThinning : public AthAlgTool, public IThinningTool {
+    public: 
+      JetTrackParticleThinning(const std::string& t, const std::string& n, const IInterface* p);
+      ~JetTrackParticleThinning();
+      StatusCode initialize();
+      StatusCode finalize();
+      virtual StatusCode doThinning() const;
+
+    private:
+      ServiceHandle<IThinningSvc> m_thinningSvc;
+      mutable unsigned int m_ntot, m_npass;
+      std::string m_jetSGKey, m_inDetSGKey, m_selectionString;
+      bool m_and;
+      ExpressionParsing::ExpressionParser *m_parser;
+  }; 
+}
+
+#endif // DERIVATIONFRAMEWORK_JETTRACKPARTICLETHINNING_H
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/MuonTrackParticleThinning.h b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/MuonTrackParticleThinning.h
new file mode 100644
index 0000000000000000000000000000000000000000..97103bd26bbdb192005d4ce1887721b28737284a
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/MuonTrackParticleThinning.h
@@ -0,0 +1,47 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// MuonTrackParticleThinning.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef DERIVATIONFRAMEWORK_MUONTRACKPARTICLETHINNING_H
+#define DERIVATIONFRAMEWORK_MUONTRACKPARTICLETHINNING_H
+
+#include <string>
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "DerivationFrameworkInterfaces/IThinningTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "DerivationFrameworkInDet/TracksInCone.h"
+
+namespace ExpressionParsing {
+  class ExpressionParser;
+}
+
+class IThinningSvc;
+
+namespace DerivationFramework {
+
+  class MuonTrackParticleThinning : public AthAlgTool, public IThinningTool {
+    public: 
+      MuonTrackParticleThinning(const std::string& t, const std::string& n, const IInterface* p);
+      ~MuonTrackParticleThinning();
+      StatusCode initialize();
+      StatusCode finalize();
+      virtual StatusCode doThinning() const;
+
+    private:
+      ServiceHandle<IThinningSvc> m_thinningSvc;
+      mutable unsigned int m_ntot, m_npass;
+      std::string m_muonSGKey;
+      std::string m_inDetSGKey; 
+      std::string m_selectionString; 
+      float m_coneSize;	
+      bool m_and;
+      ExpressionParsing::ExpressionParser *m_parser;
+  }; 
+}
+
+#endif // DERIVATIONFRAMEWORK_MUONTRACKPARTICLETHINNING_H
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TauTrackParticleThinning.h b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TauTrackParticleThinning.h
new file mode 100644
index 0000000000000000000000000000000000000000..c2c7e9e420a9f3c5bb46b45afdb91fd67bd68c4e
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TauTrackParticleThinning.h
@@ -0,0 +1,45 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// TauTrackParticleThinning.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef DERIVATIONFRAMEWORK_TAUTRACKPARTICLETHINNING_H
+#define DERIVATIONFRAMEWORK_TAUTRACKPARTICLETHINNING_H
+
+#include <string>
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "DerivationFrameworkInterfaces/IThinningTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "DerivationFrameworkInDet/TracksInCone.h"
+
+namespace ExpressionParsing {
+  class ExpressionParser;
+}
+
+class IThinningSvc;
+
+namespace DerivationFramework {
+
+  class TauTrackParticleThinning : public AthAlgTool, public IThinningTool {
+    public: 
+      TauTrackParticleThinning(const std::string& t, const std::string& n, const IInterface* p);
+      ~TauTrackParticleThinning();
+      StatusCode initialize();
+      StatusCode finalize();
+      virtual StatusCode doThinning() const;
+
+    private:
+      ServiceHandle<IThinningSvc> m_thinningSvc;
+      mutable unsigned int m_ntot, m_npass;
+      std::string m_tauSGKey, m_inDetSGKey, m_selectionString;
+      float m_coneSize;
+      bool m_and;
+      ExpressionParsing::ExpressionParser *m_parser;
+  }; 
+}
+
+#endif // DERIVATIONFRAMEWORK_TAUTRACKPARTICLETHINNING_H
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TrackParametersAtPV.h b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TrackParametersAtPV.h
new file mode 100644
index 0000000000000000000000000000000000000000..cbefe92e0c027a5077a4a38490ee918eefed2681
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TrackParametersAtPV.h
@@ -0,0 +1,54 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////
+// TrackParametersAtPV.h  (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef DERIVATIONFRAMEWORK_TRACKPARAMETERSATPV_H
+#define DERIVATIONFRAMEWORK_TRACKPARAMETERSATPV_H 
+
+#include<string>
+
+// Gaudi & Athena basics
+#include "AthenaBaseComps/AthAlgTool.h"
+
+// DerivationFramework includes
+#include "DerivationFrameworkInterfaces/IAugmentationTool.h"
+
+namespace DerivationFramework {
+
+  /** @class TrackParametersAtPV
+ 
+      the code used in this implementation is kindly stolen from:
+      atlasoff:: ISF/ISF_Core/ISF_Tools
+
+      @author James Catmore -at- cern.ch
+     */
+  class TrackParametersAtPV : public AthAlgTool, public IAugmentationTool {
+   
+  public: 
+    /** Constructor with parameters */
+    TrackParametersAtPV( const std::string& t, const std::string& n, const IInterface* p );
+   
+    /** Destructor */
+    ~TrackParametersAtPV();
+   
+    // Athena algtool's Hooks
+    StatusCode  initialize();
+    StatusCode  finalize();
+ 
+    /** Check that the current event passes this filter */
+    virtual StatusCode addBranches() const;
+
+  private:
+    std::string m_collTrackName;
+    std::string m_collVertexName;
+    std::string m_sgKey1;
+
+  }; 
+ 
+}
+
+#endif
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TrackParametersForTruthParticles.h b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TrackParametersForTruthParticles.h
new file mode 100644
index 0000000000000000000000000000000000000000..a7a5bbb4b9ffa81de1aca1e2932d930d9eb0a0e7
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TrackParametersForTruthParticles.h
@@ -0,0 +1,62 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////
+// TrackParametersForTruthParticles.h  (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef DERIVATIONFRAMEWORK_TrackParametersForTruthParticles_H
+#define DERIVATIONFRAMEWORK_TrackParametersForTruthParticles_H 
+
+#include<string>
+
+// Gaudi & Athena basics
+#include "AthenaBaseComps/AthAlgTool.h"
+
+// DerivationFramework includes
+#include "DerivationFrameworkInterfaces/IAugmentationTool.h"
+#include "GaudiKernel/ToolHandle.h"
+
+class IInDetPhysValDecoratorTool;
+
+namespace DerivationFramework {
+
+  /** @class TrackParametersForTruthParticles
+ 
+
+     */
+  class TrackParametersForTruthParticles : public AthAlgTool, public IAugmentationTool {
+   
+  public: 
+    /** Constructor with parameters */
+    TrackParametersForTruthParticles( const std::string& t, const std::string& n, const IInterface* p );
+   
+    /** Destructor */
+    ~TrackParametersForTruthParticles();
+   
+    // Athena algtool's Hooks
+    StatusCode  initialize();
+    StatusCode  finalize();
+ 
+    /** Check that the current event passes this filter */
+    virtual StatusCode addBranches() const;
+
+  private:
+    std::string m_collTruthName;
+    std::string m_sgKey1;
+		
+		ToolHandle<IInDetPhysValDecoratorTool> m_decoTool;
+    
+		/**  Pt cut on truth particles to be dressed  [MeV] */
+    float m_ptCut;
+
+    /**  Only dress primary truth particles */
+    bool  m_doPrimary;
+
+
+  }; 
+ 
+}
+
+#endif
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TrackParticleThinning.h b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TrackParticleThinning.h
new file mode 100644
index 0000000000000000000000000000000000000000..d25c109991bd590c616b54d2c4f67d377e99d13b
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TrackParticleThinning.h
@@ -0,0 +1,44 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// TrackParticleThinning.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef DERIVATIONFRAMEWORK_TRACKPARTICLETHINNING_H
+#define DERIVATIONFRAMEWORK_TRACKPARTICLETHINNING_H
+
+#include <string>
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "DerivationFrameworkInterfaces/IThinningTool.h"
+#include "GaudiKernel/ToolHandle.h"
+
+namespace ExpressionParsing {
+  class ExpressionParser;
+}
+
+class IThinningSvc;
+
+namespace DerivationFramework {
+
+  class TrackParticleThinning : public AthAlgTool, public IThinningTool {
+    public: 
+      TrackParticleThinning(const std::string& t, const std::string& n, const IInterface* p);
+      ~TrackParticleThinning();
+      StatusCode initialize();
+      StatusCode finalize();
+      virtual StatusCode doThinning() const;
+
+    private:
+      ServiceHandle<IThinningSvc> m_thinningSvc;
+      std::string m_expression;
+      ExpressionParsing::ExpressionParser *m_parser;
+      mutable unsigned int m_ntot, m_npass;
+      std::string m_inDetSGKey, m_selectionString;
+      bool m_and;
+  }; 
+}
+
+#endif // DERIVATIONFRAMEWORK_TRACKPARTICLETHINNING_H
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TrackStateOnSurfaceDecorator.h b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TrackStateOnSurfaceDecorator.h
new file mode 100644
index 0000000000000000000000000000000000000000..ad08c1a6cdd1c2d00f2f09e33106779aa892f67b
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TrackStateOnSurfaceDecorator.h
@@ -0,0 +1,85 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// TrackToVertexWrapper.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef DERIVATIONFRAMEWORK_TRACKSTATEONSURFACEDECORATOR_H
+#define DERIVATIONFRAMEWORK_TRACKSTATEONSURFACEDECORATOR_H
+
+#include <string>
+#include <vector>
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "DerivationFrameworkInterfaces/IAugmentationTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "AthLinks/ElementLink.h"
+#include "xAODTracking/TrackMeasurementValidationContainer.h"
+
+
+class AtlasDetectorID;
+class PixelID;
+class SCT_ID;
+class TRT_ID;
+class ITRT_CalDbSvc;
+
+namespace Trk {
+  class IResidualPullCalculator;
+  class PrepRawData;
+}
+
+namespace DerivationFramework {
+
+  class TrackStateOnSurfaceDecorator : public AthAlgTool, public IAugmentationTool {
+    public: 
+      TrackStateOnSurfaceDecorator(const std::string& t, const std::string& n, const IInterface* p);
+
+      StatusCode initialize();
+      StatusCode finalize();
+      virtual StatusCode addBranches() const;
+
+    private:
+      ElementLink< xAOD::TrackMeasurementValidationContainer > buildElementLink( const Trk::PrepRawData*, 
+                                                                  const std::vector<unsigned int>*, 
+                                                                  const xAOD::TrackMeasurementValidationContainer* ) const;
+    
+      std::string m_sgName;
+      std::string m_containerName;
+    
+      std::string m_pixelMapName;
+      std::string m_sctMapName;
+      std::string m_trtMapName;
+      
+      std::string m_pixelClustersName;
+      std::string m_sctClustersName;
+      std::string m_trtDCName;      
+      
+      std::string m_pixelMsosName;
+      std::string m_sctMsosName;
+      std::string m_trtMsosName;
+      
+      const AtlasDetectorID* m_idHelper;
+      const PixelID*         m_pixId; 
+      const SCT_ID*          m_sctId;
+      const TRT_ID*          m_trtId;
+
+      ToolHandle < Trk::IResidualPullCalculator > m_residualPullCalculator;
+      ServiceHandle<ITRT_CalDbSvc> m_trtcaldbSvc;
+      
+      bool    m_storeHoles;
+      bool    m_storeOutliers;
+      bool    m_storeTRT;
+      bool    m_storeSCT;
+      bool    m_storePixel;
+      bool    m_addPulls;
+      bool    m_addSurfaceInfo;
+      bool    m_addPRD;
+      bool    m_addExtraEventInfo;
+      
+  }; 
+}
+
+#endif // DERIVATIONFRAMEWORK_TRACKSTATEONSURFACEDECORATOR_H
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TrackToVertexWrapper.h b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TrackToVertexWrapper.h
new file mode 100644
index 0000000000000000000000000000000000000000..eaedc7be4d7e1305e77f5d7200d0391d7f0ad92a
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TrackToVertexWrapper.h
@@ -0,0 +1,40 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// TrackToVertexWrapper.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef DERIVATIONFRAMEWORK_TRACKTOVERTEXWRAPPER_H
+#define DERIVATIONFRAMEWORK_TRACKTOVERTEXWRAPPER_H
+
+#include <string>
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "DerivationFrameworkInterfaces/IAugmentationTool.h"
+#include "GaudiKernel/ToolHandle.h"
+
+namespace Trk
+{
+  class ITrackToVertexIPEstimator;
+}
+
+namespace DerivationFramework {
+
+  class TrackToVertexWrapper : public AthAlgTool, public IAugmentationTool {
+    public: 
+      TrackToVertexWrapper(const std::string& t, const std::string& n, const IInterface* p);
+
+      StatusCode initialize();
+      StatusCode finalize();
+      virtual StatusCode addBranches() const;
+
+    private:
+      ToolHandle< Trk::ITrackToVertexIPEstimator > m_tool;
+      std::string m_sgName;
+      std::string m_containerName;
+  }; 
+}
+
+#endif // DERIVATIONFRAMEWORK_TRACKTOVERTEXWRAPPER_H
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TracksInCone.h b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TracksInCone.h
new file mode 100644
index 0000000000000000000000000000000000000000..1e1596341e016c507aeeb9ee90fa052404cf2e2e
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/TracksInCone.h
@@ -0,0 +1,33 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// ======================================================================
+// TracksInCone
+// James.Catmore@cern.ch
+// Given an xAOD::IParticle and an IDTrackParticle container, checks 
+// which tracks are in a cone of a given size around the IParticle. Sets
+// a mask accordingly. Intended for thinning use.
+// ======================================================================
+#pragma once
+
+#include "xAODBase/IParticle.h"
+#include "xAODTracking/TrackParticleContainer.h"
+namespace DerivationFramework {
+	struct TracksInCone{
+		
+		void select(const xAOD::IParticle* particle, float coneSize, const xAOD::TrackParticleContainer* tracks, std::vector<bool> &mask) {
+			float particleEta = particle->eta();
+			float particlePhi = particle->phi();
+			unsigned int i(0);
+			for (xAOD::TrackParticleContainer::const_iterator trIt = tracks->begin(); trIt!=tracks->end(); ++trIt, ++i) {
+				float deltaEta = (*trIt)->eta() - particleEta;
+				float deltaPhi = fabs((*trIt)->phi() - particlePhi);
+				if (deltaPhi > TMath::Pi()) deltaPhi = 2.0*TMath::Pi() - deltaPhi;
+				float deltaR = sqrt(deltaEta*deltaEta + deltaPhi*deltaPhi);
+				if (deltaR < coneSize) mask[i] = true;
+			}
+			return;
+		}
+	};
+}
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/cmt/requirements b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/cmt/requirements
new file mode 100644
index 0000000000000000000000000000000000000000..075c683930d0860f57837d7529b3871005faa341
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/cmt/requirements
@@ -0,0 +1,50 @@
+package DerivationFrameworkInDet
+author James Catmore <james.catmore@cern.ch>
+
+#################################################################
+# public use statements
+use AtlasPolicy                 AtlasPolicy-*
+use AthenaBaseComps             AthenaBaseComps-*       Control
+use DerivationFrameworkInterfaces DerivationFrameworkInterfaces-* PhysicsAnalysis/DerivationFramework
+use xAODBase			xAODBase-*		Event/xAOD
+use xAODTracking                xAODTracking-*          Event/xAOD
+use xAODEgamma                  xAODEgamma-*            Event/xAOD
+use AthLinks                    AthLinks-*              Control
+
+private
+use AthenaKernel		            AthenaKernel-*		Control
+use GaudiInterface              GaudiInterface-*        External
+use xAODMuon			              xAODMuon-*		Event/xAOD
+use xAODTau			                xAODTau-*		Event/xAOD	
+use xAODJet			                xAODJet-*		Event/xAOD
+use xAODTruth           xAODTruth-*             Event/xAOD
+use ExpressionEvaluation	ExpressionEvaluation-*	PhysicsAnalysis/CommonTools  
+use TrkVertexFitterInterfaces   TrkVertexFitterInterfaces-*  Tracking/TrkVertexFitter
+
+use AtlasDetDescr               AtlasDetDescr-*                 DetectorDescription
+use TrkTrack                    TrkTrack-*                      Tracking/TrkEvent
+use TrkEventPrimitives          TrkEventPrimitives-*            Tracking/TrkEvent
+use TrkPrepRawData              TrkPrepRawData-*                Tracking/TrkEvent
+use InDetIdentifier             InDetIdentifier-*               InnerDetector/InDetDetDescr
+use TrkParameters               TrkParameters-*                 Tracking/TrkEvent
+use TrkCompetingRIOsOnTrack     TrkCompetingRIOsOnTrack-*       Tracking/TrkEvent
+use TrkRIO_OnTrack              TrkRIO_OnTrack-*                Tracking/TrkEvent
+use InDetReadoutGeometry        InDetReadoutGeometry-*          InnerDetector/InDetDetDescr
+use  TrkToolInterfaces          TrkToolInterfaces-*             Tracking/TrkTools
+use TRT_ConditionsServices      TRT_ConditionsServices-*        InnerDetector/InDetConditions
+use CommissionEvent		CommissionEvent-*	      	Commission
+use xAODEventInfo       	xAODEventInfo-*         	Event/xAOD
+
+use InDetPhysValMonitoring      InDetPhysValMonitoring-*     InnerDetector/InDetValidation
+
+################################################################
+#
+public
+
+## declare the directories CMT should know about
+branches python share src
+
+apply_pattern dual_use_library files= " *.cxx "
+apply_pattern declare_joboptions files=" *.py"
+apply_pattern declare_python_modules files="*.py"
+
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/python/InDetCommon.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/python/InDetCommon.py
new file mode 100644
index 0000000000000000000000000000000000000000..d5094b2fdd325a3a397dab6e6790fe970d3e25c4
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/python/InDetCommon.py
@@ -0,0 +1,27 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+#********************************************************************
+# InDetCommon.py 
+# Schedules all tools needed for ID track object selection and writes
+# results into SG. These may then be accessed along the train   
+#********************************************************************
+from DerivationFrameworkCore.DerivationFrameworkMaster import *
+
+#====================================================================
+# EXPRESSION OF Z0 AT THE PRIMARY VERTEX
+#====================================================================
+from DerivationFrameworkInDet.DerivationFrameworkInDetConf import DerivationFramework__TrackParametersAtPV
+DFCommonZ0AtPV = DerivationFramework__TrackParametersAtPV(name = "DFCommonZ0AtPV",
+                                                          TrackParticleContainerName = "InDetTrackParticles",
+							  VertexContainerName = "PrimaryVertices", 
+                                                          Z0SGEntryName = "DFCommonInDetTrackZ0AtPV" )
+ToolSvc += DFCommonZ0AtPV
+
+#=======================================
+# CREATE THE DERIVATION KERNEL ALGORITHM   
+#=======================================
+
+from DerivationFrameworkCore.DerivationFrameworkCoreConf import DerivationFramework__CommonAugmentation
+DerivationFrameworkJob += CfgMgr.DerivationFramework__CommonAugmentation("InDetCommonKernel",
+                                                                         AugmentationTools = [DFCommonZ0AtPV]
+                                                                         )
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/python/__init__.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/python/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..74583d364ec2ca794156596c7254d9b234a940c6
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/python/__init__.py
@@ -0,0 +1,2 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/share/IDTR1.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/share/IDTR1.py
new file mode 100644
index 0000000000000000000000000000000000000000..bdf00c0355682f0b9aaef6063f58f705f9ec31c5
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/share/IDTR1.py
@@ -0,0 +1,59 @@
+#====================================================================
+# IDTR1.py
+# Test set-up
+# It requires the reductionConf flag IDTR1 in Reco_tf.py  
+#====================================================================
+ 
+# Set up common services and job object.
+# This should appear in ALL derivation job options
+from DerivationFrameworkCore.DerivationFrameworkMaster import *
+ 
+#====================================================================
+# CP GROUP TOOLS
+#====================================================================
+from TrkVertexFitterUtils.TrkVertexFitterUtilsConf import Trk__TrackToVertexIPEstimator
+IDTR1IPETool = Trk__TrackToVertexIPEstimator(name = "IDTR1IPETool")
+ToolSvc += IDTR1IPETool
+print IDTR1IPETool
+ 
+#====================================================================
+# AUGMENTATION TOOLS
+#====================================================================
+from DerivationFrameworkInDet.DerivationFrameworkInDetConf import DerivationFramework__TrackToVertexWrapper
+IDTR1TrackToVertexWrapper= DerivationFramework__TrackToVertexWrapper(name = "IDTR1TrackToVertexWrapper",
+                                                                      TrackToVertexIPEstimator = IDTR1IPETool,
+                                                                      DecorationPrefix = "IDTR1",
+                                                                      ContainerName = "InDetTrackParticles")
+ToolSvc += IDTR1TrackToVertexWrapper 
+print IDTR1TrackToVertexWrapper
+ 
+#====================================================================
+# CREATE THE DERIVATION KERNEL ALGORITHM AND PASS THE ABOVE TOOLS  
+#====================================================================
+from DerivationFrameworkCore.DerivationFrameworkCoreConf import DerivationFramework__DerivationKernel
+DerivationFrameworkJob += CfgMgr.DerivationFramework__DerivationKernel("IDTR1Kernel",
+                                                                        AugmentationTools = [IDTR1TrackToVertexWrapper]
+                                                                      )
+ 
+ 
+#====================================================================
+# SET UP STREAM  
+#====================================================================
+ 
+# The base name (DAOD_TEST5 here) must match the string in
+streamName = derivationFlags.WriteDAOD_IDTR1Stream.StreamName
+fileName   = buildFileName( derivationFlags.WriteDAOD_IDTR1Stream )
+IDTR1Stream = MSMgr.NewPoolRootStream( streamName, fileName )
+IDTR1Stream.AcceptAlgs(["IDTR1Kernel"])
+
+# Add event info, tracks, vertices and the decoration
+IDTR1Stream.AddItem("xAOD::EventInfo#*")
+IDTR1Stream.AddItem("xAOD::EventAuxInfo#*")
+IDTR1Stream.AddItem("xAOD::TrackParticleContainer#*")
+IDTR1Stream.AddItem("xAOD::TrackParticleAuxContainer#*")
+IDTR1Stream.AddItem("xAOD::VertexContainer#PrimaryVertices")
+IDTR1Stream.AddItem("xAOD::VertexAuxContainer#PrimaryVerticesAux.")
+#IDTR1Stream.AddItem("std::vector<float>#IDTR1D0")
+#IDTR1Stream.AddItem("std::vector<float>#IDTR1Z0")
+#IDTR1Stream.AddItem("std::vector<float>#IDTR1D0Sigma")
+#IDTR1Stream.AddItem("std::vector<float>#IDTR1Z0Sigma")
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/share/truthDressing.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/share/truthDressing.py
new file mode 100755
index 0000000000000000000000000000000000000000..dc43fb7eec0eaa338281daf0090a9dc8d13e0883
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/share/truthDressing.py
@@ -0,0 +1,190 @@
+
+
+#--------------------------------------------------------------
+# Import config
+#--------------------------------------------------------------
+from AthenaCommon.AthenaCommonFlags import athenaCommonFlags
+from RecExConfig.RecFlags import rec
+from RecExConfig.RecAlgsFlags import recAlgs
+
+#--------------------------------------------------------------
+# Event related parameters and input files
+#--------------------------------------------------------------
+
+athenaCommonFlags.FilesInput = ["/tmp/amorley/mc14_13TeV.187039.Herwigpp_UEEE4_CTEQ6L1_Zmumu.merge.AOD.e2770_s1982_s2008_r5787_r5853_tid01598243_00/AOD.01598243._000545.pool.root.1"]
+
+import MagFieldServices.SetupField
+
+# --- number of events to process
+athenaCommonFlags.EvtMax     = 10
+athenaCommonFlags.SkipEvents = 0#122-2 #33
+
+doVP1 = False
+
+# --- disable error protection of RecExCommon
+athenaCommonFlags.AllowIgnoreConfigError.set_Value_and_Lock(False)
+
+
+#--------------------------------------------------------------
+# Additional Detector Setup
+#--------------------------------------------------------------
+
+from AthenaCommon.DetFlags import DetFlags 
+
+# --- switch on InnerDetector
+DetFlags.ID_setOn()
+
+# --- turn off Calo
+DetFlags.Calo_setOff()
+
+# --- and switch off Muons
+DetFlags.Muon_setOff()
+
+#--------------------------------------------------------------
+# Control
+#--------------------------------------------------------------
+
+# --- Set output level threshold (2=DEBUG, 3=INFO, 4=WARNING, 5=ERROR, 6=FATAL )
+rec.OutputLevel.set_Value_and_Lock       (INFO)
+
+# --- controls what is written out. ESD includes AOD, so it's normally enough
+# --- ESD writing temporarily disabled post 2013 migration - to be reinstated! 
+
+from ParticleBuilderOptions.AODFlags import AODFlags
+AODFlags.TrackParticleSlimmer=False 
+AODFlags.TrackParticleLastHitAndPerigeeSlimmer=False
+
+rec.doWriteESD.set_Value_and_Lock        (False)###
+rec.doAOD.set_Value_and_Lock             (False)
+rec.doWriteAOD.set_Value_and_Lock        (False)
+rec.doDPD.set_Value_and_Lock             (False)
+rec.doCBNT.set_Value_and_Lock            (False)
+rec.doWriteTAG.set_Value_and_Lock        (False)
+
+# --- turn on InDet
+rec.doInDet.set_Value_and_Lock           (True)
+# --- turn off calo
+rec.doCalo.set_Value_and_Lock           (False)
+# --- turn off muons
+rec.doMuon.set_Value_and_Lock            (False) 
+# --- turn off forward detectors
+rec.doForwardDet.set_Value_and_Lock      (False)
+# --- turn off trigger
+rec.doTrigger.set_Value_and_Lock         (False)
+
+# --- turn off combined reconstruction
+rec.doEgamma.set_Value_and_Lock          (False)
+rec.doMuonCombined.set_Value_and_Lock    (False)
+rec.doTau.set_Value_and_Lock             (False)
+rec.doJetMissingETTag.set_Value_and_Lock (False)
+
+# --- turn of calo stuff we don't need anyway
+from CaloRec.CaloRecFlags import jobproperties
+jobproperties.CaloRecFlags.doCaloTopoCluster.set_Value_and_Lock  (False)
+jobproperties.CaloRecFlags.doCaloEMTopoCluster.set_Value_and_Lock(False)
+jobproperties.CaloRecFlags.doCaloTopoTower.set_Value_and_Lock    (False)
+
+# --- turn of jets (Hack!!!)
+from JetRec.JetRecFlags import jetFlags
+jetFlags.Enabled.set_Value_and_Lock          (False)
+
+# --- turn off egamma Brem
+recAlgs.doEgammaBremReco.set_Value_and_Lock  (False)
+# --- turn off Eflow and missing ET
+recAlgs.doEFlow.set_Value_and_Lock           (False)
+recAlgs.doEFlowJet.set_Value_and_Lock        (False)
+recAlgs.doMissingET.set_Value_and_Lock       (False)
+recAlgs.doMissingETSig.set_Value_and_Lock    (False)
+recAlgs.doObjMissingET.set_Value_and_Lock    (False)
+# --- turn off combined muons
+recAlgs.doMuGirl.set_Value_and_Lock          (False)
+recAlgs.doMuTag.set_Value_and_Lock           (False)
+recAlgs.doMuidLowPt.set_Value_and_Lock       (False)
+recAlgs.doMuonIDCombined.set_Value_and_Lock  (False)
+recAlgs.doMuonIDStandAlone.set_Value_and_Lock(False)
+recAlgs.doMuonSpShower.set_Value_and_Lock    (False)
+recAlgs.doStaco.set_Value_and_Lock           (False)
+recAlgs.doCaloTrkMuId.set_Value_and_Lock     (False)
+recAlgs.doTileMuID.set_Value_and_Lock        (False)
+# --- trigger
+recAlgs.doTrigger.set_Value_and_Lock         (False)
+
+
+#--------------------------------------------------------------
+# Printout config
+#--------------------------------------------------------------
+
+from AthenaCommon.GlobalFlags import globalflags
+print "globalflags configuration:"
+print globalflags
+
+print "detflags configuration:"
+DetFlags.Print()
+
+print "rec configuration:"
+print rec
+
+#--------------------------------------------------------------
+# Load InDet configuration
+#--------------------------------------------------------------
+
+
+# IMPORTANT NOTE: initialization of the flags and locking them is done in InDetRec_jobOptions.py!
+# This way RecExCommon just needs to import the properties without doing anything else!
+# DO NOT SET JOBPROPERTIES AFTER THIS LINE! The change will be ignored!
+
+#--------------------------------------------------------------
+# load master joboptions file
+#--------------------------------------------------------------
+
+include ("RecExCommon/RecExCommon_topOptions.py")
+
+from AthenaCommon import CfgMgr
+
+# DerivationJob is COMMON TO ALL DERIVATIONS
+DerivationFrameworkJob = CfgMgr.AthSequencer("MySeq2")
+
+# Set up stream auditor
+from AthenaCommon.AppMgr import ServiceMgr as svcMgr
+if not hasattr(svcMgr, 'DecisionSvc'):
+        svcMgr += CfgMgr.DecisionSvc()
+svcMgr.DecisionSvc.CalcStats = True
+
+
+# Add the track dressing alg
+streamName = "TESTSTREAM_"
+
+from DerivationFrameworkInDet.DerivationFrameworkInDetConf import DerivationFramework__TrackParametersForTruthParticles
+TruthDecor = DerivationFramework__TrackParametersForTruthParticles( name = "TruthTPDecor",
+                                                                    DecorationPrefix = streamName)
+ToolSvc +=TruthDecor
+
+augmentationTools = [TruthDecor]
+
+
+from DerivationFrameworkCore.DerivationFrameworkCoreConf import DerivationFramework__CommonAugmentation
+DerivationFrameworkJob += CfgMgr.DerivationFramework__CommonAugmentation("DFTSOS_KERN",
+                                                                        AugmentationTools = augmentationTools,
+                                                                        OutputLevel =INFO)
+
+topSequence += DerivationFrameworkJob
+
+
+from OutputStreamAthenaPool.MultipleStreamManager import MSMgr
+
+fileName   = "test.pool.root"
+TestStream = MSMgr.NewPoolRootStream( streamName, fileName)
+TestStream.AddItem("xAOD::EventInfo_v1#*")
+TestStream.AddItem("xAOD::EventAuxInfo_v1#*")
+TestStream.AddItem("xAOD::TruthParticleContainer_v1#*")
+TestStream.AddItem("xAOD::TruthParticleAuxContainer_v1#*")
+TestStream.AddItem("xAOD::TruthVertexContainer_v1#*")
+TestStream.AddItem("xAOD::TruthVertexAuxContainer_v1#*")
+TestStream.AddItem("xAOD::TruthEventContainer_v1#*")
+TestStream.AddItem("xAOD::TruthEventAuxContainer_v1#*")
+
+
+if doVP1:
+  from VP1Algs.VP1AlgsConf import VP1Alg
+  topSequence += VP1Alg()
+
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/EgammaTrackParticleThinning.cxx b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/EgammaTrackParticleThinning.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..0228900b85630caab2804c1d2cee628bab803e28
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/EgammaTrackParticleThinning.cxx
@@ -0,0 +1,328 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/////////////////////////////////////////////////////////////////
+// EgammaTrackParticleThinning.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Author: James Catmore (James.Catmore@cern.ch)
+
+#include "DerivationFrameworkInDet/EgammaTrackParticleThinning.h"
+#include "AthenaKernel/IThinningSvc.h"
+#include "ExpressionEvaluation/ExpressionParser.h"
+#include "ExpressionEvaluation/SGxAODProxyLoader.h"
+#include "ExpressionEvaluation/SGNTUPProxyLoader.h"
+#include "ExpressionEvaluation/MultipleProxyLoader.h"
+#include "xAODEgamma/PhotonContainer.h"
+#include "xAODEgamma/ElectronContainer.h"
+#include "xAODTracking/TrackParticleContainer.h"
+#include "xAODTracking/VertexContainer.h"
+#include <vector>
+#include <string>
+
+// Constructor
+DerivationFramework::EgammaTrackParticleThinning::EgammaTrackParticleThinning(const std::string& t,
+                                                                              const std::string& n,
+                                                                              const IInterface* p ) :
+AthAlgTool(t,n,p),
+m_thinningSvc("ThinningSvc",n),
+m_ntot(0),
+m_ntotGSF(0),
+m_npass(0),
+m_nGSFPass(0),
+m_sgKey(""),
+m_inDetSGKey("InDetTrackParticles"),
+m_gsfSGKey("GSFTrackParticles"),
+m_selectionString(""),
+m_bestMatchOnly(true),
+m_coneSize(-1.0),
+m_and(false)
+{
+    declareInterface<DerivationFramework::IThinningTool>(this);
+    declareProperty("ThinningService", m_thinningSvc);
+    declareProperty("SGKey", m_sgKey);
+    declareProperty("InDetTrackParticlesKey", m_inDetSGKey);
+    declareProperty("GSFTrackParticlesKey", m_gsfSGKey);
+    declareProperty("SelectionString", m_selectionString);
+    declareProperty("BestMatchOnly", m_bestMatchOnly);
+    declareProperty("ConeSize", m_coneSize);
+    declareProperty("ApplyAnd", m_and); 
+}
+
+// Destructor
+DerivationFramework::EgammaTrackParticleThinning::~EgammaTrackParticleThinning() {
+}
+
+// Athena initialize and finalize
+StatusCode DerivationFramework::EgammaTrackParticleThinning::initialize()
+{
+    // Decide which collections need to be checked for ID TrackParticles
+    ATH_MSG_VERBOSE("initialize() ...");
+    if (m_inDetSGKey=="") {
+        ATH_MSG_FATAL("No inner detector track collection provided for thinning.");
+        return StatusCode::FAILURE;
+    } else {ATH_MSG_INFO("Using " << m_inDetSGKey << "as the source collection for inner detector track particles");}
+    if (m_sgKey=="") {
+        ATH_MSG_FATAL("No e-gamma collection provided for thinning.");
+        return StatusCode::FAILURE;
+    } else { ATH_MSG_INFO("Inner detector track particles associated with objects in " << m_sgKey << " will be retained in this format with the rest being thinned away");}
+    if (m_gsfSGKey=="") {
+        ATH_MSG_FATAL("No GSF track collection provided for thinning.");
+        return StatusCode::FAILURE;
+    } else { ATH_MSG_INFO("GSF track particles associated with objects in " << m_sgKey << " will be retained in this format with the rest being thinned away");}
+    
+    // Set up the text-parsing machinery for selectiong the photon directly according to user cuts
+    if (m_selectionString!="") {
+	    ExpressionParsing::MultipleProxyLoader *proxyLoaders = new ExpressionParsing::MultipleProxyLoader();
+	    proxyLoaders->push_back(new ExpressionParsing::SGxAODProxyLoader(evtStore()));
+	    proxyLoaders->push_back(new ExpressionParsing::SGNTUPProxyLoader(evtStore()));
+	    if (m_selectionString!="") {
+            m_parser = new ExpressionParsing::ExpressionParser(proxyLoaders);
+            m_parser->loadExpression(m_selectionString);
+        }
+    }
+    
+    return StatusCode::SUCCESS;
+}
+
+StatusCode DerivationFramework::EgammaTrackParticleThinning::finalize()
+{
+    ATH_MSG_VERBOSE("finalize() ...");
+    ATH_MSG_INFO("Processed "<< m_ntot <<" tracks, of which "<< m_npass<< " were retained ");
+    ATH_MSG_INFO("Processed "<< m_ntotGSF <<" GSF tracks, of which "<< m_nGSFPass << " were retained ");
+    if (m_selectionString!="") {
+        delete m_parser;
+        m_parser = 0;
+    }
+    
+    return StatusCode::SUCCESS;
+}
+
+// The thinning itself
+StatusCode DerivationFramework::EgammaTrackParticleThinning::doThinning() const
+{
+    
+    // Retrieve main TrackParticle collection
+    const xAOD::TrackParticleContainer* importedTrackParticles;
+    if (evtStore()->retrieve(importedTrackParticles,m_inDetSGKey).isFailure()) {
+        ATH_MSG_ERROR("No TrackParticle collection with name " << m_inDetSGKey << " found in StoreGate!");
+        return StatusCode::FAILURE;
+    }
+    // Retrieve GSF TrackParticle collection if required
+    const xAOD::TrackParticleContainer* importedGSFTrackParticles;
+    if (evtStore()->retrieve(importedGSFTrackParticles,m_gsfSGKey).isFailure()) {
+        ATH_MSG_ERROR("No GSF TrackParticle collection with name " << m_gsfSGKey << " found in StoreGate!");
+        return StatusCode::FAILURE;
+    }
+    
+    // Check the event contains tracks
+    unsigned int nTracks = importedTrackParticles->size();
+    unsigned int nGSF = importedGSFTrackParticles->size();
+    if (nTracks==0 || nGSF==0) return StatusCode::SUCCESS;
+    
+    // Set up a mask with the same entries as the full TrackParticle collection(s)
+    std::vector<bool> mask, gsfMask;
+    mask.assign(nTracks,false); // default: don't keep any tracks
+    gsfMask.assign(nGSF,false);
+    m_ntot += nTracks;
+    m_ntotGSF += nGSF;
+    
+    // Retrieve e-gamma container
+    const xAOD::EgammaContainer* importedEgamma(0);
+    if (evtStore()->retrieve(importedEgamma,m_sgKey).isFailure()) {
+        ATH_MSG_ERROR("No e-gamma collection with name " << m_sgKey << " found in StoreGate!");
+        return StatusCode::FAILURE;
+    }
+    unsigned int nEgammas(importedEgamma->size());
+    if (nEgammas==0) return StatusCode::SUCCESS;
+    std::vector<const xAOD::Egamma*> egToCheck; egToCheck.clear();
+    
+    // Execute the text parsers if requested
+    if (m_selectionString!="") {
+        std::vector<int> entries =  m_parser->evaluateAsVector();
+        unsigned int nEntries = entries.size();
+        // check the sizes are compatible
+        if (nEgammas!= nEntries ) {
+        	ATH_MSG_ERROR("Sizes incompatible! Are you sure your selection string used e-gamma objects??");
+            return StatusCode::FAILURE;
+        } else {
+        	// identify which e-gammas to keep for the thinning check
+        	for (unsigned int i=0; i<nEgammas; ++i) if (entries[i]==1) egToCheck.push_back((*importedEgamma)[i]);
+        }
+    }
+    
+    // Are we dealing with electrons or photons?
+    const xAOD::ElectronContainer* testElectrons = dynamic_cast<const xAOD::ElectronContainer*>(importedEgamma);
+    const xAOD::PhotonContainer* testPhotons = dynamic_cast<const xAOD::PhotonContainer*>(importedEgamma);
+    bool isElectrons(false), isPhotons(false);
+    if (testElectrons) isElectrons = true;
+    if (testPhotons) isPhotons = true;
+
+    // Set elements in the mask to true if there is a corresponding ElementLink from a reconstructed object
+    if (m_selectionString=="") { // check all objects as user didn't provide a selection string
+        if (isElectrons) setElectronMasks(mask,gsfMask,importedEgamma,importedTrackParticles,importedGSFTrackParticles,m_bestMatchOnly);
+        if (isPhotons) setPhotonMasks(mask,gsfMask,importedEgamma,importedTrackParticles,importedGSFTrackParticles,m_bestMatchOnly);
+    } else { // check only photons passing user selection string
+        if (isElectrons) setElectronMasks(mask,gsfMask,egToCheck,importedTrackParticles,importedGSFTrackParticles,m_bestMatchOnly);
+        if (isPhotons) setPhotonMasks(mask,gsfMask,egToCheck,importedTrackParticles,importedGSFTrackParticles,m_bestMatchOnly);
+    }
+    
+    // Count up the mask contents
+    for (unsigned int i=0; i<nTracks; ++i) {
+        if (mask[i]) ++m_npass;
+    }
+    for (unsigned int i=0; i<nGSF; ++i) {
+        if (gsfMask[i]) ++m_nGSFPass;
+    }
+    
+    
+    // Execute the thinning service based on the mask. Finish.
+    if (m_and) {
+        if (m_thinningSvc->filter(*importedTrackParticles, mask, IThinningSvc::Operator::And).isFailure()) {
+                ATH_MSG_ERROR("Application of thinning service failed! ");
+                return StatusCode::FAILURE;
+        }
+	if (m_thinningSvc->filter(*importedGSFTrackParticles, gsfMask, IThinningSvc::Operator::And).isFailure()) {
+        	ATH_MSG_ERROR("Application of thinning service failed! ");
+        	return StatusCode::FAILURE;
+    	}
+    }
+    if (!m_and) {
+        if (m_thinningSvc->filter(*importedTrackParticles, mask, IThinningSvc::Operator::Or).isFailure()) {
+                ATH_MSG_ERROR("Application of thinning service failed! ");
+                return StatusCode::FAILURE;
+        }
+        if (m_thinningSvc->filter(*importedGSFTrackParticles, gsfMask, IThinningSvc::Operator::Or).isFailure()) {
+        	ATH_MSG_ERROR("Application of thinning service failed! ");
+        	return StatusCode::FAILURE;
+    	}
+    }
+    
+    return StatusCode::SUCCESS;
+}
+
+void DerivationFramework::EgammaTrackParticleThinning::setPhotonMasks(std::vector<bool>& mask,
+                                                                      std::vector<bool>& gsfMask,
+                                                                      const xAOD::EgammaContainer*& egammas,
+                                                                      const xAOD::TrackParticleContainer*& tps,
+                                                                      const xAOD::TrackParticleContainer*& gsfs,
+                                                                      const bool& bestMatchOnly) const {
+   
+    DerivationFramework::TracksInCone trIC;
+    for (xAOD::EgammaContainer::const_iterator egIt=egammas->begin(); egIt!=egammas->end(); ++egIt) {
+        const xAOD::Photon* photon = dynamic_cast<const xAOD::Photon*>(*egIt);
+        if (m_coneSize>0.0) {
+		trIC.select(photon,m_coneSize,tps,mask); // check InDet tracks in a cone around the e-gammas
+	}	
+        std::vector< ElementLink< xAOD::VertexContainer > > vertexLinks= photon->vertexLinks();
+        unsigned int nLinks = vertexLinks.size();
+        if (nLinks==0) continue;
+        if (bestMatchOnly) nLinks = 1;
+        for (unsigned int i=0; i<nLinks; ++i) {
+	    if (!(vertexLinks[i])) continue;
+            if (!(vertexLinks[i]).isValid() ) continue;
+            const xAOD::Vertex* vx = *(vertexLinks[i]);
+            if(!vx) continue;
+            auto trackParticleLinks = vx->trackParticleLinks();
+            for ( auto link : trackParticleLinks){
+                if( !link.isValid() ) continue;
+                gsfMask[link.index() ] = true;
+                const ElementLink< xAOD::TrackParticleContainer > origTrackLink =
+                (*gsfs)[link.index()]->auxdata< ElementLink< xAOD::TrackParticleContainer > >("originalTrackParticle");
+                int inDetIndex = origTrackLink.index();
+                mask[inDetIndex] = true;
+            }
+        }
+    }
+    return;
+}
+
+void DerivationFramework::EgammaTrackParticleThinning::setPhotonMasks(std::vector<bool>& mask,
+                                                                      std::vector<bool>& gsfMask,
+                                                                      std::vector<const xAOD::Egamma*>& egammas,
+                                                                      const xAOD::TrackParticleContainer*& tps,
+                                                                      const xAOD::TrackParticleContainer*& gsfs,
+                                                                      const bool& bestMatchOnly) const {
+    DerivationFramework::TracksInCone trIC; 
+    for (std::vector<const xAOD::Egamma*>::iterator egIt=egammas.begin(); egIt!=egammas.end(); ++egIt) {
+        const xAOD::Photon* photon = dynamic_cast<const xAOD::Photon*>(*egIt);
+        if (m_coneSize>0.0){ trIC.select(photon,m_coneSize,tps,mask);} // check InDet tracks in a cone around the e-gammas
+        std::vector< ElementLink< xAOD::VertexContainer > > vertexLinks= photon->vertexLinks();
+        unsigned int nLinks = vertexLinks.size();
+        if (nLinks == 0) {continue;}
+        if (bestMatchOnly) nLinks = 1;
+        for (unsigned int i=0; i<nLinks; ++i) {
+            if( ! (vertexLinks[i]).isValid() ) continue;
+            const xAOD::Vertex* vx = *(vertexLinks[i]);
+            if(!vx) continue;
+            auto trackParticleLinks = vx->trackParticleLinks();
+            for ( auto link : trackParticleLinks){
+                if( !link.isValid() ) continue;
+                gsfMask[link.index() ] = true;
+                const ElementLink< xAOD::TrackParticleContainer > origTrackLink =
+                (*gsfs)[link.index()]->auxdata< ElementLink< xAOD::TrackParticleContainer > >("originalTrackParticle");
+                int inDetIndex = origTrackLink.index();
+                mask[inDetIndex] = true;
+            }
+        }
+    }
+    return;
+}
+
+void DerivationFramework::EgammaTrackParticleThinning::setElectronMasks(std::vector<bool>& mask,
+                                                                        std::vector<bool>& gsfMask,
+                                                                        const xAOD::EgammaContainer*& egammas,
+                                                                        const xAOD::TrackParticleContainer*& tps,
+                                                                        const xAOD::TrackParticleContainer*& gsfs,
+                                                                        const bool& bestMatchOnly) const{
+    DerivationFramework::TracksInCone trIC;
+    for (xAOD::EgammaContainer::const_iterator egIt=egammas->begin(); egIt!=egammas->end(); ++egIt) {
+        const xAOD::Electron* electron = dynamic_cast<const xAOD::Electron*>(*egIt);
+	if (m_coneSize>0.0) trIC.select(electron,m_coneSize,tps,mask); // check InDet tracks in a cone around the e-gammas
+        unsigned int nGSFLinks = 1;
+        if (!bestMatchOnly) nGSFLinks = electron->nTrackParticles();
+        for (unsigned int i=0; i<nGSFLinks; ++i) {
+	    if (!(electron->trackParticleLink(i).isValid())) continue;
+            int gsfIndex = electron->trackParticleLink(i).index();
+            gsfMask[gsfIndex] = true;
+            const ElementLink< xAOD::TrackParticleContainer > origTrackLink =
+            (*gsfs)[gsfIndex]->auxdata< ElementLink< xAOD::TrackParticleContainer > >("originalTrackParticle");
+	    if (origTrackLink.isValid()) {
+            	int inDetIndex = origTrackLink.index();
+            	mask[inDetIndex] = true;
+	    }	
+	}
+    }
+    return;
+}
+
+void DerivationFramework::EgammaTrackParticleThinning::setElectronMasks(std::vector<bool>& mask,
+                                                                        std::vector<bool>& gsfMask,
+                                                                        std::vector<const xAOD::Egamma*>& egammas,
+                                                                        const xAOD::TrackParticleContainer*& tps,
+                                                                        const xAOD::TrackParticleContainer*& gsfs,
+                                                                        const bool& bestMatchOnly) const {
+    DerivationFramework::TracksInCone trIC;
+    for (std::vector<const xAOD::Egamma*>::iterator egIt=egammas.begin(); egIt!=egammas.end(); ++egIt) {
+        unsigned int nGSFLinks = 1;
+        const xAOD::Electron* electron = dynamic_cast<const xAOD::Electron*>(*egIt);
+	if (m_coneSize>0.0) trIC.select(electron,m_coneSize,tps,mask); // check InDet tracks in a cone around the e-gammas
+        if (!bestMatchOnly) nGSFLinks = electron->nTrackParticles();
+        for (unsigned int i=0; i<nGSFLinks; ++i) {
+	    if (!(electron->trackParticleLink(i).isValid())) continue;
+            int gsfIndex = electron->trackParticleLink(i).index();
+            gsfMask[gsfIndex] = true;
+            const ElementLink< xAOD::TrackParticleContainer > origTrackLink =
+            (*gsfs)[gsfIndex]->auxdata< ElementLink< xAOD::TrackParticleContainer > >("originalTrackParticle");
+	    if (origTrackLink.isValid()) {
+            	int inDetIndex = origTrackLink.index();
+            	mask[inDetIndex] = true;
+	    }	
+	 }
+    }
+    return;
+}
+
+
+
+
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/JetTrackParticleThinning.cxx b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/JetTrackParticleThinning.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..e4addae5f673b13d8b4b1387391323488f8d1780
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/JetTrackParticleThinning.cxx
@@ -0,0 +1,177 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/////////////////////////////////////////////////////////////////
+// JetTrackParticleThinning.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Author: James Catmore (James.Catmore@cern.ch)
+// This is a trivial example of an implementation of a thinning tool
+// which removes all ID tracks which do not pass a user-defined cut
+
+#include "DerivationFrameworkInDet/JetTrackParticleThinning.h"
+#include "AthenaKernel/IThinningSvc.h"
+#include "ExpressionEvaluation/ExpressionParser.h"
+#include "ExpressionEvaluation/SGxAODProxyLoader.h"
+#include "ExpressionEvaluation/SGNTUPProxyLoader.h"
+#include "ExpressionEvaluation/MultipleProxyLoader.h"
+#include "xAODJet/JetContainer.h"
+#include "xAODTracking/TrackParticleContainer.h"
+#include <vector>
+#include <string>
+
+// Constructor
+DerivationFramework::JetTrackParticleThinning::JetTrackParticleThinning(const std::string& t,
+                                                                        const std::string& n,
+                                                                        const IInterface* p ) :
+AthAlgTool(t,n,p),
+m_thinningSvc("ThinningSvc",n),
+m_ntot(0),
+m_npass(0),
+m_jetSGKey(""),
+m_inDetSGKey("InDetTrackParticles"),
+m_selectionString(""),
+m_and(false)
+{
+    declareInterface<DerivationFramework::IThinningTool>(this);
+    declareProperty("ThinningService", m_thinningSvc);
+    declareProperty("JetKey", m_jetSGKey);
+    declareProperty("InDetTrackParticlesKey", m_inDetSGKey);
+    declareProperty("SelectionString", m_selectionString);
+    declareProperty("ApplyAnd", m_and);
+}
+
+// Destructor
+DerivationFramework::JetTrackParticleThinning::~JetTrackParticleThinning() {
+}
+
+// Athena initialize and finalize
+StatusCode DerivationFramework::JetTrackParticleThinning::initialize()
+{
+    // Decide which collections need to be checked for ID TrackParticles
+    ATH_MSG_VERBOSE("initialize() ...");
+    if (m_inDetSGKey=="") {
+        ATH_MSG_FATAL("No inner detector track collection provided for thinning.");
+        return StatusCode::FAILURE;
+    } else {ATH_MSG_INFO("Using " << m_inDetSGKey << "as the source collection for inner detector track particles");}
+    if (m_jetSGKey=="") {
+        ATH_MSG_FATAL("No jet collection provided for thinning.");
+        return StatusCode::FAILURE;
+    } else { ATH_MSG_INFO("Inner detector track particles associated with objects in " << m_jetSGKey << " will be retained in this format with the rest being thinned away");}
+    
+    // Set up the text-parsing machinery for selectiong the jet directly according to user cuts
+    if (m_selectionString!="") {
+	    ExpressionParsing::MultipleProxyLoader *proxyLoaders = new ExpressionParsing::MultipleProxyLoader();
+	    proxyLoaders->push_back(new ExpressionParsing::SGxAODProxyLoader(evtStore()));
+	    proxyLoaders->push_back(new ExpressionParsing::SGNTUPProxyLoader(evtStore()));
+	    m_parser = new ExpressionParsing::ExpressionParser(proxyLoaders);
+	    m_parser->loadExpression(m_selectionString);
+    }
+    return StatusCode::SUCCESS;
+}
+
+StatusCode DerivationFramework::JetTrackParticleThinning::finalize()
+{
+    ATH_MSG_VERBOSE("finalize() ...");
+    ATH_MSG_INFO("Processed "<< m_ntot <<" tracks, "<< m_npass<< " were retained ");
+    if (m_selectionString!="") {
+        delete m_parser;
+        m_parser = 0;
+    }
+    return StatusCode::SUCCESS;
+}
+
+// The thinning itself
+StatusCode DerivationFramework::JetTrackParticleThinning::doThinning() const
+{
+    
+    // Retrieve main TrackParticle collection
+    const xAOD::TrackParticleContainer* importedTrackParticles;
+    if (evtStore()->retrieve(importedTrackParticles,m_inDetSGKey).isFailure()) {
+        ATH_MSG_ERROR("No TrackParticle collection with name " << m_inDetSGKey << " found in StoreGate!");
+        return StatusCode::FAILURE;
+    }
+    
+    // Check the event contains tracks
+    unsigned int nTracks = importedTrackParticles->size();
+    if (nTracks==0) return StatusCode::SUCCESS;
+    
+    // Set up a mask with the same entries as the full TrackParticle collection
+    std::vector<bool> mask;
+    mask.assign(nTracks,false); // default: don't keep any tracks
+    m_ntot += nTracks;
+    
+    // Retrieve containers
+    // ... jets
+    const xAOD::JetContainer* importedJets(0);
+    if (evtStore()->retrieve(importedJets,m_jetSGKey).isFailure()) {
+        ATH_MSG_ERROR("No jet collection with name " << m_jetSGKey << " found in StoreGate!");
+        return StatusCode::FAILURE;
+    }
+    unsigned int nJets(importedJets->size());
+    std::vector<const xAOD::Jet*> jetToCheck; jetToCheck.clear();
+    
+    // Execute the text parser if requested
+    if (m_selectionString!="") {
+        std::vector<int> entries =  m_parser->evaluateAsVector();
+        unsigned int nEntries = entries.size();
+        // check the sizes are compatible
+        if (nJets != nEntries ) {
+        	ATH_MSG_ERROR("Sizes incompatible! Are you sure your selection string used jets??");
+            return StatusCode::FAILURE;
+        } else {
+        	// identify which jets to keep for the thinning check
+        	for (unsigned int i=0; i<nJets; ++i) if (entries[i]==1) jetToCheck.push_back((*importedJets)[i]);
+        }
+    }
+    
+    // Set elements in the mask to true if there is a corresponding ElementLink from a reconstructed object
+    // ... jets
+    if (m_selectionString=="") { // check all jets as user didn't provide a selection string
+        for (xAOD::JetContainer::const_iterator jetIt=importedJets->begin(); jetIt!=importedJets->end(); ++jetIt) {
+            std::vector<const xAOD::TrackParticle*> jetTracks;
+            bool haveJetTracks = (*jetIt)->getAssociatedObjects(xAOD::JetAttribute::GhostTrack, jetTracks);
+            if ( !haveJetTracks ) {ATH_MSG_WARNING("Associated tracks not found");}
+            else {
+                for (std::vector<const xAOD::TrackParticle*>::iterator jetTrIt=jetTracks.begin(); jetTrIt!=jetTracks.end(); ++jetTrIt) {
+                    int index = (*jetTrIt)->index();
+                    mask[index] = true;
+                }
+            }
+        }
+    } else { // check only jets passing user selection string
+    	for (std::vector<const xAOD::Jet*>::iterator jetIt = jetToCheck.begin(); jetIt!=jetToCheck.end(); ++jetIt) {
+            std::vector<const xAOD::TrackParticle*> jetTracks;
+            bool haveJetTracks = (*jetIt)->getAssociatedObjects(xAOD::JetAttribute::GhostTrack, jetTracks);
+            if ( !haveJetTracks ) {ATH_MSG_WARNING("Associated tracks not found");}
+            else {
+                for (std::vector<const xAOD::TrackParticle*>::iterator jetTrIt=jetTracks.begin(); jetTrIt!=jetTracks.end(); ++jetTrIt) {
+                    int index = (*jetTrIt)->index();
+                    mask[index] = true;
+                }
+            }
+        }
+    }
+    
+    // Count up the mask contents
+    for (unsigned int i=0; i<nTracks; ++i) {
+        if (mask[i]) ++m_npass;
+    }
+    
+    // Execute the thinning service based on the mask. Finish.
+    if (m_and) {
+        if (m_thinningSvc->filter(*importedTrackParticles, mask, IThinningSvc::Operator::And).isFailure()) {
+                ATH_MSG_ERROR("Application of thinning service failed! ");
+                return StatusCode::FAILURE;
+        }
+    }
+    if (!m_and) {
+        if (m_thinningSvc->filter(*importedTrackParticles, mask, IThinningSvc::Operator::Or).isFailure()) {
+                ATH_MSG_ERROR("Application of thinning service failed! ");
+                return StatusCode::FAILURE;
+        }
+    }
+
+    return StatusCode::SUCCESS;
+}
+
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/MuonTrackParticleThinning.cxx b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/MuonTrackParticleThinning.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..201b483268b090a262fd224c53490a64f144b207
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/MuonTrackParticleThinning.cxx
@@ -0,0 +1,167 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/////////////////////////////////////////////////////////////////
+// MuonTrackParticleThinning.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Author: James Catmore (James.Catmore@cern.ch)
+// This is a trivial example of an implementation of a thinning tool
+// which removes all ID tracks which do not pass a user-defined cut
+
+#include "DerivationFrameworkInDet/MuonTrackParticleThinning.h"
+#include "AthenaKernel/IThinningSvc.h"
+#include "ExpressionEvaluation/ExpressionParser.h"
+#include "ExpressionEvaluation/SGxAODProxyLoader.h"
+#include "ExpressionEvaluation/SGNTUPProxyLoader.h"
+#include "ExpressionEvaluation/MultipleProxyLoader.h"
+#include "xAODMuon/MuonContainer.h"
+#include "xAODTracking/TrackParticleContainer.h"
+#include <vector>
+#include <string>
+
+// Constructor
+DerivationFramework::MuonTrackParticleThinning::MuonTrackParticleThinning(const std::string& t,
+                                                                          const std::string& n,
+                                                                          const IInterface* p ) :
+AthAlgTool(t,n,p),
+m_thinningSvc("ThinningSvc",n),
+m_ntot(0),
+m_npass(0),
+m_muonSGKey(""),
+m_inDetSGKey("InDetTrackParticles"),
+m_selectionString(""),
+m_coneSize(-1.0),
+m_and(false)
+{
+    declareInterface<DerivationFramework::IThinningTool>(this);
+    declareProperty("ThinningService", m_thinningSvc);
+    declareProperty("MuonKey", m_muonSGKey);
+    declareProperty("InDetTrackParticlesKey", m_inDetSGKey);
+    declareProperty("SelectionString", m_selectionString);
+    declareProperty("ConeSize", m_coneSize);
+    declareProperty("ApplyAnd", m_and);
+}
+
+// Destructor
+DerivationFramework::MuonTrackParticleThinning::~MuonTrackParticleThinning() {
+}
+
+// Athena initialize and finalize
+StatusCode DerivationFramework::MuonTrackParticleThinning::initialize()
+{
+    // Decide which collections need to be checked for ID TrackParticles
+    ATH_MSG_VERBOSE("initialize() ...");
+    if (m_inDetSGKey=="") {
+        ATH_MSG_FATAL("No inner detector track collection provided for thinning.");
+        return StatusCode::FAILURE;
+    } else {ATH_MSG_INFO("Using " << m_inDetSGKey << "as the source collection for inner detector track particles");}
+    if (m_muonSGKey=="") {
+        ATH_MSG_FATAL("No muon collection provided for thinning.");
+        return StatusCode::FAILURE;
+    } else { ATH_MSG_INFO("Inner detector track particles associated with objects in " << m_muonSGKey << " will be retained in this format with the rest being thinned away");}
+   
+    // Set up the text-parsing machinery for selectiong the muon directly according to user cuts
+    if (m_selectionString!="") {
+	    ExpressionParsing::MultipleProxyLoader *proxyLoaders = new ExpressionParsing::MultipleProxyLoader();
+	    proxyLoaders->push_back(new ExpressionParsing::SGxAODProxyLoader(evtStore()));
+	    proxyLoaders->push_back(new ExpressionParsing::SGNTUPProxyLoader(evtStore()));
+	    m_parser = new ExpressionParsing::ExpressionParser(proxyLoaders);
+	    m_parser->loadExpression(m_selectionString);
+    }
+    return StatusCode::SUCCESS;
+}
+
+StatusCode DerivationFramework::MuonTrackParticleThinning::finalize()
+{
+    ATH_MSG_VERBOSE("finalize() ...");
+    ATH_MSG_INFO("Processed "<< m_ntot <<" tracks, "<< m_npass<< " were retained ");
+    if (m_selectionString!="") {
+        delete m_parser;
+        m_parser = 0;
+    }
+    return StatusCode::SUCCESS;
+}
+
+// The thinning itself
+StatusCode DerivationFramework::MuonTrackParticleThinning::doThinning() const
+{
+    // Retrieve main TrackParticle collection
+    const xAOD::TrackParticleContainer* importedTrackParticles;
+    if (evtStore()->retrieve(importedTrackParticles,m_inDetSGKey).isFailure()) {
+        ATH_MSG_ERROR("No TrackParticle collection with name " << m_inDetSGKey << " found in StoreGate!");
+        return StatusCode::FAILURE;
+    }
+    
+    // Check the event contains tracks
+    unsigned int nTracks = importedTrackParticles->size();
+    if (nTracks==0) return StatusCode::SUCCESS;
+    
+    // Set up a mask with the same entries as the full TrackParticle collection
+    std::vector<bool> mask;
+    mask.assign(nTracks,false); // default: don't keep any tracks
+    m_ntot += nTracks;
+    
+    // Retrieve containers
+    // ... muons
+    const xAOD::MuonContainer* importedMuons(0);
+    if (evtStore()->retrieve(importedMuons,m_muonSGKey).isFailure()) {
+        ATH_MSG_ERROR("No muon collection with name " << m_muonSGKey << " found in StoreGate!");
+        return StatusCode::FAILURE;
+    }
+    unsigned int nMuons(importedMuons->size());
+    std::vector<const xAOD::Muon*> muToCheck; muToCheck.clear();
+    // Execute the text parser if requested
+    if (m_selectionString!="") {
+        std::vector<int> entries =  m_parser->evaluateAsVector();
+        unsigned int nEntries = entries.size();
+        // check the sizes are compatible
+        if (nMuons != nEntries ) {
+        	ATH_MSG_ERROR("Sizes incompatible! Are you sure your selection string used muons??");
+            return StatusCode::FAILURE;
+        } else {
+        	// identify which muons to keep for the thinning check
+        	for (unsigned int i=0; i<nMuons; ++i) if (entries[i]==1) muToCheck.push_back((*importedMuons)[i]);
+        }
+    }
+
+    DerivationFramework::TracksInCone tInC;    
+    if (m_selectionString=="") { // check all muons as user didn't provide a selection string
+	    for (xAOD::MuonContainer::const_iterator muIt=importedMuons->begin(); muIt!=importedMuons->end(); ++muIt) {
+		if ((*muIt)->inDetTrackParticleLink().isValid()) {
+	        	int index = (*muIt)->inDetTrackParticleLink().index();
+	        	mask[index] = true;
+		}
+		if (m_coneSize>0.0) tInC.select(*muIt,m_coneSize,importedTrackParticles,mask); // check tracks in a cone around the muon if req'd
+	    }
+    } else { // check only muons passing user selection string
+        for (std::vector<const xAOD::Muon*>::iterator muIt = muToCheck.begin(); muIt!=muToCheck.end(); ++muIt) {
+	    if ((*muIt)->inDetTrackParticleLink().isValid()) {
+            	int index = (*muIt)->inDetTrackParticleLink().index();
+            	mask[index] = true;
+	    } 	
+	    if (m_coneSize>0.0) tInC.select(*muIt,m_coneSize,importedTrackParticles,mask); // check tracks in a cone around the muon if req'd	
+        }
+    }
+    
+    // Count up the mask contents
+    for (unsigned int i=0; i<nTracks; ++i) {
+        if (mask[i]) ++m_npass;
+    }
+    // Execute the thinning service based on the mask. Finish.
+    if (m_and) {
+        if (m_thinningSvc->filter(*importedTrackParticles, mask, IThinningSvc::Operator::And).isFailure()) {
+                ATH_MSG_ERROR("Application of thinning service failed! ");
+                return StatusCode::FAILURE;
+        }
+    }
+    if (!m_and) {
+        if (m_thinningSvc->filter(*importedTrackParticles, mask, IThinningSvc::Operator::Or).isFailure()) {
+                ATH_MSG_ERROR("Application of thinning service failed! ");
+                return StatusCode::FAILURE;
+        }
+    }
+
+    return StatusCode::SUCCESS;
+}
+
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/TauTrackParticleThinning.cxx b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/TauTrackParticleThinning.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..a7fb17ba9525a20833ccb87c4d101cd3fd14b3df
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/TauTrackParticleThinning.cxx
@@ -0,0 +1,172 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/////////////////////////////////////////////////////////////////
+// TauTrackParticleThinning.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Author: James Catmore (James.Catmore@cern.ch)
+// This is a trivial example of an implementation of a thinning tool
+// which removes all ID tracks which do not pass a user-defined cut
+
+#include "DerivationFrameworkInDet/TauTrackParticleThinning.h"
+#include "AthenaKernel/IThinningSvc.h"
+#include "ExpressionEvaluation/ExpressionParser.h"
+#include "ExpressionEvaluation/SGxAODProxyLoader.h"
+#include "ExpressionEvaluation/MultipleProxyLoader.h"
+#include "ExpressionEvaluation/SGNTUPProxyLoader.h"
+#include "xAODTau/TauJetContainer.h"
+#include "xAODTracking/TrackParticleContainer.h"
+#include <vector>
+#include <string>
+
+// Constructor
+DerivationFramework::TauTrackParticleThinning::TauTrackParticleThinning(const std::string& t,
+                                                                        const std::string& n,
+                                                                        const IInterface* p ) :
+AthAlgTool(t,n,p),
+m_thinningSvc("ThinningSvc",n),
+m_ntot(0),
+m_npass(0),
+m_tauSGKey(""),
+m_inDetSGKey("InDetTrackParticles"),
+m_selectionString(""),
+m_coneSize(-1.0),
+m_and(false)
+{
+    declareInterface<DerivationFramework::IThinningTool>(this);
+    declareProperty("ThinningService", m_thinningSvc);
+    declareProperty("TauKey", m_tauSGKey);
+    declareProperty("InDetTrackParticlesKey", m_inDetSGKey);
+    declareProperty("SelectionString", m_selectionString);
+    declareProperty("ConeSize", m_coneSize);
+    declareProperty("ApplyAnd", m_and);
+}
+
+// Destructor
+DerivationFramework::TauTrackParticleThinning::~TauTrackParticleThinning() {
+}
+
+// Athena initialize and finalize
+StatusCode DerivationFramework::TauTrackParticleThinning::initialize()
+{
+    // Decide which collections need to be checked for ID TrackParticles
+    ATH_MSG_VERBOSE("initialize() ...");
+    if (m_inDetSGKey=="") {
+        ATH_MSG_FATAL("No inner detector track collection provided for thinning.");
+        return StatusCode::FAILURE;
+    } else {ATH_MSG_INFO("Using " << m_inDetSGKey << "as the source collection for inner detector track particles");}
+    if (m_tauSGKey=="") {
+        ATH_MSG_FATAL("No tau collection provided for thinning.");
+        return StatusCode::FAILURE;
+    } else { ATH_MSG_INFO("Inner detector track particles associated with objects in " << m_tauSGKey << " will be retained in this format with the rest being thinned away");}
+    
+    // Set up the text-parsing machinery for selectiong the tau directly according to user cuts
+    if (m_selectionString!="") {
+	    ExpressionParsing::MultipleProxyLoader *proxyLoaders = new ExpressionParsing::MultipleProxyLoader();
+	    proxyLoaders->push_back(new ExpressionParsing::SGxAODProxyLoader(evtStore()));
+	    proxyLoaders->push_back(new ExpressionParsing::SGNTUPProxyLoader(evtStore()));
+	    m_parser = new ExpressionParsing::ExpressionParser(proxyLoaders);
+	    m_parser->loadExpression(m_selectionString);
+    }
+    return StatusCode::SUCCESS;
+}
+
+StatusCode DerivationFramework::TauTrackParticleThinning::finalize()
+{
+    ATH_MSG_VERBOSE("finalize() ...");
+    ATH_MSG_INFO("Processed "<< m_ntot <<" tracks, "<< m_npass<< " were retained ");
+    if (m_selectionString!="") {
+        delete m_parser;
+        m_parser = 0;
+    }
+    return StatusCode::SUCCESS;
+}
+
+// The thinning itself
+StatusCode DerivationFramework::TauTrackParticleThinning::doThinning() const
+{
+    
+    // Retrieve main TrackParticle collection
+    const xAOD::TrackParticleContainer* importedTrackParticles;
+    if (evtStore()->retrieve(importedTrackParticles,m_inDetSGKey).isFailure()) {
+        ATH_MSG_ERROR("No TrackParticle collection with name " << m_inDetSGKey << " found in StoreGate!");
+        return StatusCode::FAILURE;
+    }
+    
+    // Check the event contains tracks
+    unsigned int nTracks = importedTrackParticles->size();
+    if (nTracks==0) return StatusCode::SUCCESS;
+    
+    // Set up a mask with the same entries as the full TrackParticle collection
+    std::vector<bool> mask;
+    mask.assign(nTracks,false); // default: don't keep any tracks
+    m_ntot += nTracks;
+    
+    // Retrieve containers
+    // ... taus
+    const xAOD::TauJetContainer* importedTaus(0);
+    if (evtStore()->retrieve(importedTaus,m_tauSGKey).isFailure()) {
+        ATH_MSG_ERROR("No tau collection with name " << m_tauSGKey << " found in StoreGate!");
+        return StatusCode::FAILURE;
+    }
+    unsigned int nTaus(importedTaus->size());
+    std::vector<const xAOD::TauJet*> tauToCheck; tauToCheck.clear();
+    
+    // Execute the text parser if requested
+    if (m_selectionString!="") {
+        std::vector<int> entries =  m_parser->evaluateAsVector();
+        unsigned int nEntries = entries.size();
+        // check the sizes are compatible
+        if (nTaus != nEntries ) {
+        	ATH_MSG_ERROR("Sizes incompatible! Are you sure your selection string used taus??");
+            return StatusCode::FAILURE;
+        } else {
+        	// identify which taus to keep for the thinning check
+        	for (unsigned int i=0; i<nTaus; ++i) if (entries[i]==1) tauToCheck.push_back((*importedTaus)[i]);
+        }
+    }
+    
+    // Set elements in the mask to true if there is a corresponding ElementLink from a reconstructed object
+    // ... taus
+    DerivationFramework::TracksInCone trIC;
+    if (m_selectionString=="") { // check all taus as user didn't provide a selection string
+	    for (xAOD::TauJetContainer::const_iterator tauIt=importedTaus->begin(); tauIt!=importedTaus->end(); ++tauIt) {
+		if (m_coneSize>0.0) trIC.select(*tauIt,m_coneSize,importedTrackParticles,mask); // check tracks in a cone around the tau if req'd
+            	for (unsigned int i=0; i<(*tauIt)->nTracks(); ++i) {
+                	int index = (*tauIt)->trackLinks().at(i).index();
+                	mask[index] = true;
+            	}
+	    }
+    } else { // check only taus passing user selection string
+        for (std::vector<const xAOD::TauJet*>::iterator tauIt = tauToCheck.begin(); tauIt!=tauToCheck.end(); ++tauIt) {
+	    if (m_coneSize>0.0) trIC.select(*tauIt,m_coneSize,importedTrackParticles,mask); // check tracks in a cone around the tau if req'd	
+            for (unsigned int i=0; i<(*tauIt)->nTracks(); ++i) {
+                int index = (*tauIt)->trackLinks().at(i).index();
+                mask[index] = true;
+            }
+        }
+    }
+    
+    // Count up the mask contents
+    for (unsigned int i=0; i<nTracks; ++i) {
+        if (mask[i]) ++m_npass;
+    }
+    
+    // Execute the thinning service based on the mask. Finish.
+    if (m_and) {
+        if (m_thinningSvc->filter(*importedTrackParticles, mask, IThinningSvc::Operator::And).isFailure()) {
+                ATH_MSG_ERROR("Application of thinning service failed! ");
+                return StatusCode::FAILURE;
+        }
+    }
+    if (!m_and) {
+        if (m_thinningSvc->filter(*importedTrackParticles, mask, IThinningSvc::Operator::Or).isFailure()) {
+                ATH_MSG_ERROR("Application of thinning service failed! ");
+                return StatusCode::FAILURE;
+        }
+    }
+
+    return StatusCode::SUCCESS;
+}
+
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/TrackParametersAtPV.cxx b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/TrackParametersAtPV.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..329c57e5fe89d3418fee6197bfcd24fa5fd59b3c
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/TrackParametersAtPV.cxx
@@ -0,0 +1,112 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// TrackParametersAtPV.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Author: Tomoe Kishimoto (Tomoe.Kishimoto@cern.ch)
+// Wrapper around the passSelection() method of xAOD egamma
+// Writes result to SG for later selection by string parser
+
+#include "DerivationFrameworkInDet/TrackParametersAtPV.h"
+#include "xAODTracking/TrackParticleContainer.h"
+#include "xAODTracking/VertexContainer.h"
+#include <vector>
+#include <string>
+
+// Constructor
+DerivationFramework::TrackParametersAtPV::TrackParametersAtPV( const std::string& t,
+                                                 const std::string& n,
+                                                 const IInterface* p ) :
+  AthAlgTool(t,n,p),
+  m_collTrackName("InDetTrackParticles"),
+  m_collVertexName("PrimaryVertices"),
+  m_sgKey1("")
+  {
+    declareInterface<DerivationFramework::IAugmentationTool>(this);
+    declareProperty("TrackParticleContainerName", m_collTrackName);
+    declareProperty("VertexContainerName", m_collVertexName);
+    declareProperty("Z0SGEntryName", m_sgKey1);
+  }
+ 
+// Destructor
+DerivationFramework::TrackParametersAtPV::~TrackParametersAtPV() {
+} 
+
+// Athena initialize and finalize
+StatusCode DerivationFramework::TrackParametersAtPV::initialize()
+{
+  if (m_collTrackName == "" || m_collVertexName == "") {
+    ATH_MSG_ERROR("No selection variables for the HIGGS3 selection wrapper tool!");
+    return StatusCode::FAILURE;
+  }
+  
+  if (m_sgKey1 == "") {
+    ATH_MSG_ERROR("No Store Gate Keys for the HIGGS3 selection wrapper tool!");
+    return StatusCode::FAILURE;
+  }
+  
+  ATH_MSG_VERBOSE("initialize() ...");
+  return StatusCode::SUCCESS;
+}
+
+StatusCode DerivationFramework::TrackParametersAtPV::finalize()
+{
+  ATH_MSG_VERBOSE("finalize() ...");
+  return StatusCode::SUCCESS;
+}
+
+// Augmentation
+StatusCode DerivationFramework::TrackParametersAtPV::addBranches() const
+{
+  std::vector<float> *track_z0_PV = new std::vector<float>();
+
+  // Get Primary vertex
+  const xAOD::VertexContainer* vertices = 
+    evtStore()->retrieve< const xAOD::VertexContainer >(m_collVertexName);
+    
+  if(!vertices) {
+    ATH_MSG_ERROR ("Couldn't retrieve VertexContainer with key: " << m_collVertexName);
+    return StatusCode::FAILURE;
+  }
+
+  const xAOD::Vertex* pv(0);
+  for (const xAOD::Vertex* vx : *vertices) {
+    if (vx->vertexType() == xAOD::VxType::PriVtx) {
+      pv = vx;
+      break;
+    }
+  }
+
+  // Get the track container
+  const xAOD::TrackParticleContainer* tracks = 
+    evtStore()->retrieve< const xAOD::TrackParticleContainer >(m_collTrackName);
+  
+  if(!tracks) {
+    ATH_MSG_ERROR ("Couldn't retrieve TrackParticleContainer with key: " << m_collTrackName);
+    return StatusCode::FAILURE;
+  }
+
+  // Get track z0 w.r.t PV
+  for (xAOD::TrackParticleContainer::const_iterator trackIt=tracks->begin(); trackIt!=tracks->end(); ++trackIt) {
+    if (pv) {
+      float z0wrtPV = (*trackIt)->z0() + (*trackIt)->vz() - pv->z();
+      track_z0_PV->push_back(z0wrtPV);
+
+    } else {
+      track_z0_PV->push_back(999.);
+    }
+  }
+
+  // Write decision to SG for access by downstream algs 
+  if (evtStore()->contains<std::vector<float> >(m_sgKey1)) {
+      ATH_MSG_ERROR("Tool is attempting to write StoreGate keys which already exists. Please use a different key");
+      return StatusCode::FAILURE;
+  } else {
+    CHECK(evtStore()->record(track_z0_PV, m_sgKey1));       
+  }
+
+  return StatusCode::SUCCESS;
+}
+
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/TrackParametersForTruthParticles.cxx b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/TrackParametersForTruthParticles.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..6e39607243a1cf4c289ba31d1137f766e76dbcd9
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/TrackParametersForTruthParticles.cxx
@@ -0,0 +1,79 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// TrackParametersForTruthParticles.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Author: Tomoe Kishimoto (Tomoe.Kishimoto@cern.ch)
+// Wrapper around the passSelection() method of xAOD egamma
+// Writes result to SG for later selection by string parser
+
+#include "DerivationFrameworkInDet/TrackParametersForTruthParticles.h"
+#include "xAODTruth/TruthParticleContainer.h"
+#include <vector>
+#include <string>
+
+#include "InDetPhysValMonitoring/IInDetPhysValDecoratorTool.h"
+
+// Constructor
+DerivationFramework::TrackParametersForTruthParticles::TrackParametersForTruthParticles( const std::string& t,
+                                                 const std::string& n,
+                                                 const IInterface* p ) :
+  AthAlgTool(t,n,p),
+  m_collTruthName("TruthParticle"),
+  m_sgKey1(""),
+  m_decoTool("InDetPhysValTruthDecoratorTool")
+	{
+    declareInterface<DerivationFramework::IAugmentationTool>(this);
+    declareProperty("TruthParticleContainerName", m_collTruthName);
+    declareProperty("DecorationPrefix",m_sgKey1);
+    declareProperty("PtCut",m_ptCut = 400);
+    declareProperty("OnlyDressPrimaryTracks", m_doPrimary = true);
+  }
+ 
+// Destructor
+DerivationFramework::TrackParametersForTruthParticles::~TrackParametersForTruthParticles() {
+} 
+
+// Athena initialize and finalize
+StatusCode DerivationFramework::TrackParametersForTruthParticles::initialize()
+{
+  
+  ATH_MSG_VERBOSE("initialize() ...");
+  
+	ATH_CHECK(m_decoTool.retrieve());
+
+	return StatusCode::SUCCESS;
+}
+
+StatusCode DerivationFramework::TrackParametersForTruthParticles::finalize()
+{
+  ATH_MSG_VERBOSE("finalize() ...");
+  return StatusCode::SUCCESS;
+}
+
+// Augmentation
+StatusCode DerivationFramework::TrackParametersForTruthParticles::addBranches() const
+{
+
+  // Get the track container
+  const xAOD::TruthParticleContainer* tracks = 
+    evtStore()->retrieve< const xAOD::TruthParticleContainer >(m_collTruthName);
+  
+  if(!tracks) {
+    ATH_MSG_ERROR ("Couldn't retrieve TrackParticleContainer with key: " << m_collTruthName);
+    return StatusCode::FAILURE;
+  }
+
+  for ( const auto truth: *tracks) {
+		if( truth->status() != 1 || truth->charge() == 0 ) continue;   
+		if( m_doPrimary && truth->barcode() > 200e3 ) continue;
+    if( truth->pt() < m_ptCut ) continue;
+    m_decoTool->decorateTruth(*truth, m_sgKey1);
+	}
+
+
+  return StatusCode::SUCCESS;
+}
+
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/TrackParticleThinning.cxx b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/TrackParticleThinning.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..6737f6f7ab610ca8c58401ae03648dde819eff68
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/TrackParticleThinning.cxx
@@ -0,0 +1,134 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/////////////////////////////////////////////////////////////////
+// TrackParticleThinning.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Author: James Catmore (James.Catmore@cern.ch)
+// Removes all ID tracks which do not pass a user-defined cut
+
+#include "DerivationFrameworkInDet/TrackParticleThinning.h"
+#include "AthenaKernel/IThinningSvc.h"
+#include "ExpressionEvaluation/ExpressionParser.h"
+#include "ExpressionEvaluation/SGxAODProxyLoader.h"
+#include "ExpressionEvaluation/SGNTUPProxyLoader.h"
+#include "ExpressionEvaluation/MultipleProxyLoader.h"
+#include "xAODTracking/TrackParticleContainer.h"
+#include <vector>
+#include <string>
+
+// Constructor
+DerivationFramework::TrackParticleThinning::TrackParticleThinning(const std::string& t,
+                                                                  const std::string& n,
+                                                                  const IInterface* p ) :
+AthAlgTool(t,n,p),
+m_thinningSvc("ThinningSvc",n),
+m_ntot(0),
+m_npass(0),
+m_inDetSGKey("InDetTrackParticles"),
+m_selectionString(""),
+m_and(false)
+{
+    declareInterface<DerivationFramework::IThinningTool>(this);
+    declareProperty("ThinningService", m_thinningSvc);
+    declareProperty("InDetTrackParticlesKey", m_inDetSGKey);
+    declareProperty("SelectionString", m_selectionString);
+    declareProperty("ApplyAnd", m_and);
+}
+
+// Destructor
+DerivationFramework::TrackParticleThinning::~TrackParticleThinning() {
+}
+
+// Athena initialize and finalize
+StatusCode DerivationFramework::TrackParticleThinning::initialize()
+{
+    ATH_MSG_VERBOSE("initialize() ...");
+    if (m_inDetSGKey=="") {
+        ATH_MSG_FATAL("No inner detector track collection provided for thinning.");
+        return StatusCode::FAILURE;
+    } else {ATH_MSG_INFO("Using " << m_inDetSGKey << "as the source collection for inner detector track particles");}
+    
+    if (m_selectionString=="") {
+        ATH_MSG_FATAL("No inner detector track selection string provided!");
+        return StatusCode::FAILURE;
+    } else {ATH_MSG_INFO("Track thinning selection string: " << m_selectionString);}
+    
+    // Set up the text-parsing machinery for thinning the tracks directly according to user cuts
+    if (m_selectionString!="") {
+	    ExpressionParsing::MultipleProxyLoader *proxyLoaders = new ExpressionParsing::MultipleProxyLoader();
+	    proxyLoaders->push_back(new ExpressionParsing::SGxAODProxyLoader(evtStore()));
+	    proxyLoaders->push_back(new ExpressionParsing::SGNTUPProxyLoader(evtStore()));
+	    m_parser = new ExpressionParsing::ExpressionParser(proxyLoaders);
+	    m_parser->loadExpression(m_selectionString);
+    }
+    return StatusCode::SUCCESS;
+}
+
+StatusCode DerivationFramework::TrackParticleThinning::finalize()
+{
+    ATH_MSG_VERBOSE("finalize() ...");
+    ATH_MSG_INFO("Processed "<< m_ntot <<" tracks, "<< m_npass<< " were retained ");
+    if (m_parser) {
+        delete m_parser;
+        m_parser = 0;
+    }
+    return StatusCode::SUCCESS;
+}
+
+// The thinning itself
+StatusCode DerivationFramework::TrackParticleThinning::doThinning() const
+{
+    
+    // Retrieve main TrackParticle collection
+    const xAOD::TrackParticleContainer* importedTrackParticles;
+    if (evtStore()->retrieve(importedTrackParticles,m_inDetSGKey).isFailure()) {
+        ATH_MSG_ERROR("No TrackParticle collection with name " << m_inDetSGKey << " found in StoreGate!");
+        return StatusCode::FAILURE;
+    }
+    
+    // Check the event contains tracks
+    unsigned int nTracks = importedTrackParticles->size();
+    if (nTracks==0) return StatusCode::SUCCESS;
+    
+    // Set up a mask with the same entries as the full TrackParticle collection
+    std::vector<bool> mask;
+    mask.assign(nTracks,false); // default: don't keep any tracks
+    m_ntot += nTracks;
+    
+    // Execute the text parser and update the mask
+    if (m_parser) {
+    	std::vector<int> entries =  m_parser->evaluateAsVector();
+    	unsigned int nEntries = entries.size();
+    	// check the sizes are compatible
+    	if (nTracks != nEntries ) {
+    		ATH_MSG_ERROR("Sizes incompatible! Are you sure your selection string used ID TrackParticles?");
+            return StatusCode::FAILURE;
+    	} else {
+            // set mask
+            for (unsigned int i=0; i<nTracks; ++i) if (entries[i]==1) mask[i]=true;
+    	}
+    }
+    // Count the mask
+    for (unsigned int i=0; i<nTracks; ++i) {
+        if (mask[i]) ++m_npass;
+    }
+    
+    // Execute the thinning service based on the mask. Finish.
+    if (m_and) { 
+    	if (m_thinningSvc->filter(*importedTrackParticles, mask, IThinningSvc::Operator::And).isFailure()) {
+        	ATH_MSG_ERROR("Application of thinning service failed! ");
+        	return StatusCode::FAILURE;
+    	}
+    }
+    if (!m_and) {
+        if (m_thinningSvc->filter(*importedTrackParticles, mask, IThinningSvc::Operator::Or).isFailure()) {
+                ATH_MSG_ERROR("Application of thinning service failed! ");
+                return StatusCode::FAILURE;
+        }
+    }
+    
+    return StatusCode::SUCCESS;
+}
+
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/TrackStateOnSurfaceDecorator.cxx b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/TrackStateOnSurfaceDecorator.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..750fd4828ccf58d53284a671023c8cf06892fbdf
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/TrackStateOnSurfaceDecorator.cxx
@@ -0,0 +1,487 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// TrackStateOnSurfaceDecorator.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Author:Anthony Morley
+//
+
+#include "DerivationFrameworkInDet/TrackStateOnSurfaceDecorator.h"
+#include "xAODTracking/TrackParticleContainer.h"
+#include "xAODTracking/TrackMeasurementValidationContainer.h"
+
+#include "xAODTracking/TrackStateValidationContainer.h"
+#include "xAODTracking/TrackStateValidationAuxContainer.h"
+
+
+#include "TrkTrack/TrackStateOnSurface.h"
+#include "TrkEventPrimitives/TrackStateDefs.h"
+#include "TrkParameters/TrackParameters.h"
+
+#include "AtlasDetDescr/AtlasDetectorID.h"
+#include "InDetIdentifier/PixelID.h"
+#include "InDetIdentifier/SCT_ID.h"
+#include "InDetIdentifier/TRT_ID.h"
+#include "TrkPrepRawData/PrepRawData.h"
+
+#include "TrkRIO_OnTrack/RIO_OnTrack.h"
+#include "TrkCompetingRIOsOnTrack/CompetingRIOsOnTrack.h"
+
+#include "TrkToolInterfaces/IResidualPullCalculator.h"
+#include "TrkEventPrimitives/ResidualPull.h"
+
+#include "TRT_ConditionsServices/ITRT_CalDbSvc.h"
+
+#include "xAODEventInfo/EventInfo.h"
+#include "CommissionEvent/ComTime.h"
+
+#include "InDetReadoutGeometry/SiDetectorElement.h"
+
+
+#include <vector>
+#include <string>
+
+namespace DerivationFramework {
+
+  TrackStateOnSurfaceDecorator::TrackStateOnSurfaceDecorator(const std::string& t,
+      const std::string& n,
+      const IInterface* p) : 
+    AthAlgTool(t,n,p),
+    m_sgName(""),
+    m_containerName(""),
+    m_pixelMapName("PixelClustersOffsets"),
+    m_sctMapName("SCT_ClustersOffsets"),
+    m_trtMapName("TRT_DriftCirclesOffsets"),
+    m_pixelClustersName("PixelClusters"),
+    m_sctClustersName("SCT_Clusters"),
+    m_trtDCName("TRT_DriftCircles"),
+    m_pixelMsosName("PixelMSOSs"),
+    m_sctMsosName("SCT_MSOSs"),
+    m_trtMsosName("TRT_MSOSs"),
+    m_residualPullCalculator("Trk::ResidualPullCalculator/ResidualPullCalculator"),
+    m_trtcaldbSvc("TRT_CalDbSvc",n)  
+  {
+    declareInterface<DerivationFramework::IAugmentationTool>(this);
+    declareProperty("DecorationPrefix",       m_sgName);
+    declareProperty("ContainerName",          m_containerName);
+    declareProperty("PixelMapName",           m_pixelMapName);
+    declareProperty("SctMapName",             m_sctMapName);
+    declareProperty("TrtMapName",             m_trtMapName);
+    declareProperty("PixelClustersName",      m_pixelClustersName);
+    declareProperty("SctClustersName",        m_sctClustersName);
+    declareProperty("TrtDriftCirclesName",    m_trtDCName);
+    declareProperty("PixelMsosName",          m_pixelMsosName);
+    declareProperty("SctMsosName",            m_sctMsosName);
+    declareProperty("TrtMsosName",            m_trtMsosName);    
+    declareProperty("ResidualPullCalculator", m_residualPullCalculator);
+    declareProperty("TRT_CalDbSvc",           m_trtcaldbSvc);
+    declareProperty("StoreHoles",             m_storeHoles =true);
+    declareProperty("StoreOutliers",          m_storeOutliers = true);
+    declareProperty("StoreTRT",               m_storeTRT =false);
+    declareProperty("StoreSCT",               m_storeSCT = true);
+    declareProperty("StorePixel",             m_storePixel =true);
+    declareProperty("AddPulls",               m_addPulls =true);
+    declareProperty("AddSurfaceInfo",         m_addSurfaceInfo =true);
+    declareProperty("AddPRD",                 m_addPRD =true);
+    declareProperty("AddExtraEventInfo",      m_addExtraEventInfo=true);
+  }
+
+  StatusCode TrackStateOnSurfaceDecorator::initialize()
+  {
+    if (m_sgName=="") {
+      ATH_MSG_WARNING("No decoration prefix name provided for the output of TrackStateOnSurfaceDecorator!");
+    }
+    
+    if (m_containerName=="") {
+      ATH_MSG_ERROR("No TrackParticle collection provided for TrackStateOnSurfaceDecorator!");
+      return StatusCode::FAILURE;
+    }
+
+    // need Atlas id-helpers to identify sub-detectors, take them from detStore
+    if (detStore()->retrieve(m_idHelper, "AtlasID").isFailure()) {
+      ATH_MSG_ERROR("Could not get AtlasDetectorID helper");
+      return StatusCode::FAILURE;
+    }   
+
+    if( m_storePixel && detStore()->retrieve(m_pixId,"PixelID").isFailure() ){
+      ATH_MSG_ERROR("Unable to retrieve pixel ID helper");
+      return StatusCode::FAILURE;
+    }
+
+    if( m_storeSCT && detStore()->retrieve(m_sctId,"SCT_ID").isFailure() ){
+      ATH_MSG_ERROR("Could not retrieve SCT helper");
+      return StatusCode::FAILURE; 
+    } 
+
+    if( m_storeTRT && detStore()->retrieve(m_trtId,"TRT_ID").isFailure() ){
+      ATH_MSG_ERROR("Could not retrieve TRT helper");
+      return StatusCode::FAILURE; 
+    } 
+    
+    if( m_storeTRT){
+      CHECK(m_trtcaldbSvc.retrieve());
+    }
+
+    if( m_addPulls ){
+      CHECK(m_residualPullCalculator.retrieve());
+    }
+    
+    return StatusCode::SUCCESS;
+  }
+
+  StatusCode TrackStateOnSurfaceDecorator::finalize()
+  {
+    return StatusCode::SUCCESS;
+  }
+
+  StatusCode TrackStateOnSurfaceDecorator::addBranches() const
+  {
+    ATH_MSG_DEBUG("Adding TSOS branches the track particles");
+
+    static SG::AuxElement::Decorator< std::vector< ElementLink< xAOD::TrackStateValidationContainer > > >  dectsos_msosLink(m_sgName+"_msosLink");
+
+
+
+    // retrieve track container
+    const xAOD::TrackParticleContainer* tracks=0;
+    CHECK( evtStore()->retrieve( tracks, m_containerName ) );
+    if( ! tracks ) {
+        ATH_MSG_ERROR ("Couldn't retrieve TrackParticles with key: " << m_containerName );
+        return StatusCode::FAILURE;
+    }
+    
+    
+    const std::vector<unsigned int>*  pixelClusterOffsets(0);
+    const std::vector<unsigned int>*  sctClusterOffsets(0);
+    const std::vector<unsigned int>*  trtClusterOffsets(0);
+    
+    const xAOD::TrackMeasurementValidationContainer* pixelClusters(0);
+    const xAOD::TrackMeasurementValidationContainer* sctClusters(0);
+    const xAOD::TrackMeasurementValidationContainer* trtDCs(0);
+ 
+    
+    // Create the xAOD container and its auxiliary store
+    xAOD::TrackStateValidationContainer*    msosPixel=0; 
+    xAOD::TrackStateValidationContainer*    msosSCT=0; 
+    xAOD::TrackStateValidationContainer*    msosTRT=0;
+
+    int nPixelMSOS(0);
+    int nSCT_MSOS(0);
+    int nTRT_MSOS(0);
+     
+
+    //Add event-level information
+    if (m_addExtraEventInfo) {
+      const xAOD::EventInfo* eventInfo = 0;
+      if (evtStore()->retrieve(eventInfo).isFailure()) {
+        ATH_MSG_ERROR(" Cannot access to event info.");
+        return StatusCode::FAILURE;
+      }
+
+      //Add TRT event phase
+      const ComTime *trtPhase = 0;
+      float trtPhase_time=0.0;
+      if ( evtStore()->contains<ComTime>("TRT_Phase") ){
+        StatusCode sc = evtStore()->retrieve(trtPhase, "TRT_Phase");  
+        if (sc.isFailure() || !trtPhase) {
+          //do not throw errors, since it could not be there
+          ATH_MSG_DEBUG("Failed to retrieve TRT phase information.");
+        } else {
+          trtPhase_time = trtPhase->getTime();
+        } 
+      } //TRT phase
+      eventInfo->auxdecor<float>(m_sgName+"_TrtPhaseTime") = trtPhase_time;
+      
+    } //extra event info
+
+    
+    if(m_addPRD){
+      // Get clusters and the mapping between xAOD::PRD and Trk::PRD
+      // Store the MSOS's in a conatiner based on the type of the detector 
+      if(m_storePixel){
+        CHECK( evtStore()->retrieve( pixelClusterOffsets, m_pixelMapName ) );
+        CHECK( evtStore()->retrieve( pixelClusters, m_pixelClustersName ) );
+      
+        msosPixel = new xAOD::TrackStateValidationContainer();
+        xAOD::TrackStateValidationAuxContainer* aux = new xAOD::TrackStateValidationAuxContainer();
+        CHECK( evtStore()->record( msosPixel, m_pixelMsosName ) );
+        CHECK( evtStore()->record( aux, m_pixelMsosName + "Aux." ) );
+        msosPixel->setStore( aux );
+      }
+      if(m_storeSCT){
+        CHECK( evtStore()->retrieve( sctClusterOffsets, m_sctMapName ) );
+        CHECK( evtStore()->retrieve( sctClusters, m_sctClustersName ) );
+
+        msosSCT = new xAOD::TrackStateValidationContainer();
+        xAOD::TrackStateValidationAuxContainer* aux = new xAOD::TrackStateValidationAuxContainer();
+        CHECK( evtStore()->record( msosSCT, m_sctMsosName ) );
+        CHECK( evtStore()->record( aux, m_sctMsosName + "Aux." ) );
+        msosSCT->setStore( aux );
+      }
+      if(m_storeTRT){
+        CHECK( evtStore()->retrieve( trtClusterOffsets, m_trtMapName ) );    
+        CHECK( evtStore()->retrieve( trtDCs, m_trtDCName ) );
+
+        msosTRT = new xAOD::TrackStateValidationContainer();
+        xAOD::TrackStateValidationAuxContainer* aux = new xAOD::TrackStateValidationAuxContainer();
+        CHECK( evtStore()->record( msosTRT, m_trtMsosName ) );
+        CHECK( evtStore()->record( aux, m_trtMsosName + "Aux." ) );
+        msosTRT->setStore( aux );
+      }
+    }
+    
+    
+    // Run tool for each element and calculate the impact parameters/errors 
+    for (const auto& track : *tracks) {
+
+      if( !track->trackLink().isValid() || track->track() == 0 ) {
+        ATH_MSG_WARNING("Track particle without Trk::Track");
+        continue;
+      }
+      ATH_MSG_DEBUG("We have a Trk::Track");
+
+      //  This is the vector in which we will store the element links to the MSOS's
+      std::vector< ElementLink< xAOD::TrackStateValidationContainer > > msosLink;
+
+      // We now have a valid Trk::Track
+      const Trk::Track* trkTrack = track->track();
+
+      //Loop over the TrkStateOnSurfaces
+      for (const auto& trackState: *(trkTrack->trackStateOnSurfaces())){
+
+        //Only store Holes, Measurement &  Outliers 
+        if( !trackState->types()[Trk::TrackStateOnSurface::Hole] && 
+            !trackState->types()[Trk::TrackStateOnSurface::Measurement] &&
+            !trackState->types()[Trk::TrackStateOnSurface::Outlier] ) {
+          continue;
+        }
+
+        // Check if we want to store this types of TSOS
+        if(!m_storeOutliers && trackState->types()[Trk::TrackStateOnSurface::Outlier] )
+          continue;
+
+
+        if(!m_storeHoles && trackState->types()[Trk::TrackStateOnSurface::Hole] )
+          continue;
+
+        // Check that the surface has detector element
+        if(!trackState->surface().associatedDetectorElement()){
+          continue;
+        }
+
+        // Check that the surface ID is valid
+        Identifier surfaceID = trackState->surface().associatedDetectorElement()->identify();
+        if( !surfaceID.is_valid() ){
+          ATH_MSG_WARNING("Invalid surface ID");
+          continue;
+        }
+
+        //Determine what detector the hit is in
+        bool isPixel(false); 
+        bool isSCT(false);  
+        bool isTRT(false);  
+      
+        if( m_idHelper->is_trt(surfaceID) ){
+          isTRT = true;
+          if(!m_storeTRT)
+            continue;
+        }else if( m_idHelper->is_sct(surfaceID) ){
+          isSCT = true;
+          if(!m_storeSCT)
+            continue;
+        }else if( m_idHelper->is_pixel(surfaceID) ){
+          isPixel = true; 
+          if(!m_storePixel)
+            continue;
+        } 
+        
+        if( !isPixel && !isSCT && !isTRT ){
+          continue;
+        } 
+         
+        //Create new MSOS to fill with information
+        xAOD::TrackStateValidation*  msos =  new xAOD::TrackStateValidation();
+
+        //Put it in the obeject in the correct conatiner -  one for each detector type.
+        if(isTRT){        
+          //Add the msos to the container 
+          msosTRT->push_back( msos );
+          //Set the det id
+          msos->setDetType( Trk::TrackState::TRT );
+          //Build the element link to the MSOS
+          ElementLink< xAOD::TrackStateValidationContainer > elink( *msosTRT, nTRT_MSOS ); 
+          elink.toPersistent();
+          msosLink.push_back(elink);
+          ++nTRT_MSOS;
+        }else if(isSCT){
+          //Add the msos to the container 
+          msosSCT->push_back( msos );
+          //Set the det id
+          msos->setDetType( Trk::TrackState::SCT );
+          //Build the element link to the MSOS
+          ElementLink< xAOD::TrackStateValidationContainer > elink( *msosSCT, nSCT_MSOS ); 
+          elink.toPersistent();
+          msosLink.push_back(elink);
+          ++nSCT_MSOS;
+        }else if(isPixel){
+          //Add the msos to the container 
+          msosPixel->push_back( msos );
+          //Set the det id
+          msos->setDetType( Trk::TrackState::Pixel );
+          //Build the element link to the MSOS
+          ElementLink< xAOD::TrackStateValidationContainer > elink( *msosPixel, nPixelMSOS ); 
+          elink.toPersistent();
+          msosLink.push_back(elink);
+          ++nPixelMSOS;
+        }
+
+        
+
+        //fill type
+        if( trackState->types()[Trk::TrackStateOnSurface::Hole] ){   
+          msos->setType( Trk::TrackStateOnSurface::Hole );
+        } else if (trackState->types()[Trk::TrackStateOnSurface::Measurement]){
+          msos->setType( Trk::TrackStateOnSurface::Measurement );
+        } else if ( trackState->types()[Trk::TrackStateOnSurface::Outlier] ) {
+          msos->setType( Trk::TrackStateOnSurface::Outlier );
+        }
+
+        //Fill surface id
+        msos->setDetElementId(  surfaceID.get_compact() );
+
+
+ 
+        //Get the measurement base object
+        const Trk::MeasurementBase* measurement=trackState->measurementOnTrack();
+        const Trk::RIO_OnTrack* hit = measurement ? dynamic_cast<const Trk::RIO_OnTrack*>(measurement) : 0;
+
+        if(!hit){
+          const Trk::CompetingRIOsOnTrack *crot = dynamic_cast<const Trk::CompetingRIOsOnTrack*>(measurement);
+          if(crot){
+            hit = &crot->rioOnTrack( crot->indexOfMaxAssignProb() );
+          }
+        }
+        
+        if(m_addPRD){
+          // Build an element link to the xAOD PRD
+          const Trk::PrepRawData* prd = hit->prepRawData();
+          if(prd && prd->getHashAndIndex().isValid() ){            
+            if(isTRT){
+              msos->setTrackMeasurementValidationLink( buildElementLink( prd, trtClusterOffsets, trtDCs) );
+            }else if(isSCT){
+              msos->setTrackMeasurementValidationLink( buildElementLink( prd, sctClusterOffsets, sctClusters) );
+            }else if(isPixel){
+              msos->setTrackMeasurementValidationLink( buildElementLink( prd, pixelClusterOffsets, pixelClusters) );
+            }
+          } 
+        }
+
+
+//        if (isPixel ) {
+//           tsos_bec.push_back( (int)m_pixId->barrel_ec(surfaceID) );
+//           tsos_layer.push_back( (int)m_pixId->layer_disk(surfaceID) );
+//           tsos_moduleeta.push_back( (int)m_pixId->eta_module(surfaceID) );
+//           tsos_modulephi.push_back( (int)m_pixId->phi_module(surfaceID) );
+//        } else if ( isSCT ) {
+//           tsos_bec.push_back( (int)m_sctId->barrel_ec(surfaceID) );
+//           tsos_layer.push_back( (int)m_sctId->layer_disk(surfaceID) );
+//           tsos_moduleeta.push_back( (int)m_sctId->barrel_ec(surfaceID) );
+//           tsos_modulephi.push_back( (int)m_sctId->phi_module(surfaceID) );
+//        } else if ( isTRT ) {
+//           tsos_bec.push_back( (int)m_trtId->barrel_ec(surfaceID) );
+//           tsos_layer.push_back( (int)m_trtId->layer_or_wheel(surfaceID) );
+//           tsos_moduleeta.push_back( (int)m_trtId->straw_layer(surfaceID) );
+//           tsos_modulephi.push_back( (int)m_trtId->phi_module(surfaceID) );
+//        }
+        
+        
+        const Trk::TrackParameters* tp = trackState->trackParameters();       
+        if(!tp){
+          continue;
+        }
+
+        // Set local positions on the surface
+        msos->setLocalPosition( tp->parameters()[0], tp->parameters()[1] );
+ 
+        // Set calculate local incident angles
+        const Trk::TrkDetElementBase *de = hit->detectorElement();
+        const InDetDD::SiDetectorElement *side = dynamic_cast<const InDetDD::SiDetectorElement *>(de);
+        if ( side && (isSCT || isPixel) ) {
+          Amg::Vector3D mytrack = tp->momentum();
+          Amg::Vector3D mynormal = side->normal();
+          Amg::Vector3D myphiax = side->phiAxis();
+          Amg::Vector3D myetaax = side->etaAxis();
+          float trketacomp = mytrack.dot(myetaax);
+          float trkphicomp = mytrack.dot(myphiax);
+          float trknormcomp = mytrack.dot(mynormal);  
+          msos->setLocalAngles( atan2(trketacomp,trknormcomp), atan2(trkphicomp,trknormcomp) );
+        } 
+ 
+        // Add the drift time for the tracks position -- note the position is biased 
+        if(isTRT){
+          TRTCond::RtRelation const *rtr = m_trtcaldbSvc->getRtRelation(surfaceID);
+          if(rtr) 
+            msos->auxdata<float>("driftTime") = rtr->drifttime(fabs(tp->parameters()[0]));
+        }
+
+        if(m_addPulls){
+          const Trk::ResidualPull *biased   = m_residualPullCalculator->residualPull(measurement, tp, Trk::ResidualPull::Biased);
+          if(biased){
+            if(biased->dimension()>Trk::locY){  
+              msos->setBiasedResidual( biased->residual()[Trk::locX], biased->residual()[Trk::locY] );
+              msos->setBiasedPull( biased->pull()[Trk::locX], biased->pull()[Trk::locY] );            
+            } else {
+              msos->setBiasedResidual( biased->residual()[Trk::locX], 0 );
+              msos->setBiasedPull( biased->pull()[Trk::locX], 0 );            
+            }
+            delete biased;
+          } 
+
+          const Trk::ResidualPull *unbiased = m_residualPullCalculator->residualPull(measurement, tp, Trk::ResidualPull::Unbiased);
+          if(unbiased){
+            if(unbiased->dimension()>Trk::locY){  
+              msos->setUnbiasedResidual( unbiased->residual()[Trk::locX], unbiased->residual()[Trk::locY] );
+              msos->setUnbiasedPull( unbiased->pull()[Trk::locX], unbiased->pull()[Trk::locY] );            
+            } else {
+              msos->setUnbiasedResidual( unbiased->residual()[Trk::locX], 0 );
+              msos->setUnbiasedPull( unbiased->pull()[Trk::locX], 0 );            
+            }
+            delete unbiased;
+          }
+        }
+      } //end loop over TSOS's
+       
+      ATH_MSG_DEBUG("The number of TSOS's " << msosLink.size() );
+
+      dectsos_msosLink( *track ) = msosLink;
+      
+      ATH_MSG_DEBUG("Finished dressing TrackParticle");
+
+    } // end of loop over tracks              
+    return StatusCode::SUCCESS;
+  }  
+  
+  
+  ElementLink< xAOD::TrackMeasurementValidationContainer >  TrackStateOnSurfaceDecorator::buildElementLink( const Trk::PrepRawData* prd, 
+                                                                  const std::vector<unsigned int>* offsets, 
+                                                                  const xAOD::TrackMeasurementValidationContainer* xaodPrdCont) const
+  {
+                                                                  
+    const IdentContIndex& contIndex = prd->getHashAndIndex();
+    if( contIndex.collHash() >= offsets->size() ){
+      ATH_MSG_ERROR(" Offsets are incorrect " <<  contIndex.collHash() << " " <<  offsets->size() <<" "<< contIndex.objIndex());
+      return ElementLink< xAOD::TrackMeasurementValidationContainer >(0,0);
+    }
+    
+    unsigned int xaodIndex = offsets->at( contIndex.collHash() ) + contIndex.objIndex(); 
+    ElementLink< xAOD::TrackMeasurementValidationContainer > el( *xaodPrdCont, xaodIndex ); 
+    el.toPersistent();
+    
+    return el;
+ 
+  }
+  
+  
+}
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/TrackToVertexWrapper.cxx b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/TrackToVertexWrapper.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..7e1c60d701e4ec09864ffb7b6a4a8a015abd383f
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/TrackToVertexWrapper.cxx
@@ -0,0 +1,124 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// TrackToVertexWrapper.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Author: James Catmore (james.catmore@cern.ch)
+//
+
+#include "DerivationFrameworkInDet/TrackToVertexWrapper.h"
+#include "xAODTracking/TrackParticleContainer.h"
+#include "TrkVertexFitterInterfaces/ITrackToVertexIPEstimator.h"
+#include <vector>
+#include <string>
+
+namespace DerivationFramework {
+
+  TrackToVertexWrapper::TrackToVertexWrapper(const std::string& t,
+      const std::string& n,
+      const IInterface* p) : 
+    AthAlgTool(t,n,p),
+    m_tool("Trk::TrackToVertexIPEstimator"),
+    m_sgName(""),
+    m_containerName("")
+  {
+    declareInterface<DerivationFramework::IAugmentationTool>(this);
+    declareProperty("TrackToVertexIPEstimator", m_tool);
+    declareProperty("DecorationPrefix", m_sgName);
+    declareProperty("ContainerName", m_containerName);
+  }
+
+  StatusCode TrackToVertexWrapper::initialize()
+  {
+    if (m_sgName=="") {
+      ATH_MSG_ERROR("No decoration prefix name provided for the output of TracktoVertexWrapper!");
+      return StatusCode::FAILURE;
+    }
+    if (m_containerName=="") {
+      ATH_MSG_ERROR("No TrackParticle collection provided for TracktoVertexWrapper!");
+      return StatusCode::FAILURE;
+    }
+    ATH_CHECK(m_tool.retrieve());
+    return StatusCode::SUCCESS;
+  }
+
+  StatusCode TrackToVertexWrapper::finalize()
+  {
+    return StatusCode::SUCCESS;
+  }
+
+  StatusCode TrackToVertexWrapper::addBranches() const
+  {
+
+    // retrieve track container
+    const xAOD::TrackParticleContainer* tracks = evtStore()->retrieve< const xAOD::TrackParticleContainer >( m_containerName );
+    if( ! tracks ) {
+        ATH_MSG_ERROR ("Couldn't retrieve TrackParticles with key: " << m_containerName );
+        return StatusCode::FAILURE;
+    }
+    // Run tool for each element and calculate the impact parameters/errors 
+    for (xAOD::TrackParticleContainer::const_iterator trItr = tracks->begin(); trItr!=tracks->end(); ++trItr) {
+      const Trk::ImpactParametersAndSigma* iPandSigma(NULL);
+      const Trk::ImpactParametersAndSigma* iPandSigmaBiased(NULL);
+      if ( (*trItr)->vertex() ) {
+	iPandSigma = m_tool->estimate(*trItr,(*trItr)->vertex(),true);
+	iPandSigmaBiased = m_tool->estimate(*trItr,(*trItr)->vertex(),false);
+	if( iPandSigma==0 ) ATH_MSG_WARNING ("trackToVertexIPEstimator failed !");
+	if( iPandSigmaBiased==0 ) ATH_MSG_WARNING ("trackToVertexIPEstimator biased IP failed !");
+      } else {
+	ATH_MSG_DEBUG("No vertex associated to the track. Skipping it.");
+      }
+      // Do the decoration for each track
+      SG::AuxElement::Decorator< float > decnD0(m_sgName+"_unbiased_d0");
+      SG::AuxElement::Decorator< float > decnZ0(m_sgName+"_unbiased_z0");
+      SG::AuxElement::Decorator< float > decnD0Err(m_sgName+"_unbiased_d0Sigma");
+      SG::AuxElement::Decorator< float > decnZ0Err(m_sgName+"_unbiased_z0Sigma");
+      SG::AuxElement::Decorator< float > decnPVD0Err(m_sgName+"_unbiased_PVd0Sigma");
+      SG::AuxElement::Decorator< float > decnPVZ0Err(m_sgName+"_unbiased_PVz0Sigma");
+      if (iPandSigma) {
+	decnD0( **trItr ) = iPandSigma->IPd0;
+	decnZ0( **trItr ) = iPandSigma->IPz0;
+	decnD0Err( **trItr ) = iPandSigma->sigmad0;
+	decnZ0Err( **trItr ) = iPandSigma->sigmaz0;
+	decnPVD0Err (**trItr ) = iPandSigma->PVsigmad0;
+	decnPVZ0Err (**trItr ) = iPandSigma->PVsigmaz0;
+	delete iPandSigma;
+      } else {
+	decnD0( **trItr ) = 999.;
+	decnZ0( **trItr ) = 999.;
+	decnD0Err( **trItr ) = 999.;
+	decnZ0Err( **trItr ) = 999.;
+	decnPVD0Err (**trItr ) = 999.;
+	decnPVZ0Err (**trItr ) = 999.;
+      }
+
+      SG::AuxElement::Decorator< float > decn_b_D0(m_sgName+"_biased_d0");
+      SG::AuxElement::Decorator< float > decn_b_Z0(m_sgName+"_biased_z0");
+      SG::AuxElement::Decorator< float > decn_b_D0Err(m_sgName+"_biased_d0Sigma");
+      SG::AuxElement::Decorator< float > decn_b_Z0Err(m_sgName+"_biased_z0Sigma");
+      SG::AuxElement::Decorator< float > decn_b_PVD0Err(m_sgName+"_biased_PVd0Sigma");
+      SG::AuxElement::Decorator< float > decn_b_PVZ0Err(m_sgName+"_biased_PVz0Sigma");
+      if (iPandSigmaBiased) {
+	decn_b_D0( **trItr ) = iPandSigmaBiased->IPd0;
+	decn_b_Z0( **trItr ) = iPandSigmaBiased->IPz0;
+	decn_b_D0Err( **trItr ) = iPandSigmaBiased->sigmad0;
+	decn_b_Z0Err( **trItr ) = iPandSigmaBiased->sigmaz0;
+	decn_b_PVD0Err (**trItr ) = iPandSigmaBiased->PVsigmad0;
+	decn_b_PVZ0Err (**trItr ) = iPandSigmaBiased->PVsigmaz0;
+	delete iPandSigmaBiased;
+      } else {
+	decn_b_D0( **trItr ) = 999.;
+	decn_b_Z0( **trItr ) = 999.;
+	decn_b_D0Err( **trItr ) = 999.;
+	decn_b_Z0Err( **trItr ) = 999.;
+	decn_b_PVD0Err (**trItr ) = 999.;
+	decn_b_PVZ0Err (**trItr ) = 999.;
+      }
+    } // end of loop over tracks		 	 	  
+    
+    return StatusCode::SUCCESS;
+  }  
+
+}
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/components/DerivationFrameworkInDet_entries.cxx b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/components/DerivationFrameworkInDet_entries.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..ed5b46370154ab7c975e3f0cc84d3f51ff406432
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/components/DerivationFrameworkInDet_entries.cxx
@@ -0,0 +1,35 @@
+#include "GaudiKernel/DeclareFactoryEntries.h"
+#include "DerivationFrameworkInDet/TrackToVertexWrapper.h"
+#include "DerivationFrameworkInDet/TrackParticleThinning.h"
+#include "DerivationFrameworkInDet/MuonTrackParticleThinning.h"
+#include "DerivationFrameworkInDet/EgammaTrackParticleThinning.h"
+#include "DerivationFrameworkInDet/JetTrackParticleThinning.h"
+#include "DerivationFrameworkInDet/TauTrackParticleThinning.h"
+#include "DerivationFrameworkInDet/TrackParametersAtPV.h"
+#include "DerivationFrameworkInDet/TrackStateOnSurfaceDecorator.h"
+#include "DerivationFrameworkInDet/TrackParametersForTruthParticles.h"
+
+using namespace DerivationFramework;
+
+DECLARE_TOOL_FACTORY( TrackToVertexWrapper )
+DECLARE_TOOL_FACTORY( TrackParticleThinning )
+DECLARE_TOOL_FACTORY( MuonTrackParticleThinning )
+DECLARE_TOOL_FACTORY( EgammaTrackParticleThinning )
+DECLARE_TOOL_FACTORY( TauTrackParticleThinning )
+DECLARE_TOOL_FACTORY( JetTrackParticleThinning )
+DECLARE_TOOL_FACTORY( TrackParametersAtPV )
+DECLARE_TOOL_FACTORY( TrackStateOnSurfaceDecorator )
+DECLARE_TOOL_FACTORY( TrackParametersForTruthParticles )
+
+DECLARE_FACTORY_ENTRIES( DerivationFrameworkInDet ) {
+   DECLARE_TOOL( TrackToVertexWrapper )
+   DECLARE_TOOL( TrackParticleThinning )
+   DECLARE_TOOL( MuonTrackParticleThinning )
+   DECLARE_TOOL( EgammaTrackParticleThinning )
+   DECLARE_TOOL( TauTrackParticleThinning )
+   DECLARE_TOOL( JetTrackParticleThinning )
+   DECLARE_TOOL( TrackParametersAtPV )
+	 DECLARE_TOOL( TrackStateOnSurfaceDecorator )
+	 DECLARE_TOOL( TrackParametersForTruthParticles )
+}
+
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/components/DerivationFrameworkInDet_load.cxx b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/components/DerivationFrameworkInDet_load.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..8d3d476abb43c3fa88b2795804d6efa74b79bdba
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/components/DerivationFrameworkInDet_load.cxx
@@ -0,0 +1,3 @@
+#include "GaudiKernel/LoadFactoryEntries.h"
+
+LOAD_FACTORY_ENTRIES( DerivationFrameworkInDet )