diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/PhotonD3PDMaker/ITruthParticleFilterCutTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/PhotonD3PDMaker/ITruthParticleFilterCutTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..e59e523938eb67fba42d667690b1327d417e2d84
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/PhotonD3PDMaker/ITruthParticleFilterCutTool.h
@@ -0,0 +1,31 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef PHOTOND3PDMAKER_ITRUTHPARTICLEFILTERCUTTOOL_H
+#define PHOTOND3PDMAKER_ITRUTHPARTICLEFILTERCUTTOOL_H
+ 
+ 
+// Includes for Gaudi
+#include "GaudiKernel/StatusCode.h"
+#include "GaudiKernel/IAlgTool.h"
+
+namespace HepMC{
+  class GenParticle;
+}
+ 
+static const InterfaceID IID_ITruthParticleFilterCutTool("ITruthParticleFilterCutTool", 1 , 0);
+ 
+class ITruthParticleFilterCutTool: virtual public IAlgTool {
+ 
+ public:
+  // Athena algorithm's Hooks
+  virtual StatusCode  initialize() = 0;
+  virtual StatusCode  execute()    = 0;
+  virtual StatusCode  finalize()   = 0;
+  virtual bool passesCut( const HepMC::GenParticle* tp)=0 ;
+
+  static const InterfaceID& interfaceID() { return IID_ITruthParticleFilterCutTool;}
+};
+
+#endif 
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/PhotonD3PDMaker/PhotonD3PD_AddReflexDict.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/PhotonD3PDMaker/PhotonD3PD_AddReflexDict.h
new file mode 100644
index 0000000000000000000000000000000000000000..8458651490d1f71c349323ecadae796ba5b4aadf
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/PhotonD3PDMaker/PhotonD3PD_AddReflexDict.h
@@ -0,0 +1,15 @@
+// dear emacs, this is -*- C++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+namespace PhotonD3PD_AddReflexDict {
+
+  struct dict{
+  };
+
+}
+
+
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/PhotonD3PDMaker/selection.xml b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/PhotonD3PDMaker/selection.xml
new file mode 100644
index 0000000000000000000000000000000000000000..16ce8b580f258a170dfe66fa77ab015352a1f807
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/PhotonD3PDMaker/selection.xml
@@ -0,0 +1,3 @@
+<lcgdict>
+
+</lcgdict>
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/cmt/requirements b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/cmt/requirements
new file mode 100644
index 0000000000000000000000000000000000000000..dbd4fa647e3c5317571963491b8b0c39d44ed6d1
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/cmt/requirements
@@ -0,0 +1,69 @@
+package PhotonD3PDMaker
+
+use AtlasPolicy                AtlasPolicy-*     
+use GaudiInterface             GaudiInterface-*        External
+
+private
+use AtlasBoost		       AtlasBoost-*	       External
+use AtlasHepMC		       AtlasHepMC-*	       External
+use AtlasROOT                  AtlasROOT-*             External
+use AtlasCLHEP                 AtlasCLHEP-*            External
+
+use AthenaKernel               AthenaKernel-*          Control
+use AthenaBaseComps            AthenaBaseComps-*       Control
+use StoreGate 		       StoreGate-*             Control
+use DataModel                  DataModel-*             Control
+use SGTools                    SGTools-*               Control
+use Navigation                 Navigation-*            Control
+
+use Identifier 		       Identifier-* 	       DetectorDescription
+
+use GeneratorObjects           GeneratorObjects-*      Generators
+
+use McParticleKernel	       McParticleKernel-*      PhysicsAnalysis/TruthParticleID
+use McParticleEvent            McParticleEvent-*       PhysicsAnalysis/TruthParticleID
+
+use EventKernel                EventKernel-*           Event
+use FourMomUtils	       FourMomUtils-*          Event
+use ParticleEvent              ParticleEvent-*         PhysicsAnalysis/AnalysisCommon
+
+use egammaEvent                egammaEvent-*           Reconstruction/egamma
+use muonEvent                  muonEvent-*             Reconstruction/MuonIdentification
+
+use Particle 		       Particle-* 	       Reconstruction
+
+use TrkParameters 	       TrkParameters-* 	       Tracking/TrkEvent
+use TrkNeutralParameters       TrkNeutralParameters-*  Tracking/TrkEvent
+use TrkTrackSummary 	       TrkTrackSummary-*       Tracking/TrkEvent
+
+use D3PDMakerUtils	       D3PDMakerUtils-*        PhysicsAnalysis/D3PDMaker
+use D3PDMakerInterfaces	       D3PDMakerInterfaces-*   PhysicsAnalysis/D3PDMaker
+
+use PhotonAnalysisUtils        PhotonAnalysisUtils-*   PhysicsAnalysis/StandardModelPhys
+use VxVertex                   VxVertex-*              Tracking/TrkEvent
+
+use CaloEvent                  CaloEvent-*             Calorimeter
+#use CaloUtils                  CaloUtils-*             Calorimeter
+use CaloGeoHelpers             CaloGeoHelpers-*        Calorimeter
+
+use TrkParticleBase            TrkParticleBase-*       Tracking/TrkEvent
+use TrkTrack                   TrkTrack-*              Tracking/TrkEvent
+
+use ITrackToVertex             ITrackToVertex-*        Reconstruction/RecoTools
+
+use egammaUtils                egammaUtils-*           Reconstruction/egamma
+
+#use IsolationTool              IsolationTool-*         Reconstruction/RecoTools
+
+use CaloDetDescr	       CaloDetDescr-*          Calorimeter
+
+end_private
+
+
+library PhotonD3PDMaker *.cxx components/*.cxx
+apply_pattern component_library
+apply_pattern declare_python_modules files="*.py"
+apply_pattern declare_joboptions files="*.py"
+
+# Insert this if we need to add some weird structure to reflex, like vector^n<var>
+# apply_pattern lcgdict dict=PhotonD3PD_AddReflex headerfiles="../PhotonD3PDMaker/PhotonD3PD_AddReflexDict.h" selectionfile=selection.xml
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddCellFilter.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddCellFilter.py
new file mode 100644
index 0000000000000000000000000000000000000000..4e0c08d2c9318595147668d469daf9fca944637a
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddCellFilter.py
@@ -0,0 +1,38 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+from AthenaCommon.AlgSequence import AlgSequence
+import D3PDMakerCoreComps
+import PhotonD3PDMaker
+from D3PDMakerConfig.D3PDMakerFlags                  import D3PDMakerFlags
+from PhotonD3PDMaker.PhotonD3PDMakerFlags            import PhotonD3PDMakerFlags
+
+DVGetter = D3PDMakerCoreComps.SGDataVectorGetterTool
+
+def AddCellFilter(outputsgkey = "SelectedCells",
+                  seq = AlgSequence()):
+
+    from AthenaCommon.AppMgr      import ToolSvc
+
+    photongetter = DVGetter('photoncellfilter_Getter',
+                            TypeName = 'PhotonContainer',
+                            SGKey = D3PDMakerFlags.PhotonSGKey())
+    ToolSvc += photongetter
+
+    electrongetter = DVGetter('electroncellfilter_Getter',
+                              TypeName = 'ElectronContainer',
+                              SGKey = D3PDMakerFlags.ElectronSGKey())
+    ToolSvc += electrongetter
+
+    from ROOT import egammaPID
+    cellfilter = PhotonD3PDMaker.CellFilter(InputCellCollectionName = "AODCellContainer",
+                                            OutputCellCollectionName = "SelectedCells",
+                                            photonGetter = photongetter,
+                                            electronGetter = electrongetter,
+                                            ptCut = 15000.,
+                                            etaCut = 2.5,
+                                            deltaRCut = PhotonD3PDMakerFlags.CellDrCut(),
+                                            photonID = egammaPID.PhotonIDLoose,
+                                            electronID = egammaPID.ElectronIDMediumPP)
+
+    seq += cellfilter
+    
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddElectronsToD3PD.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddElectronsToD3PD.py
new file mode 100644
index 0000000000000000000000000000000000000000..3e6b2fc0654b9dc8b606a7ad5cda84ef810524d9
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddElectronsToD3PD.py
@@ -0,0 +1,263 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+import PhotonD3PDMaker
+import D3PDMakerCoreComps
+import CaloD3PDMaker
+from PhotonD3PDMaker.PhotonD3PDMakerFlags            import PhotonD3PDMakerFlags
+from D3PDMakerCoreComps.IndexAssociation             import IndexAssociation
+from D3PDMakerCoreComps.IndexMultiAssociation        import IndexMultiAssociation
+from D3PDMakerCoreComps.SimpleAssociation            import SimpleAssociation
+from PhotonD3PDMaker.PhotonD3PD                      import _args
+from egammaD3PDMaker.ElectronD3PDObject              import ElectronD3PDObject
+from egammaD3PDMaker                                 import egammaDetailFillerTool
+from ROOT                                            import egammaParameters
+import egammaD3PDMaker
+import egammaD3PDAnalysis
+from D3PDMakerConfig.D3PDMakerFlags                  import D3PDMakerFlags
+from egammaD3PDMaker.defineBlockAndAlg               import defineAlgLODFunc, defineBlockAndAlg
+from AthenaCommon.AlgSequence import AlgSequence
+from AthenaCommon.AppMgr      import ToolSvc
+from AthenaCommon.Include     import include
+from D3PDMakerCoreComps.release_version              import at_least_version
+import TrackD3PDMaker
+from AthenaPython                                    import PyAthena
+from RecExConfig.RecFlags                            import rec
+from D3PDMakerCoreComps.resolveSGKey                 import testSGKey
+from CaloD3PDMaker                                   import ClusterTimeFillerTool
+import EventCommonD3PDMaker
+
+DVGetter = D3PDMakerCoreComps.SGDataVectorGetterTool
+ElectronUDPrefix = "PhotonD3PD::ElectronUDPrefix_"
+
+
+topo_iso_in_aod = at_least_version ('17.1.2') and not at_least_version ('17.3.0')
+
+def AddElectronsToD3PD(alg, **kw):
+    from AthenaCommon.AppMgr      import ToolSvc
+    preseq = AlgSequence(D3PDMakerFlags.PreD3PDAlgSeqName())
+
+    # some electron->jet matching
+    for i in PhotonD3PDMakerFlags.JetCollections():
+
+        collection_name = "jet_"+i+"_"
+
+        # this jet matching for electrons is different than for photons.
+        # PAU doesn't do any jet matching for electrons, so I elected to keep this
+        # matching consistent with what the rest of ATLAS is doing, rather than
+        # keep the PAU convention for photons.
+        from EventCommonD3PDMaker.DRAssociation     import DRAssociation
+        EleJetD3PDAssoc = DRAssociation (ElectronD3PDObject,
+                                         'JetCollection',
+                                         i,
+                                         0.2,
+                                         collection_name,
+                                         level = 1,
+                                         blockname = 'ElectronJetMatch_'+i)
+        EleJetD3PDAssoc.defineBlock (1, 'ElectronJetIndex_'+i,
+                                     D3PDMakerCoreComps.IndexFillerTool,
+                                     Target = collection_name)
+
+    # stuff that's not going to make it in there otherwise
+    #
+    additionalElectronIncludes=["SumCellsGain", "NbCellsGain"]
+    if (PhotonD3PDMakerFlags.ElectronDumpingLevel() < 2):
+        additionalElectronIncludes += ["Rings",
+                                       "Pointing",
+                                       "EMTrackFitDetailsBrem",
+                                       "EMTrackFitDetailsRefit",
+                                       "IsoPtCorrected",
+                                       "TrackIsoIP",
+                                       "Samplings",
+                                       "AllSamplings",
+                                       "ClusterKin",
+                                       "RawSamplings",
+                                       "RawClusterKin",
+                                       "SumCellsGain",
+                                       "NbCellsGain"]
+                                    
+        
+    from egammaD3PDMaker.ElectronD3PDObject import ElectronClusterAssoc
+    ElectronClusterAssoc.defineBlock(1, 'Time', ClusterTimeFillerTool)
+    ElectronClusterAssoc.defineBlock(2, '', PhotonD3PDMaker.ShowerRadiusFillerTool)
+ 
+    CellGetter = DVGetter ('ElectronSelectedCellGetter', 
+                           TypeName = 'CaloCellContainer', 
+                           SGKey = PhotonD3PDMakerFlags.SelectedCellsContainerName())
+    ToolSvc += CellGetter
+    ElectronCellAssoc = IndexMultiAssociation(ElectronClusterAssoc,
+                                              CaloD3PDMaker.CaloClusterExtendedCellAssociationTool,
+                                              "cell_",
+                                              level=1,
+                                              prefix="cell_",
+                                              blockname = 'ClusterExtendedCells',
+                                              allowMissing = True,
+                                              Getter = CellGetter,
+                                              DRCut=PhotonD3PDMakerFlags.CellDrCut())
+
+    ElectronD3PDObject.defineBlock(1, "CoNoise",
+                                   egammaDetailFillerTool,
+                                   Details = [egammaParameters.etconoisedR04Sig2, 'etconoisedR04Sig2',
+                                              egammaParameters.etconoisedR04Sig3, 'etconoisedR04Sig3']);
+    
+    # Topo cluster associations.
+    ElectronTopoD3PDAssoc = DRAssociation (ElectronD3PDObject,
+                                           'CaloClusterContainer',
+                                           D3PDMakerFlags.ClusterSGKey(),
+                                           0.1,
+                                           'topo',
+                                           level = PhotonD3PDMakerFlags.ElectronDumpingLevel(),
+                                           blockname = 'TopoMatch')
+    ElectronTopoD3PDAssoc.defineBlock (PhotonD3PDMakerFlags.ElectronDumpingLevel(), 'TopoKinematics',
+                                       EventCommonD3PDMaker.FourMomFillerTool,
+                                       WriteM = False)
+    ElectronTopoD3PDAssoc.defineBlock (1, 'ElectronTopoKinematicsEM',
+                                       PhotonD3PDMaker.ClusterFillerTool,
+                                       Prefix = "EMsamplings_",
+                                       UseCaloSamplings = [0,1,2,3,4,5,6,7])
+    ElectronTopoD3PDAssoc.defineBlock (1, 'ElectronTopoKinematicsUncalibratedEM',
+                                       PhotonD3PDMaker.ClusterFillerTool,
+                                       Prefix = "EMsamplings_uncalibrated_",
+                                       SignalState = PyAthena.P4SignalState.UNCALIBRATED,
+                                       UseCaloSamplings = [0,1,2,3,4,5,6,7])
+    
+    # Some tools for topocluster isolatoin
+    from egammaCaloTools.egammaTopoIsoToolBase   import egammaTopoIsoToolBase
+    egammaCalTopoIsoTool = egammaTopoIsoToolBase("egammaCalTopoIsoToolBase")
+    egammaCalTopoIsoTool.UseEMScale = False
+    egammaTopoIsoTool = egammaTopoIsoToolBase("egammTopoIsoToolBase")
+
+    if egammaTopoIsoTool not in ToolSvc:
+        ToolSvc += egammaTopoIsoTool
+    if egammaCalTopoIsoTool not in ToolSvc:
+        ToolSvc += egammaCalTopoIsoTool
+
+    #----------------------------------------------
+    # TopoCluster isolation variables, requested by Sandrine, Jean-Baptiste, and Jessica
+
+    # Add additional TopoCluster Isolation variables
+    # -- first, schedule them to be calculated
+    ClusterTopoIsoGetter = DVGetter('el_egammaTopoAlgClusterGetter',
+                                    TypeName = 'CaloClusterContainer',
+                                    SGKey = D3PDMakerFlags.ClusterSGKey())
+    ElectronTopoIsoGetter =  DVGetter('el_egammaTopoPosEMIsoAlgEgammaGetter',
+                               TypeName = 'ElectronContainer',
+                               SGKey = D3PDMakerFlags.ElectronSGKey())
+    preseq += egammaD3PDAnalysis.egammaTopoIsoAlg("el_egammaTopoPosEMIsoAlg",
+                                                  EgammaGetter = ElectronTopoIsoGetter,
+                                                  ClusterGetter = ClusterTopoIsoGetter,
+                                                  TopoIsoTool = egammaTopoIsoTool,
+                                                  PositiveEnergyClusters = True, 
+                                                  UseEMScale = True,
+                                                  ConeSizes = [.20, .30, .40, .50, .60],
+                                                  AllowMissing = False,
+                                                  UDPrefix = ElectronUDPrefix)
+    preseq += egammaD3PDAnalysis.egammaTopoIsoAlg("el_egammaTopoCalIsoAlg",
+                                                  EgammaGetter = ElectronTopoIsoGetter,
+                                                  ClusterGetter = ClusterTopoIsoGetter,
+                                                  TopoIsoTool = egammaCalTopoIsoTool,
+                                                  PositiveEnergyClusters = False,
+                                                  UseEMScale = False,
+                                                  ConeSizes = [.20, .30, .40, .50, .60],
+                                                  AllowMissing = False,
+                                                  UDPrefix = ElectronUDPrefix)
+    preseq += egammaD3PDAnalysis.egammaTopoIsoAlg("el_egammaTopoPosCalIsoAlg",
+                                                  EgammaGetter = ElectronTopoIsoGetter,
+                                                  ClusterGetter = ClusterTopoIsoGetter,
+                                                  TopoIsoTool = egammaCalTopoIsoTool,
+                                                  PositiveEnergyClusters = True,
+                                                  UseEMScale = False,
+                                                  ConeSizes = [.20, .30, .40, .50, .60],
+                                                  AllowMissing = False,
+                                                  UDPrefix = ElectronUDPrefix)
+    # now fill them
+    ElectronD3PDObject.defineBlock (PhotonD3PDMakerFlags.ElectronDumpingLevel(),
+                                    'PhotonD3PD_ElectronExtraUDTopoCones',
+                                    D3PDMakerCoreComps.UserDataFillerTool,
+                                    UDPrefix = ElectronUDPrefix,
+                                    Vars = ['topoCalEtcone20', '', 'float',
+                                            'topoCalEtcone30', '', 'float',
+                                            'topoCalEtcone40', '', 'float',
+                                            'topoCalEtcone50', '', 'float',
+                                            'topoCalEtcone60', '', 'float',
+                                            'topoPosEtcone20', '', 'float',
+                                            'topoPosEtcone30', '', 'float',
+                                            'topoPosEtcone40', '', 'float',
+                                            'topoPosEtcone50', '', 'float',
+                                            'topoPosEtcone60', '', 'float',
+                                            'topoPosCalEtcone20', '', 'float',
+                                            'topoPosCalEtcone30', '', 'float',
+                                            'topoPosCalEtcone40', '', 'float',
+                                            'topoPosCalEtcone50', '', 'float',
+                                            'topoPosCalEtcone60', '', 'float',
+                                            ])
+    #----------------------------------------------
+    
+    # some truth associations
+    if rec.doTruth():
+        # construct an association tool from an egamma* object to a genparticle
+        # for now, at least, needs to use the PAU tools for object matching
+        from PhotonAnalysisUtils.PAU_AtlasExtrapolator import PAU_AtlasExtrapolator
+        theAtlasExtrapolator = PAU_AtlasExtrapolator()
+
+        from PhotonAnalysisUtils.PAU_ExtrapolateToCaloTool import PAU_ExtrapolateToCaloTool
+        exToCalo = PAU_ExtrapolateToCaloTool(theAtlasExtrapolator = theAtlasExtrapolator)
+
+        from PhotonAnalysisUtils.TruthTools import TruthToolsWrapper
+        PAUtruthTool = TruthToolsWrapper(exToCalo)
+
+        PAUElectronTruthParticleAssociationTool = IndexAssociation(ElectronD3PDObject,
+                                                                   PhotonD3PDMaker.TruthParticleAssociationTool,
+                                                                   target="mc_",
+                                                                   prefix="mc_",
+                                                                   level=1,
+                                                                   blockname="PAUElectronTruthParticleAssociationTool",
+                                                                   allowMissing=False,
+                                                                   PAUtruthTool = PAUtruthTool)
+        
+        PAUElectronEgammaTruthParticleAssociationTool = IndexAssociation(ElectronD3PDObject,
+                                                                         PhotonD3PDMaker.TruthParticleAssociationTool,
+                                                                         target="egammaTruth_",
+                                                                         prefix='egammaTruth_',
+                                                                         level=1,
+                                                                         blockname="PAUElectronEgammaTruthParticleAssociationTool",
+                                                                         allowMissing=False,
+                                                                         PAUtruthTool = PAUtruthTool)
+
+        
+
+    # Finally, associate the electron to a track
+    ElectronTrackParticleIndexAssociation = IndexAssociation(ElectronD3PDObject,
+                                                             egammaD3PDMaker.egammaTrackParticleAssociationTool,
+                                                             target="trk",
+                                                             prefix="trk_",
+                                                             level=1,
+                                                             blockname="TrackIndex",
+                                                             allowMissing=False)
+
+    GSFTrackParticlesInSample = testSGKey ('Rec::TrackParticleContainer', "GSFTrackParticleCandidate")
+    if GSFTrackParticlesInSample:
+        ElectronTrackParticleIndexAssociation = IndexAssociation(ElectronD3PDObject,
+                                                                 egammaD3PDMaker.egammaTrackParticleAssociationTool,
+                                                                 target="GSF_trk",
+                                                                 prefix="GSF_trk_",
+                                                                 level=1,
+                                                                 blockname="GSFTrackIndex",
+                                                                 allowMissing=False)
+        
+
+    ed3pd = ElectronD3PDObject        (**_args ( PhotonD3PDMakerFlags.ElectronDumpingLevel(),
+                                                 'Electron', kw,
+                                                 include=additionalElectronIncludes,
+                                                 exclude=['JetMatch'],
+                                                 EgammaJetSignedIPAndPTRel_target='jet_AntiKt4TopoEMJets_'))
+    alg += ed3pd
+    
+    # GSF electrons?
+    GSFElectronsInSample = testSGKey ('ElectronContainer', D3PDMakerFlags.GSFElectronSGKey())
+    if GSFElectronsInSample:
+        alg += GSFElectronD3PDObject(**_args ( PhotonD3PDMakerFlags.ElectronDumpingLevel(),
+                                               'GSFElectron', kw,
+                                               sgkey = D3PDMakerFlags.GSFElectronSGKey(),
+                                               EgammaJetSignedIPAndPTRel_target='jet_AntiKt4TopoEMJets_',
+                                               prefix = 'el_gsf_'))
+
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddJetsToD3PD.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddJetsToD3PD.py
new file mode 100644
index 0000000000000000000000000000000000000000..5064ddd6e7e275c17817e2d7fceb2b4f90f28b80
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddJetsToD3PD.py
@@ -0,0 +1,47 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+from JetRec.JetMomentGetter               import make_JetMomentGetter
+from JetD3PDMaker.JetD3PDObject           import JetD3PDObject
+import JetD3PDMaker
+from JetTagD3PDMaker.JetTagD3PDMakerKeys  import JetTagD3PDKeys
+
+from PhotonD3PDMaker.PhotonD3PDMakerFlags import PhotonD3PDMakerFlags
+from PhotonD3PDMaker.PhotonD3PD           import _args
+
+def AddJetsToD3PD(alg, **kw):
+    for i in PhotonD3PDMakerFlags.JetCollections():
+        
+        collname=i
+        if PhotonD3PDMakerFlags.EnableBTagging():
+            collname=i+PhotonD3PDMakerFlags.BTaggingSuffix()
+
+        # This will change the following variables:
+        # _jvtx_x, _jvtx_y, _jvtx_z, _sumPtTrk, _nTrk, _OriginIndex, _isBad*, 
+        if PhotonD3PDMakerFlags.ReCalculateJetMoments():
+            make_JetMomentGetter(collname, [jvatool])
+    
+        collection_name = "jet_"+i+"_"
+        jetd3pd = JetD3PDObject              (**_args ( 3, i,  kw,
+                                                        prefix=collection_name,
+                                                        sgkey=collname,
+                                                        include=[JetTagD3PDKeys.TruthInfoBlockName(),
+                                                                 JetTagD3PDKeys.BTagWeightsBlockName(),
+                                                                 JetTagD3PDKeys.IP2DInfoBaseBlockName(),
+                                                                 JetTagD3PDKeys.IP2DIPInfoBaseBlockName(),
+                                                                 JetTagD3PDKeys.IP3DInfoBaseBlockName(),
+                                                                 JetTagD3PDKeys.IP3DIPInfoBaseBlockName(),
+                                                                 JetTagD3PDKeys.SV1InfoBaseBlockName(),
+                                                                 JetTagD3PDKeys.SV2InfoBaseBlockName(),
+                                                                 JetTagD3PDKeys.JetFitterInfoBaseBlockName(),
+                                                                 JetTagD3PDKeys.JetFitterCombInfoBaseBlockName(),
+                                                                 JetTagD3PDKeys.JetFitterTagInfoBlockName(),
+                                                                 JetTagD3PDKeys.SVInfoPlusBlockName(),
+                                                                 JetTagD3PDKeys.SV0InfoPlusBlockName(),
+                                                                 'ConstituentScale',
+                                                                 'Samplings',
+                                                                 'TracksMoments'],
+                                                        JetVertexFraction_FromUD=PhotonD3PDMakerFlags.FillFullJVF(),
+                                                        JetVertexFraction_FillFullJVF=PhotonD3PDMakerFlags.FillFullJVF(),
+                                                        allowMissing=True))
+
+        alg += jetd3pd
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddMETToD3PD.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddMETToD3PD.py
new file mode 100644
index 0000000000000000000000000000000000000000..d7ea7cd95d260d3ee244bc30ab2315ab43c96554
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddMETToD3PD.py
@@ -0,0 +1,102 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+from PhotonD3PDMaker.PhotonD3PDMakerFlags import PhotonD3PDMakerFlags
+from PhotonD3PDMaker.PhotonD3PD import _args
+from RecExConfig.RecFlags import rec
+
+def AddMETToD3PD(alg, CustomMETCollections=[], **kw):
+    from MissingETD3PDMaker.MissingETD3PDMakerFlags import MissingETD3PDMakerFlags
+    MissingETD3PDMakerFlags.METDefaultJetPrefix.set_Value_and_Lock('jet_AntiKt4LCTopo_MET_')
+
+    # does this really need to be 10?
+    from D3PDMakerConfig.METD3PDObject                   import METD3PDObject
+    alg += METD3PDObject              (**_args (10, 'MET'              , kw))
+
+    if PhotonD3PDMakerFlags.FillFullMET():
+        from MissingETD3PDMaker.MissingETD3PDObject import MissingETD3PDObject
+        alg += MissingETD3PDObject        (**_args (   10, 'MissingET'        , kw,
+                                                       allowMissing = True))
+    else:
+        # But we want to customize the MET information a bit....
+        MET_ALGS=[]
+        Level1METList = [MissingETD3PDMakerFlags.METCryoSGKey(),
+                         MissingETD3PDMakerFlags.METRefFinalSGKey(),
+                         MissingETD3PDMakerFlags.METRefEleSGKey(),
+                         MissingETD3PDMakerFlags.METRefJetSGKey(),
+                         MissingETD3PDMakerFlags.METRefMuonSGKey(),
+                         MissingETD3PDMakerFlags.METRefMuonStacoSGKey(),
+                         MissingETD3PDMakerFlags.METRefMuonMuidSGKey(),
+                         MissingETD3PDMakerFlags.METRefGammaSGKey(),
+                         MissingETD3PDMakerFlags.METRefTauSGKey(),
+                         MissingETD3PDMakerFlags.METCellOutSGKey(),
+                         MissingETD3PDMakerFlags.METMuonBoySGKey(),
+                         MissingETD3PDMakerFlags.METMuonBoyTrackSGKey()]
+        
+        Level2METList = [MissingETD3PDMakerFlags.METFinalSGKey()]
+        
+        Level3CaloMETList = [MissingETD3PDMakerFlags.METTopoSGKey(),
+                             MissingETD3PDMakerFlags.METLocHadTopoSGKey()]
+    
+        from MissingETD3PDMaker.MissingETD3PDObject import MissingETCustomizer
+        from MissingETD3PDMaker.MissingETD3PDObject import CaloMissingETCustomizer
+        for key in Level1METList:
+            MET_ALGS += MissingETCustomizer (key, 1, prefix='MET_', allowMissing=True)
+        for key in Level2METList:
+            MET_ALGS += MissingETCustomizer (key, 2, prefix='MET_', allowMissing=True)
+        for key in Level3CaloMETList:
+            MET_ALGS += CaloMissingETCustomizer (key, 3, prefix='MET_', allowMissing=True)
+        
+        alg += MET_ALGS
+    
+        if rec.doTruth():
+            from MissingETD3PDMaker.MissingETD3PDObject          import MissingETTruthD3PDObject
+            alg += MissingETTruthD3PDObject   (**_args (    1, 'METTruth'         , kw))
+
+        # FIXME
+        # This really doesn't seem to add anything, except warnings at run time
+        # We should re-evaluate if this is at all useful to us, and if it is, how to configure it.
+        # 
+        # from MissingETD3PDMaker.MissingETGoodnessD3PDObject  import MissingETGoodnessD3PDObject
+        # alg += MissingETGoodnessD3PDObject(**_args (    1, 'METGoodness'      , kw))
+
+    # Now, fill in some custom MET collections
+    METFlavors=['MET_RefGamma',
+                'MET_RefFinal',
+                'MET_RefFinal_STVF',
+                'MET_RefJet',
+                'MET_RefJet_JVF',
+                'MET_RefJet_JVFCut',
+                'MET_RefEle', 
+                'MET_Muon_Total_Staco',
+                'MET_Muon_Isol_Staco',
+                'MET_Muon_NonIsol_Staco', 
+                'MET_Muon_Isol_Muid',
+                'MET_Muon_NonIsol_Muid',
+                'MET_Muon_Total_Muid',
+                'MET_Track',
+                'MET_CellOut',
+                'MET_CellOut_Eflow',
+                'MET_CellOut_Eflow_STVF',
+                'MET_CellOut_Eflow_JetArea',
+                'MET_CellOutCorr',
+                'MET_CellOut_Track',
+                'MET_CellOut_TrackPV',
+                'MET_RefTau',
+                'MET_RefMuon']
+
+    from MissingETD3PDMaker.MissingETD3PDObject import MissingETCompositionD3PDObject 
+    for coll in CustomMETCollections:
+        for flavor in METFlavors:
+            alg += MissingETD3PDObject (level=0,
+                                        sgkey = flavor+coll,
+                                        prefix='MET'+coll+flavor[3:],
+                                        allowMissing=True)
+            pass
+        alg += MissingETCompositionD3PDObject (level=4,
+                                               sgkey = 'MET_RefComposition'+coll,
+                                               suffix=coll[1:]+"_",
+                                               allowMissing = True,
+                                               exclude = [])
+
+
+    
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddMuonsToD3PD.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddMuonsToD3PD.py
new file mode 100644
index 0000000000000000000000000000000000000000..41d5668184367775a812f5d0f496eb46657650dc
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddMuonsToD3PD.py
@@ -0,0 +1,53 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+from PhotonD3PDMaker.PhotonD3PD import _args
+
+def AddMuonsToD3PD(alg,
+                   stacoMuonContainer="StacoMuonCollection",
+                   muidMuonContainer="MuidMuonCollection",
+                   caloMuonContainer="CaloMuonCollection",
+                   **kw):
+    #-------------------------------------------------------------------------------------
+    # Add some additional stuff to the muons beyond what's defined by default at level 0
+    import MuonD3PDMaker
+    from MuonD3PDMaker.MuonD3PDObject                    import MuonD3PDObject
+    from MuonD3PDMaker.MuonSegmentD3PDObject               import MuonSegmentD3PDObject
+    from MuonD3PDMaker.MuonTriggerBitsD3PDObject           import MuonTriggerBitsD3PDObject
+    if not MuonD3PDObject.allBlocknames().has_key("MuonScatteringAngleSignificance"):
+        from AthenaCommon.AppMgr import ToolSvc
+        muonScatteringSigTool=None
+        if hasattr(ToolSvc, "MuonScatteringSigTool"):
+            muonScatteringSigTool=ToolSvc.MuonScatteringSigTool
+        from JetTagD3PDMaker import MuonScatteringAngleSignificanceFillerTool
+        MuonD3PDObject.defineBlock (100, "MuonScatteringAngleSignificance",
+                                    MuonScatteringAngleSignificanceFillerTool,
+                                    ScatteringSigTool=muonScatteringSigTool) 
+    from RecExConfig.ObjKeyStore                  import cfgKeyStore
+    if (stacoMuonContainer != 'None' and cfgKeyStore.isInInput( "Analysis::MuonContainer", "StacoMuonCollection" )):
+        alg += MuonD3PDObject      (**_args (10, 'StacoMuon', kw,
+                                    sgkey=stacoMuonContainer, prefix='mu_staco_',
+                                    include = ["EFCBInfoIndex","EFMGInfoIndex", "EFMEInfoIndex"],
+                                    exclude = ["EFCBInfo", "EFMGInfo", "EFMEInfo", "L2CBInfo", "L1Info"],
+                                    allowMissing = True ))
+    else:
+        alg += MuonD3PDObject      (**_args (10, 'Muon'             , kw,
+                                             sgkey="Muons", prefix='mu_muon_',
+                                             include = ["EFCBInfoIndex","EFMGInfoIndex", "EFMEInfoIndex"],
+                                             exclude = ["EFCBInfo", "EFMGInfo", "EFMEInfo", "L2CBInfo", "L1Info"],
+                                             allowMissing = True ))
+
+    if (muidMuonContainer != 'None' and cfgKeyStore.isInInput( "Analysis::MuonContainer", "MuidMuonCollection" )):
+        alg += MuonD3PDObject      (**_args (10, 'MuidMuon', kw,
+                                    sgkey=muidMuonContainer, prefix='mu_muid_',
+                                    include = ["EFCBInfoIndex","EFMGInfoIndex", "EFMEInfoIndex"],
+                                    exclude = ["EFCBInfo", "EFMGInfo", "EFMEInfo", "L2CBInfo", "L1Info"],
+                                    allowMissing = True ))
+
+    if (caloMuonContainer != 'None'): 
+        alg += MuonD3PDObject      (**_args (10, 'CaloMuon', kw, 
+                                             sgkey=caloMuonContainer, prefix='mu_calo_', 
+                                             include = ["EFCBInfoIndex","EFMGInfoIndex", "EFMEInfoIndex"],
+                                             exclude = ["EFCBInfo", "EFMGInfo", "EFMEInfo", "L2CBInfo", "L1Info"],
+                                             allowMissing = True)) 
+    #-------------------------------------------------------------------------------------
+    
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddPhotonsToD3PD.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddPhotonsToD3PD.py
new file mode 100644
index 0000000000000000000000000000000000000000..61cea4d81392e95c3908f71731b3f5e8f7bfbf97
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddPhotonsToD3PD.py
@@ -0,0 +1,286 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+import PhotonD3PDMaker
+import D3PDMakerCoreComps
+import CaloD3PDMaker
+from PhotonD3PDMaker.PhotonD3PDMakerFlags            import PhotonD3PDMakerFlags
+from D3PDMakerCoreComps.IndexAssociation             import IndexAssociation
+from D3PDMakerCoreComps.IndexMultiAssociation        import IndexMultiAssociation
+from D3PDMakerCoreComps.SimpleAssociation            import SimpleAssociation
+from PhotonD3PDMaker.PhotonD3PD                      import _args
+from egammaD3PDMaker.PhotonD3PDObject                import PhotonD3PDObject
+from egammaD3PDMaker                                 import egammaDetailFillerTool
+from ROOT                                            import egammaParameters
+import egammaD3PDMaker
+import egammaD3PDAnalysis
+from D3PDMakerConfig.D3PDMakerFlags                  import D3PDMakerFlags
+from egammaD3PDMaker.defineBlockAndAlg               import defineAlgLODFunc, defineBlockAndAlg
+from AthenaCommon.AlgSequence import AlgSequence
+from AthenaCommon.AppMgr      import ToolSvc
+from AthenaCommon.Include     import include
+from D3PDMakerCoreComps.release_version              import at_least_version
+import TrackD3PDMaker
+from AthenaPython                                    import PyAthena
+from RecExConfig.RecFlags                            import rec
+from D3PDMakerCoreComps.resolveSGKey                 import testSGKey
+
+DVGetter = D3PDMakerCoreComps.SGDataVectorGetterTool
+
+PhotonUDPrefix = "PhotonD3PD::PhotonUDPrefix_"
+
+topo_iso_in_aod = at_least_version ('17.1.2') and not at_least_version ('17.3.0')
+
+def AddPhotonsToD3PD(alg, **kw):
+    from AthenaCommon.AppMgr      import ToolSvc
+    preseq = AlgSequence(D3PDMakerFlags.PreD3PDAlgSeqName())
+
+    # jet associations
+    for i in PhotonD3PDMakerFlags.JetCollections():
+
+        collection_name = "jet_"+i+"_"
+        from PhotonD3PDMaker.DREtAssociation        import DREtAssociation
+        PhotonJetD3PDAssoc = DREtAssociation (PhotonD3PDObject,
+                                              'JetCollection',
+                                              i,
+                                              0.4,
+                                              collection_name,
+                                              level = 1,
+                                              blockname = 'PhotonJetMatch_'+i)
+        PhotonJetD3PDAssoc.defineBlock (1, 'PhotonJetIndex_'+i,
+                                        D3PDMakerCoreComps.IndexFillerTool,
+                                        Target = collection_name)
+        
+
+    # some other random stuff
+    from egammaD3PDMaker.PhotonD3PDObject import PhotonClusterAssoc
+    from CaloD3PDMaker                    import ClusterTimeFillerTool
+    PhotonClusterAssoc.defineBlock(2, 'Time', ClusterTimeFillerTool)
+    PhotonClusterAssoc.defineBlock(2, '', PhotonD3PDMaker.ShowerRadiusFillerTool)
+ 
+    CellGetter = DVGetter ('PhotonSelectedCellGetter', 
+                           TypeName = 'CaloCellContainer', 
+                           SGKey = PhotonD3PDMakerFlags.SelectedCellsContainerName())
+    ToolSvc += CellGetter
+    PhotonCellAssoc = IndexMultiAssociation(PhotonClusterAssoc,
+                                            CaloD3PDMaker.CaloClusterExtendedCellAssociationTool,
+                                            "cell_",
+                                            level=2,
+                                            prefix="cell_",
+                                            blockname = 'ClusterExtendedCells',
+                                            allowMissing = True,
+                                            Getter = CellGetter,
+                                            DRCut=PhotonD3PDMakerFlags.CellDrCut())
+    
+    PhotonD3PDObject.defineBlock(2, "CoNoise",
+                                 egammaDetailFillerTool,
+                                 Details = [egammaParameters.etconoisedR04Sig2, 'etconoisedR04Sig2',
+                                            egammaParameters.etconoisedR04Sig3, 'etconoisedR04Sig3']);
+
+
+    # Some tools for topocluster isolatoin
+    from egammaCaloTools.egammaTopoIsoToolBase   import egammaTopoIsoToolBase
+    egammaCalTopoIsoTool = egammaTopoIsoToolBase("egammaCalTopoIsoToolBase")
+    egammaCalTopoIsoTool.UseEMScale = False
+    egammaTopoIsoTool = egammaTopoIsoToolBase("egammTopoIsoToolBase")
+
+    if egammaTopoIsoTool not in ToolSvc:
+        ToolSvc += egammaTopoIsoTool
+    if egammaCalTopoIsoTool not in ToolSvc:
+        ToolSvc += egammaCalTopoIsoTool
+
+    #----------------------------------------------
+    # TopoCluster isolation variables, requested by Sandrine, Jean-Baptiste, and Jessica
+
+    # Add additional TopoCluster Isolation variables
+    # -- first, schedule them to be calculated
+    ClusterTopoIsoGetter = DVGetter('egammaTopoAlgClusterGetter',
+                                    TypeName = 'CaloClusterContainer',
+                                    SGKey = D3PDMakerFlags.ClusterSGKey())
+    PhotonTopoIsoGetter = DVGetter('ph_egammaTopoEMIsoAlgEgammaGetter',
+                                   TypeName = 'PhotonContainer',
+                                   SGKey = D3PDMakerFlags.PhotonSGKey())
+    # calibrated clusters
+    preseq += egammaD3PDAnalysis.egammaTopoIsoAlg("ph_egammaTopoCalIsoAlg",
+                                                  EgammaGetter = PhotonTopoIsoGetter,
+                                                  ClusterGetter = ClusterTopoIsoGetter,
+                                                  TopoIsoTool = egammaCalTopoIsoTool,
+                                                  UseEMScale = False,
+                                                  ConeSizes = [.20, .30, .40, .50, .60],
+                                                  AllowMissing = False,
+                                                  UDPrefix = PhotonUDPrefix)
+    # positive, uncalibrated clusters
+    preseq += egammaD3PDAnalysis.egammaTopoIsoAlg("ph_egammaTopoPosEMIsoAlg",
+                                                  EgammaGetter = PhotonTopoIsoGetter,
+                                                  ClusterGetter = ClusterTopoIsoGetter,
+                                                  TopoIsoTool = egammaTopoIsoTool,
+                                                  UseEMScale = True,
+                                                  PositiveEnergyClusters = True,
+                                                  ConeSizes = [.20, .30, .40, .50, .60],
+                                                  AllowMissing = False,
+                                                  UDPrefix = PhotonUDPrefix)
+    # positive, calibrated clusters
+    preseq += egammaD3PDAnalysis.egammaTopoIsoAlg("ph_egammaTopoPosCalIsoAlg",
+                                                  EgammaGetter = PhotonTopoIsoGetter,
+                                                  ClusterGetter = ClusterTopoIsoGetter,
+                                                  TopoIsoTool = egammaCalTopoIsoTool,
+                                                  UseEMScale = False,
+                                                  PositiveEnergyClusters = True,
+                                                  ConeSizes = [.20, .30, .40, .50, .60],
+                                                  AllowMissing = False,
+                                                  UDPrefix = PhotonUDPrefix)
+    # --- now fill them
+    PhotonD3PDObject.defineBlock (2, 'PhotonD3PD_PhotonUDExtraTopoCones',
+                                  D3PDMakerCoreComps.UserDataFillerTool,
+                                  UDPrefix = PhotonUDPrefix,
+                                  Vars = ['topoCalEtcone20', '', 'float',
+                                          'topoCalEtcone30', '', 'float',
+                                          'topoCalEtcone40', '', 'float',
+                                          'topoCalEtcone50', '', 'float',
+                                          'topoCalEtcone60', '', 'float',
+                                          'topoPosEtcone20', '', 'float',
+                                          'topoPosEtcone30', '', 'float',
+                                          'topoPosEtcone40', '', 'float',
+                                          'topoPosEtcone50', '', 'float',
+                                          'topoPosEtcone60', '', 'float',
+                                          'topoPosCalEtcone20', '', 'float',
+                                          'topoPosCalEtcone30', '', 'float',
+                                          'topoPosCalEtcone40', '', 'float',
+                                          'topoPosCalEtcone50', '', 'float',
+                                          'topoPosCalEtcone60', '', 'float',
+                                          ])
+    #----------------------------------------------
+
+    
+    #----------------------------------------------
+    # Temporarily add back in missing variables for Jean-Francois, while we wait
+    # for Scott to fix something else.
+    from egammaD3PDMaker.PhotonD3PDObject import ConversionVertexTrackTrackParticleAssociation
+                                  
+    from PhotonAnalysisUtils.PhotonAnalysisUtilsConf import PAU_ToT_tool
+    ToTTool = PAU_ToT_tool(	name = "ToTTool" )
+    ToolSvc += ToTTool
+
+    from PhotonAnalysisUtils.PAU_AtlasExtrapolator import PAU_AtlasExtrapolator
+    theAtlasExtrapolator = PAU_AtlasExtrapolator()
+
+    from PhotonAnalysisUtils.PAU_ExtrapolateToCaloTool import PAU_ExtrapolateToCaloTool
+    exToCalo = PAU_ExtrapolateToCaloTool(theAtlasExtrapolator = theAtlasExtrapolator)
+
+    preseq += egammaD3PDAnalysis.ConversionTrackParticleCalculatorAlg("ConversionTrackParticleCalculator", 
+                                                                      PhotonGetter = DVGetter ('ConversionVertexTrackParticlePhotonGetter', 
+                                                                                               TypeName = 'PhotonContainer', 
+                                                                                               SGKey = D3PDMakerFlags.PhotonSGKey()), 
+                                                                      PAU_ToT_tool = ToTTool, 
+                                                                      ExtrapolateToCaloTool = exToCalo, 
+                                                                      UDPrefix        = PhotonUDPrefix) 
+    
+    ConversionVertexTrackTrackParticleAssociation.defineBlock(0, 'ConversionVertexTrackVariables', 
+                                                              D3PDMakerCoreComps.UserDataFillerTool, 
+                                                              UDPrefix=PhotonUDPrefix, 
+                                                              Vars = ['ToT'                , '', 'float', 
+                                                                      'DeltaEta_track_calo', '', 'float', 
+                                                                      'DeltaPhi_track_calo', '', 'float'])
+    
+    # Track parameters at conversion vertex
+    from D3PDMakerCoreComps.ContainedVectorMultiAssociation import ContainedVectorMultiAssociation
+    from egammaD3PDMaker.PhotonD3PDObject import ConversionVertexAssociation
+
+    VxTrackAtConversionVertexAssociationTool = ContainedVectorMultiAssociation(ConversionVertexAssociation,
+                                                                               PhotonD3PDMaker.VxTrackAtVertexAssociationTool,
+                                                                               prefix="paramsAtConvVtx_")
+    ConversionVertexTrackTrackParticlePerigeeAtVertexAssociationTool = SimpleAssociation(VxTrackAtConversionVertexAssociationTool,
+                                                                                         PhotonD3PDMaker.ConversionPerigeeAssociationTool)
+    ConversionVertexTrackTrackParticlePerigeeAtVertexAssociationTool.defineBlock (1, 'Trk',
+                                                                                  TrackD3PDMaker.PerigeeFillerTool)
+    TrackParticleCovarAssoc = SimpleAssociation (ConversionVertexTrackTrackParticlePerigeeAtVertexAssociationTool,
+                                                 TrackD3PDMaker.PerigeeCovarianceAssociationTool)
+    TrackParticleCovarAssoc.defineBlock (3, 'TrkCovDiag',
+                                         TrackD3PDMaker.CovarianceFillerTool,
+                                         IsTrackPerigee = True,
+                                         Error = False,
+                                         DiagCovariance = True)
+    TrackParticleCovarAssoc.defineBlock (3, 'TrkCovOffDiag',
+                                         TrackD3PDMaker.CovarianceFillerTool,
+                                         IsTrackPerigee = True,
+                                         Error = False,
+                                         OffDiagCovariance = True)
+    
+    #  NeutralPerigee parameters 
+    from InDetSecVxFinderTool.InDetSecVxFinderToolConf import InDet__InDetJetFitterUtils
+    conversionUtils = InDet__InDetJetFitterUtils(name                   = "conversionUtils",
+                                                 LinearizedTrackFactory = None,
+                                                 Extrapolator           = None)
+    ToolSvc += conversionUtils
+
+    NeutralPerigeeAtConversionVertexAssociationTool = SimpleAssociation(ConversionVertexAssociation,
+                                                                        PhotonD3PDMaker.ConversionNeutralPerigeeAssociationTool,
+                                                                        ConversionUtils = conversionUtils,
+                                                                        prefix="neutralParamsAtConvVtx_")
+    NeutralPerigeeAtConversionVertexAssociationTool.defineBlock (1, 'TrkNP',
+                                                                 PhotonD3PDMaker.NeutralPerigeeFillerTool)
+    NeutralTrackParticleCovarAssoc = SimpleAssociation (NeutralPerigeeAtConversionVertexAssociationTool,
+                                                        PhotonD3PDMaker.NeutralPerigeeCovarianceAssociationTool)
+    NeutralTrackParticleCovarAssoc.defineBlock (3, 'TrkCovDiagNP',
+                                                TrackD3PDMaker.CovarianceFillerTool,
+                                                IsTrackPerigee = True,
+                                                Error = False,
+                                                DiagCovariance = True)
+    NeutralTrackParticleCovarAssoc.defineBlock (3, 'TrkCovOffDiagNP',
+                                                TrackD3PDMaker.CovarianceFillerTool,
+                                                IsTrackPerigee = True,
+                                                Error = False,
+                                                OffDiagCovariance = True)
+    #----------------------------------------------
+
+
+    from egammaD3PDMaker.PhotonD3PDObject import PhotonTopoD3PDAssoc
+    PhotonTopoD3PDAssoc.defineBlock (1, 'PhotonTopoKinematicsEM',
+                                     PhotonD3PDMaker.ClusterFillerTool, 
+                                     Prefix = "EMsamplings_",
+                                     UseCaloSamplings = [0,1,2,3,4,5,6,7])
+    PhotonTopoD3PDAssoc.defineBlock (1, 'PhotonTopoKinematicsUncalibratedEM',
+                                     PhotonD3PDMaker.ClusterFillerTool, 
+                                     Prefix = "EMsamplings_uncalibrated_",
+                                     SignalState = PyAthena.P4SignalState.UNCALIBRATED,
+                                     UseCaloSamplings = [0,1,2,3,4,5,6,7])
+
+
+    # now, add in some truth associations
+    if rec.doTruth():
+        # construct an association tool from an egamma* object to a genparticle
+        # for now, at least, needs to use the PAU tools for object matching
+        from PhotonAnalysisUtils.PAU_AtlasExtrapolator import PAU_AtlasExtrapolator
+        theAtlasExtrapolator = PAU_AtlasExtrapolator()
+
+        from PhotonAnalysisUtils.PAU_ExtrapolateToCaloTool import PAU_ExtrapolateToCaloTool
+        exToCalo = PAU_ExtrapolateToCaloTool(theAtlasExtrapolator = theAtlasExtrapolator)
+
+        from PhotonAnalysisUtils.TruthTools import TruthToolsWrapper
+        PAUtruthTool = TruthToolsWrapper(exToCalo)
+
+        PAUPhotonTruthParticleAssociationTool = IndexAssociation(PhotonD3PDObject,
+                                                                 PhotonD3PDMaker.TruthParticleAssociationTool,
+                                                                 target="mc_",
+                                                                 prefix="mc_",
+                                                                 level=1,
+                                                                 blockname="PAUPhotonTruthParticleAssociationTool",
+                                                                 allowMissing=False,
+                                                                 PAUtruthTool = PAUtruthTool)
+
+        PAUPhotonEgammaTruthParticleAssociationTool = IndexAssociation(PhotonD3PDObject,
+                                                                       PhotonD3PDMaker.TruthParticleAssociationTool,
+                                                                       target="egammaTruth_",
+                                                                       prefix='egammaTruth_',
+                                                                       level=1,
+                                                                       blockname="PAUPhotonEgammaTruthParticleAssociationTool",
+                                                                       allowMissing=False,
+                                                                       PAUtruthTool = PAUtruthTool)
+
+    conversion_track_collection_name="trk"
+    GSFTrackParticlesInSample = testSGKey ('Rec::TrackParticleContainer', "GSFTrackParticleCandidate")
+    if GSFTrackParticlesInSample: 
+        conversion_track_collection_name = "GSF_trk" 
+    alg += PhotonD3PDObject(**_args (20, 'Photon', kw,
+                                     ConversionVertexTrackIndex_target = conversion_track_collection_name,
+                                     include=["SumCellsGain", "NbCellsGain"]))
+    
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddTrackFilter.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddTrackFilter.py
new file mode 100644
index 0000000000000000000000000000000000000000..8bd1c8cb26b102afd315e74989183e1068fda0b6
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddTrackFilter.py
@@ -0,0 +1,65 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+from AthenaCommon.AlgSequence import AlgSequence
+import D3PDMakerCoreComps
+import PhotonD3PDMaker
+from D3PDMakerConfig.D3PDMakerFlags                  import D3PDMakerFlags
+from PhotonD3PDMaker.PhotonD3PDMakerFlags            import PhotonD3PDMakerFlags
+
+DVGetter = D3PDMakerCoreComps.SGDataVectorGetterTool
+
+def AddTrackFilter(outputsgkey = "SelectedTracks",
+                   seq = AlgSequence(),
+                   GSFTrackParticlesInSample = False):
+
+    from AthenaCommon.AppMgr      import ToolSvc
+
+    # This is a filter for tracks near photon candidates.  It will look in a region around
+    # the photon, and dump the track information for all tracks that fall inside that region.
+    print "DumpAllTracks = False and DumpNearbyTracks = True...  dumping nearby tracks."
+
+    photongetter = DVGetter('photontrackfilter_Getter',
+                            TypeName = 'PhotonContainer',
+                            SGKey = D3PDMakerFlags.PhotonSGKey())
+    ToolSvc += photongetter
+
+    electrongetter = DVGetter('electrontrackfilter_Getter',
+                              TypeName = 'ElectronContainer',
+                              SGKey = D3PDMakerFlags.ElectronSGKey())
+    ToolSvc += electrongetter
+
+    gsfgetter = DVGetter('gsftracktrackfilter_Getter',
+                         TypeName = 'Rec::TrackParticleContainer',
+                         SGKey = "GSFTrackParticleCandidate")
+    ToolSvc += gsfgetter
+    
+    muongetter = DVGetter('muontrackfilter_Getter',
+                          TypeName = 'Analysis::MuonContainer',
+                          SGKey = D3PDMakerFlags.MuonSGKey())
+    ToolSvc += muongetter
+
+
+    gsfassocgetter = D3PDMakerCoreComps.SGObjGetterTool('GSFTPAssocGetter',
+                                                        SGKey = D3PDMakerFlags.GSFTrackAssocSGKey(),
+                                                        TypeName = 'TrackParticleAssocs')
+    ToolSvc += gsfassocgetter
+
+    from ROOT import egammaPID
+    trackfilter = PhotonD3PDMaker.TrackFilter(InputTrackCollectionName = "TrackParticleCandidate",
+                                              OutputTrackCollectionName = "SelectedTracks",
+                                              photonGetter = photongetter,
+                                              electronGetter = electrongetter,
+                                              CheckGSFTracks=GSFTrackParticlesInSample,
+                                              GSFTrackParticleGetter = gsfgetter,
+                                              GSFAssocGetter = gsfassocgetter,
+                                              muonGetter = muongetter,
+                                              ptCut = 12000.,
+                                              etaCut = 2.5,
+                                              deltaRCut = 0.6,
+                                              photonIsEM = egammaPID.PhotonLoose,
+                                              electronIsEM = egammaPID.ElectronTight,
+                                              storePerpendicularTracks = True,
+                                              FilterTracksForMET = PhotonD3PDMakerFlags.FilterTracksForMET())
+
+    seq += trackfilter
+    
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddTracksToD3PD.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddTracksToD3PD.py
new file mode 100644
index 0000000000000000000000000000000000000000..ad1ec3d147de19dba51fffceda27d65aef2bb39a
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddTracksToD3PD.py
@@ -0,0 +1,104 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+from AthenaCommon.AlgSequence import AlgSequence
+import D3PDMakerCoreComps
+import PhotonD3PDMaker
+from D3PDMakerCoreComps.SimpleAssociation            import SimpleAssociation
+
+from TrackD3PDMaker.TrackD3PDObject import TrackD3PDObject
+from PhotonD3PDMaker.PhotonTrackD3PDObject import PhotonTrackParticleD3PDObject
+from TrackD3PDMaker import TrackParticleVertexAssociationTool
+from D3PDMakerCoreComps.resolveSGKey                 import testSGKey
+from D3PDMakerConfig.D3PDMakerFlags                  import D3PDMakerFlags
+from D3PDMakerCoreComps.IndexAssociation             import IndexAssociation
+from TrackD3PDMaker.TrackD3PDMakerFlags              import TrackD3PDFlags
+from PhotonD3PDMaker.PhotonD3PDMakerFlags            import PhotonD3PDMakerFlags
+
+def AddTracksToD3PD(alg):
+    
+    # taken from TrackD3PDObject.py...  we only need to change the "vertexTarget/Prefix" stuff.
+    TrackParticleD3PDObject = TrackD3PDObject(_label='trk',
+                                              _prefix='trk_',
+                                              _sgkey=D3PDMakerFlags.TrackSGKey(),
+                                              _object_name='TrackParticleD3PDObject',
+                                              typeName='Rec::TrackParticleContainer',
+                                              vertexTarget='PV_',
+                                              vertexPrefix='PV_',
+                                              vertexSGKey='VxPrimaryCandidate',
+                                              truthTarget='mc',
+                                              truthPrefix='mc_',
+                                              detailedTruthPrefix='detailed_mc_',
+                                              truthMapKey='TrackParticleTruthCollection',
+                                              SGKeyForTruth=D3PDMakerFlags.TrackSGKey(),
+                                              detailedTruthMapKey='DetailedTrackTruth',
+                                              SGKeyForDetailedTruth='Tracks',
+                                              flags=TrackD3PDFlags)
+    
+    convTrackAssociation = SimpleAssociation \
+                           (TrackParticleD3PDObject,
+                            TrackParticleVertexAssociationTool,
+                            prefix = 'conv_',
+                            blockname='ConversionTrackParticle',
+                            VxSGKey='ConversionCandidate')
+
+    
+    GSFTrackParticlesInSample = testSGKey ('Rec::TrackParticleContainer', "GSFTrackParticleCandidate")
+
+    # we pretty much always want the GSF-refit tracks.
+    if GSFTrackParticlesInSample:
+        GSFTrackParticleD3PDObject = TrackD3PDObject(_label='trk',
+	                                             _prefix='trk_',
+	                                             _sgkey=D3PDMakerFlags.TrackSGKey(),
+	                                             _object_name='GSFTrackParticleD3PDObject',
+	                                             typeName='Rec::TrackParticleContainer',
+	                                             vertexTarget='PV_',
+	                                             vertexPrefix='PV_',
+	                                             vertexSGKey='VxPrimaryCandidate',
+	                                             truthTarget='mc',
+	                                             truthPrefix='mc_',
+	                                             detailedTruthPrefix='detailed_mc_',
+	                                             truthMapKey='GSFTrackParticleTruthCollection',
+	                                             SGKeyForTruth="GSFTrackParticleCandidate",
+	                                             detailedTruthMapKey='DetailedTrackTruth',
+	                                             SGKeyForDetailedTruth='Tracks',
+	                                             flags=TrackD3PDFlags) 
+
+        # add a flag for conversion tracks
+        convTrackAssociation = SimpleAssociation \
+                               (GSFTrackParticleD3PDObject,
+                                TrackParticleVertexAssociationTool,
+                                prefix = 'GSF_conv_',
+                                blockname='ConversionTrackParticle',
+                                VxSGKey='AllPhotonsVxCandidates')
+        
+        origTrackAssociation = IndexAssociation \
+                               (GSFTrackParticleD3PDObject,
+                                PhotonD3PDMaker.GSFOriginalTrackParticleAssociationTool,
+                                target="trk",
+                                prefix="trk_",
+                                level=0,
+                                blockname="GSFOriginalTPAssoc",
+                                allowMissing=False,
+                                AssocGetter = D3PDMakerCoreComps.SGObjGetterTool
+                                ('GSFAssocGetter',
+                                 SGKey = D3PDMakerFlags.GSFTrackAssocSGKey(),
+                                 TypeName = 'TrackParticleAssocs'))
+
+        alg += GSFTrackParticleD3PDObject (0,
+                                           sgkey="GSFTrackParticleCandidate",
+                                           label="GSF_trk",
+                                           prefix="GSF_trk_")
+
+    if PhotonD3PDMakerFlags.DumpAllTracks():
+        alg += TrackParticleD3PDObject (4, sgkey="TrackParticleCandidate")
+        
+    elif PhotonD3PDMakerFlags.DumpNearbyTracks():
+        from PhotonD3PDMaker.AddTrackFilter import AddTrackFilter
+        preseq = AlgSequence(D3PDMakerFlags.PreD3PDAlgSeqName())
+        AddTrackFilter("SelectedTracks", preseq, GSFTrackParticlesInSample)
+        
+        alg += TrackParticleD3PDObject       (0, sgkey="SelectedTracks")
+        alg += PhotonTrackParticleD3PDObject (0, sgkey="SelectedTracks")
+
+    else:
+        print "DumpAllTracks = False and DumpNearbyTracks = False...  not dumping any tracks."
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddTriggerToD3PD.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddTriggerToD3PD.py
new file mode 100644
index 0000000000000000000000000000000000000000..03eb785ce4eb9547e329e4043c2d8341313a6df6
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddTriggerToD3PD.py
@@ -0,0 +1,48 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+from PhotonD3PDMaker.PhotonD3PDMakerFlags import PhotonD3PDMakerFlags
+from PhotonD3PDMaker.PhotonD3PD import _args
+
+def AddTriggerToD3PD(alg, **kw):
+    # trigger objects info: to be used for matching offline photons to trigger objects and know the trigger decision
+    if PhotonD3PDMakerFlags.DumpTriggerObjectsInfo():
+        from TriggerD3PDMaker.TrigDecisionD3PDObject import TrigDecisionD3PDObject
+        alg += TrigDecisionD3PDObject (**_args (2, 'TrigDecision', kw))
+        from TrigEgammaD3PDMaker.TrigEgammaD3PD              import TrigEgammaD3PDObjects
+        TrigEgammaD3PDObjects (alg, **_args (1, 'TrigEgamma', kw))
+        from TrigMuonD3PDMaker.TrigMuonD3PD           import TrigMuonD3PDObjects
+        TrigMuonD3PDObjects   (alg, 1,
+                               TrigMuonEFIsolation_allowMissing = True) 
+        
+    if PhotonD3PDMakerFlags.DumpLotsOfTriggerInfo():
+        from TriggerD3PDMaker.EnergySumROID3PDObject import EnergySumROID3PDObject
+        from TrigMissingETD3PDMaker.TrigMETD3PDObject import TrigMETD3PDObject
+        from MissingETD3PDMaker.MissingETD3PDTriggerBitsObject import METD3PDTriggerBitsObject
+        
+        alg += EnergySumROID3PDObject(**_args ( 1, 'EnergySumROI', kw,
+                                                prefix = "trig_L1_esum_",
+                                                allowMissing = True))
+        
+        # The LVL2 information:
+        # does this need to be at a higher level?
+        alg += TrigMETD3PDObject(**_args( 1, 'TrigMETL2', kw,
+                                          prefix = "trig_L2_met_",
+                                          sgkey = "HLT_T2MissingET" ))
+        
+        # The EF information:
+        alg += TrigMETD3PDObject(**_args ( 1, 'TrigMETEF', kw,
+                                           prefix = "trig_EF_met_",
+                                           sgkey = "HLT_TrigEFMissingET" ))
+        
+        
+        alg += METD3PDTriggerBitsObject       (**_args ( 0, 'METTriggerBits', kw))
+        
+        from TriggerD3PDMaker.BGCodeD3PDObject import BGCodeD3PDObject
+        alg += BGCodeD3PDObject (**_args (1, 'BGCode', kw))
+        
+        from RecExConfig.ObjKeyStore                  import cfgKeyStore
+        if cfgKeyStore.isInInputFile( "TrigMissingETContainer", "HLT_L2MissingET_FEB" ):
+            alg += TrigMETD3PDObject(**_args( 1, 'TrigMETL2_FEB', kw,
+                                              prefix = "trig_L2_feb_met_",
+                                              sgkey = "HLT_L2MissingET_FEB" ))
+            
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddTruthToD3PD.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddTruthToD3PD.py
new file mode 100644
index 0000000000000000000000000000000000000000..cf6ce72960426a17d43855c71f8e323b3db621ca
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/AddTruthToD3PD.py
@@ -0,0 +1,148 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+import PhotonD3PDMaker
+from PhotonD3PDMaker.PhotonD3PDMakerFlags            import PhotonD3PDMakerFlags
+from AthenaCommon.AlgSequence                        import AlgSequence
+from D3PDMakerConfig.D3PDMakerFlags                  import D3PDMakerFlags
+from PhotonD3PDMaker.PhotonD3PD                      import _args
+from JetD3PDMaker.JetD3PDObject                      import JetD3PDObject
+from JetTagD3PDMaker.JetTagD3PDMakerKeys             import JetTagD3PDKeys
+
+def AddTruthToD3PD(alg, **kw):
+    from AthenaCommon.AppMgr      import ToolSvc
+    preseq = AlgSequence(D3PDMakerFlags.PreD3PDAlgSeqName())
+
+    # first things first: fix the truth bug
+    
+    from McParticleAlgs.ReOrderMcEventCollection import  FixMcEventCollection
+    topSequence = AlgSequence()
+    topSequence.Members.insert(1, FixMcEventCollection() )
+
+    D3PDMakerFlags.TruthDoPileup     = False
+    D3PDMakerFlags.TruthWritePartons = True
+    D3PDMakerFlags.TruthWriteHadrons = False
+    D3PDMakerFlags.TruthWriteGeant   = False
+
+    if PhotonD3PDMakerFlags.SaveAllTruthParticles():
+      D3PDMakerFlags.TruthWriteHadrons = True
+
+    # These give us a bit too much
+    # from MuonD3PDMaker.TruthMuonD3PDObject               import TruthMuonD3PDObject
+    # alg += TruthMuonD3PDObject    (**_args (1, 'TruthMuon', kw))
+    # truth_info = TruthParticleD3PDObject(**_args (1, 'TruthParticle', kw))
+
+    # ------------------------------------------
+    # GenEvent dumping
+    #
+    import TruthD3PDAnalysis
+    from TruthD3PDAnalysis.TruthD3PDAnalysisConf import D3PD__GenObjectsFilterTool
+    SimpleGenEventFilterTool = D3PD__GenObjectsFilterTool( "SimpleGenEventFilterTool" )
+    SimpleGenEventFilterTool.RemoveInTimePileUp = True
+    SimpleGenEventFilterTool.Remove2BCPileUp    = True
+    SimpleGenEventFilterTool.Remove800nsPileUp  = True
+    SimpleGenEventFilterTool.RemoveCavernBkg    = True
+    SimpleGenEventFilterTool.RemoveDummyEvents  = True
+    ToolSvc += SimpleGenEventFilterTool
+
+    from TruthD3PDMaker.GenEventD3PDObject      import GenEventD3PDObject
+    alg += GenEventD3PDObject     (**_args (1, 'GenEvent', kw,
+                                            filter=SimpleGenEventFilterTool))
+    # ------------------------------------------
+
+    PhotonTruthCutTool = PhotonD3PDMaker.TruthParticleFilterCutTool(name   = "PhotonTruthCutTool",
+                                                                    PDG_IDs = [22],
+                                                                    pT_low = 1000,
+                                                                    eta_high = 2.5)
+    
+    ElectronTruthCutTool = PhotonD3PDMaker.TruthParticleFilterCutTool(name   = "ElectronTruthCutTool",
+                                                                      PDG_IDs = [11],
+                                                                      pT_low = 1000,
+                                                                      eta_high = 2.5)
+    
+    MuonTruthCutTool = PhotonD3PDMaker.TruthParticleFilterCutTool(name   = "MuonTruthCutTool",
+                                                                  PDG_IDs = [13])
+
+    TauTruthCutTool = PhotonD3PDMaker.TruthParticleFilterCutTool(name   = "TauTruthCutTool",
+                                                                 PDG_IDs = [15,17])
+
+    BosonTruthCutTool = PhotonD3PDMaker.TruthParticleFilterCutTool(name = "BosonTruthCutTool",
+                                                                   PDG_IDs = [23, 24, 25, 32, 33, 34, 35, 36, 37])
+
+    PhotonD3PDMakerFlags.TruthParticleFilters = [PhotonTruthCutTool,
+                                                 ElectronTruthCutTool,
+                                                 MuonTruthCutTool,
+                                                 TauTruthCutTool,
+                                                 BosonTruthCutTool]
+
+    for i in PhotonD3PDMakerFlags.TruthParticleFilters():
+        if not i in ToolSvc:
+            ToolSvc += i
+
+    doSortTruthParticles = False
+    TP_container_name = 'TruthParticle'
+    if doSortTruthParticles:
+        # sort the truth particles before dumping them - probably not necessary
+        TP_container_name = 'SortedTruthParticles'
+        sorter =  makeTruthParticleSorterAlg(D3PDMakerFlags.TruthSGKey(),
+                                             'TruthParticleContainer',
+                                             TP_container_name)
+        preseq += sorter
+        D3PDMakerFlags.TruthParticlesSGKey = 'SortedTruthParticles,'+D3PDMakerFlags.TruthParticlesSGKey()
+        
+    from PhotonD3PDMaker.PhotonTruthParticleD3PDObject   import PhotonTruthParticleD3PDObject
+    truthdump = PhotonTruthParticleD3PDObject(**_args (2, TP_container_name, kw))
+    alg += truthdump
+
+    from TrackD3PDMaker.TruthVertexD3PDObject import TruthVertexD3PDObject
+    alg += TruthVertexD3PDObject(**_args (0, 'TruthVertex', kw))
+
+    from PhotonD3PDMaker.EgammaTruthParticleD3PDObject import EgammaTruthParticleD3PDObject
+    egammatruthdump = EgammaTruthParticleD3PDObject(**_args (2, "FilteredEgammaTruthObject", kw,
+                                                       sgkey = "FilteredEgammaTruthCollection",
+                                                       prefix = "egammaTruth_"))
+    alg += egammatruthdump
+    # ---------------------------------------------------------------------------------
+
+    # ------------------------------------------------
+    # add the TruthJet D3PDObjects
+    for truthjets in PhotonD3PDMakerFlags.alltruthjets():
+        alg += JetD3PDObject(**_args (1, truthjets, kw,
+                                      prefix="jet_"+truthjets+"_",
+                                      sgkey=truthjets+PhotonD3PDMakerFlags.JetTagD3PD_CollectionPostfix(),
+                                      exclude=['DQMoments',
+                                               'JetSamplingsFrac',
+                                               'JetQual',
+                                               'EMFraction',
+                                               'JES',
+                                               'JESMoments',
+                                               'EMScale',
+                                               'L1Info',
+                                               'L2Info',
+                                               'EFInfo'],
+                                      include=['Kinematics',
+                                               JetTagD3PDKeys.TruthInfoBlockName(),
+                                               'JetShape']))
+    # ------------------------------------------------
+
+    from TauD3PDMaker.TauD3PDMakerConf import TruthTausToSG
+    preseq += TruthTausToSG()
+    
+    from EventCommonD3PDMaker.DRIndexAssociation import DRIndexAssociation
+    from TauD3PDMaker.TruthTauD3PDObject         import TruthTauD3PDObject
+    from TauD3PDMaker.TauD3PDObject              import TauD3PDObject
+    TauTrueTauAssoc = DRIndexAssociation(
+        parent = TauD3PDObject,
+        type_name = 'TruthParticleContainer',
+        default_sgkey = 'TrueHadronicTaus',
+        default_drcut = 0.2,
+        prefix = 'trueTauAssocSmall_',
+        target = 'trueTau_' )
+    
+    TrueTauTauAssoc = DRIndexAssociation(
+        parent = TruthTauD3PDObject,
+        type_name = 'Analysis::TauJetContainer',
+        default_sgkey = D3PDMakerFlags.TauSGKey(),
+        default_drcut = 0.2,
+        prefix = 'tauAssocSmall_',
+        target = 'tau_' )
+    alg += TruthTauD3PDObject(10, sgkey = 'TrueHadronicTaus')
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/ComputePointingQuantities.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/ComputePointingQuantities.py
new file mode 100644
index 0000000000000000000000000000000000000000..791a9a4bb341a140dfd355d8977ae15c77c14cb7
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/ComputePointingQuantities.py
@@ -0,0 +1,41 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+from AthenaCommon.AppMgr      import ToolSvc
+
+from egammaTools.EMClusterErrorsToolFactory import EMClusterErrorsToolFact
+theemclustererrorstool=EMClusterErrorsToolFact("EMClusterErrorsTool")
+ToolSvc += theemclustererrorstool
+
+from CaloDetDescr.CaloDepthToolBase import CaloDepthToolFactory
+thepauextrapolcaloconvCaloDepthTool = CaloDepthToolFactory(depth='cscopt2')
+ToolSvc += thepauextrapolcaloconvCaloDepthTool
+
+from CaloDetDescr.CaloDepthToolBase import CaloDepthToolFactory
+theemextrapolcaloconvCaloDepthTool = CaloDepthToolFactory(depth='cscopt2')
+ToolSvc += theemextrapolcaloconvCaloDepthTool
+    
+from egammaTrackTools.egammaTrackToolsConf import EMExtrapolCaloConversion
+theemextrapolcaloconversion = EMExtrapolCaloConversion(CalorimeterDepth = theemextrapolcaloconvCaloDepthTool.getFullName())
+ToolSvc += theemextrapolcaloconversion
+
+from PhotonAnalysisUtils.PhotonAnalysisUtilsConf import ExtrapolCaloConversion
+thepauextrapolcaloconversion = ExtrapolCaloConversion(CalorimeterDepth = thepauextrapolcaloconvCaloDepthTool.getFullName())
+ToolSvc += thepauextrapolcaloconversion
+
+from egammaCaloTools.egammaCaloToolsConf import egammaqpoint
+theegammaqpoint=egammaqpoint("egammaQpoint",
+                             CalorimeterDepth=thepauextrapolcaloconvCaloDepthTool.getName() )
+theegammaqpoint += thepauextrapolcaloconvCaloDepthTool
+ToolSvc+=theegammaqpoint 
+
+from PhotonAnalysisUtils.PhotonAnalysisUtilsConf import ComputePointingQuantities
+PAUComputePointingQuantities = ComputePointingQuantities( name = "PAUComputePointingQuantities")
+PAUComputePointingQuantities.EMErrorDetailContainerName = "egDetailAOD"
+PAUComputePointingQuantities.EMExtrapolCaloConversion  = theemextrapolcaloconversion
+PAUComputePointingQuantities.PAUExtrapolCaloConversion = thepauextrapolcaloconversion
+PAUComputePointingQuantities.EMClusterErrorsTool       = theemclustererrorstool
+PAUComputePointingQuantities.CaloPointingTool          = theegammaqpoint
+PAUComputePointingQuantities.CalorimeterDepth          = thepauextrapolcaloconvCaloDepthTool.getName()
+
+ToolSvc += PAUComputePointingQuantities
+    
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/ConfigureTaggingOptions.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/ConfigureTaggingOptions.py
new file mode 100644
index 0000000000000000000000000000000000000000..0e7323f5123ba0304d0b7b7b63fb962aa8e7c49c
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/ConfigureTaggingOptions.py
@@ -0,0 +1,120 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+from D3PDMakerCoreComps.D3PDObject import make_SGDataVector_D3PDObject
+import EventCommonD3PDMaker
+import CaloD3PDMaker 
+import JetD3PDMaker
+import JetTagD3PDMaker
+from JetD3PDMaker.JetD3PDObject                      import JetD3PDObject
+from PhotonD3PDMaker.PhotonD3PDMakerFlags            import PhotonD3PDMakerFlags
+from RecExConfig.RecFlags                            import rec
+from D3PDMakerConfig.D3PDMakerFlags                  import D3PDMakerFlags
+from AthenaCommon.Constants                          import WARNING, INFO, ERROR, VERBOSE
+from AthenaCommon.Include                            import include
+
+from JetTagD3PDMaker.AddBTagD3PDInfo                 import addBTagInfoToJetObject
+from JetTagD3PDMaker.JetTagD3PDMakerKeys             import JetTagD3PDKeys
+from JetTagD3PDMaker.JetTagD3PDMakerFlags            import JetTagD3PDFlags
+
+def ConfigureTaggingOptions(alltruthjets,
+                            JetTagD3PD_JetFitterCharm = True,
+                            JetTagD3PD_MV3            = True):
+    
+    if JetTagD3PD_MV3:
+        JetTagD3PDFlags.Taggers+=["MV3_bVSu","MV3_bVSc","MV3_cVSu","MV3_bVSuFlip","MV3_bVScFlip","MV3_cVSuFlip"]
+        
+    if not JetTagD3PD_JetFitterCharm:
+        JetTagD3PDFlags.JetFitterCharmTagInfo=False
+    else:
+        JetTagD3PDFlags.Taggers+=["JetFitterCharm","JetFitterCharmNeg"]
+
+    addBTagInfoToJetObject(JetD3PDObject, 200)
+
+    from BTagging.BTaggingFlags import BTaggingFlags
+    
+    BTaggingFlags.CalibrationChannelAliases+=[ "AntiKt4Truth->AntiKt4TopoEM" ]
+    BTaggingFlags.CalibrationChannelAliases+=[ "AntiKt4TruthWithMuNoInt->AntiKt4TopoEM" ]
+    BTaggingFlags.Runmodus  = "analysis"
+    BTaggingFlags.Active=True
+
+    from JetRec.JetRecFlags import jetFlags
+    jetFlags.noStandardConfig = True
+    jetFlags.doBTagging = False
+
+    BTaggingFlags.OutputLevel              = WARNING
+    BTaggingFlags.ConvertParticleJets      = False
+    BTaggingFlags.JetFitterNN              = True
+
+    BTaggingFlags.doJetTagNtuple           = False
+    BTaggingFlags.doJetTagSlimNtuple       = False
+    BTaggingFlags.doJetTagFakeRateNtuple   = False
+    BTaggingFlags.doJetTagEfficiencyNtuple = False
+
+    BTaggingFlags.NewGbbNNTag              = True
+    BTaggingFlags.JetFitterCharm           = JetTagD3PD_JetFitterCharm
+    BTaggingFlags.JetFitterCharmNeg        = JetTagD3PD_JetFitterCharm
+    BTaggingFlags.MV3_bVSu                 = JetTagD3PD_MV3
+    BTaggingFlags.MV3_bVSc                 = JetTagD3PD_MV3
+    BTaggingFlags.MV3_cVSu                 = JetTagD3PD_MV3
+    BTaggingFlags.MV3_bVSuFlip             = JetTagD3PD_MV3
+    BTaggingFlags.MV3_bVScFlip             = JetTagD3PD_MV3
+    BTaggingFlags.MV3_cVSuFlip             = JetTagD3PD_MV3
+    BTaggingFlags.GbbNNTag                 = False
+    BTaggingFlags.QGTag                    = False # causes FPE's
+    BTaggingFlags.writeSecondaryVertices   = True
+
+    BTaggingFlags.SoftMuChi2               = True
+    BTaggingFlags.SecondSoftMu             = False
+    BTaggingFlags.SecondSoftMuChi2         = False
+
+    BTaggingFlags.IP1D                     = False
+
+    JetTagD3PD_calibTaggers = True
+    BTaggingFlags.IP2DFlip             = JetTagD3PD_calibTaggers
+    BTaggingFlags.IP2DPos              = JetTagD3PD_calibTaggers
+    BTaggingFlags.IP2DNeg              = JetTagD3PD_calibTaggers
+    BTaggingFlags.IP2DSpc              = JetTagD3PD_calibTaggers
+    BTaggingFlags.IP2DSpcFlip          = JetTagD3PD_calibTaggers
+    BTaggingFlags.IP2DSpcPos           = JetTagD3PD_calibTaggers
+    BTaggingFlags.IP2DSpcNeg           = JetTagD3PD_calibTaggers
+    BTaggingFlags.IP3DFlip             = JetTagD3PD_calibTaggers
+    BTaggingFlags.IP3DPos              = JetTagD3PD_calibTaggers
+    BTaggingFlags.IP3DNeg              = JetTagD3PD_calibTaggers
+    BTaggingFlags.IP3DSpc              = JetTagD3PD_calibTaggers
+    BTaggingFlags.IP3DSpcFlip          = JetTagD3PD_calibTaggers
+    BTaggingFlags.IP3DSpcPos           = JetTagD3PD_calibTaggers
+    BTaggingFlags.IP3DSpcNeg           = JetTagD3PD_calibTaggers
+    BTaggingFlags.SV1Flip              = JetTagD3PD_calibTaggers
+    BTaggingFlags.SV2Flip              = JetTagD3PD_calibTaggers
+    BTaggingFlags.JetProbFlip          = False
+    BTaggingFlags.SoftEl               = False ## no calib
+    BTaggingFlags.JetFitterNNFlip      = JetTagD3PD_calibTaggers
+    BTaggingFlags.TrackCounting        = JetTagD3PD_calibTaggers
+    BTaggingFlags.TrackCountingFlip    = JetTagD3PD_calibTaggers
+    BTaggingFlags.MV1Flip              = JetTagD3PD_calibTaggers
+    BTaggingFlags.MV2Flip              = JetTagD3PD_calibTaggers
+    BTaggingFlags.JetProb              = False
+    
+    # Truth Jet information
+    if rec.doTruth():
+            
+        if PhotonD3PDMakerFlags.RetagTruthBJets():
+            if PhotonD3PDMakerFlags.FillR0p6Jets():
+                BTaggingFlags.CalibrationChannelAliases+=[ "AntiKt6Truth->AntiKt6TopoEM" ]
+                BTaggingFlags.CalibrationChannelAliases+=[ "AntiKt6TruthWithMuNoInt->AntiKt6TopoEM" ]
+
+            for truthjets in alltruthjets:
+                modtruthjets = truthjets[:-4]
+                BTaggingFlags.Jets             += [modtruthjets]
+                BTaggingFlags.JetsWithInfoPlus += [modtruthjets]
+                
+            
+    include( "BTagging/BTagging_LoadTools.py" )
+
+    if PhotonD3PDMakerFlags.RetagTruthBJets():
+        # Now, when we loaded the tools, the new jet collections didn't exist in the input file.
+        # The tools checked the input file to see what collections it would retag.  So we need
+        # to explicitly add the new collections back into the b-tagging lists.
+        for truthjets in alltruthjets:
+            modtruthjets = truthjets[:-4]
+            BTaggingFlags.RetagJets        += [modtruthjets]
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/DREtAssociation.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/DREtAssociation.py
new file mode 100644
index 0000000000000000000000000000000000000000..cc99bd31ae4e9933a0986056a68fc1feb07fe015
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/DREtAssociation.py
@@ -0,0 +1,97 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+# $Id: DREtAssociation.py 354541 2011-03-26 04:55:52Z mhance $
+#
+# @file PhotonD3PDMaker/python/DREtAssociation.py
+# @author Mike Hance, inspired by DRAssociation by Scott Snyder
+# @date March 2011
+# @brief Helper for setting up a highest-E_T-within-DR association to a contained object.
+#
+
+
+import D3PDMakerCoreComps
+import EventCommonD3PDMaker
+import PhotonD3PDMaker
+from D3PDMakerCoreComps.D3PDObject import D3PDObject
+
+
+def DREtAssociation (parent,
+                     type_name,
+                     default_sgkey,
+                     default_drcut,
+                     prefix = '',
+                     matched = 'matched',
+                     level = 0,
+                     blockname = None,
+                     *args, **kw):
+    """Helper for setting up a highest-E_T-within-DR association to a contained object.
+
+    We get an source object and a collection of target objects.
+    We pick the target object that's highest in E_T within a given DR to the source object.
+    By default, the target collection is a DataVector from StoreGate.
+
+    parent: The parent D3PDobject or block.
+    type_name: The C++ type of the target object collection.
+    default_sgkey: Default StoreGate key for the target collection.
+    default_drcut: Default DR cut.  If no target objects are within
+                   this DR, the association will fail.
+    prefix: Prefix to add to the contained variables, if any.
+    matched: If not null, a flag variable with this name will
+             be created, set to true when the association succeeds.
+    level: Level of detail for the block.
+    blockname: Name for the block.
+
+    Extra arguments are passed to the association tool.
+
+    Here's an example.  Suppose we have an electron object, and we
+    want to record the 4-vector of a matching jet.
+
+    Usage is something like this:
+
+       ElectronObject = ...
+
+       EleJetAssoc = DREtAssociation (ElectronObject,
+                                   'JetCollection',
+                                   'Cone4H1TowerJets',
+                                   0.2,
+                                   'jet_',
+                                   level = 2,
+                                   blockname = 'JetMatch')
+       EleJetAssoc.defineBlock (2, 'JetKinematics',
+                                EventCommonD3PDMaker.FourMomFillerTool)
+
+    The DREtAssociation call makes the association.  We'll look in SG
+    for a JetCollection called `Cone4H1TowerJets' and find the jet from
+    there that's closest in DR to the electron (but not farther away
+    than 0.2).  If the electron prefix is `el_', then we'll automatically
+    create the variables `el_jet_matched' and `el_jet_dr'.  The second
+    call then adds the jet kinematic variables: `el_jet_pt', etc.
+    Additional blocks can be added if desired.
+"""
+    if blockname == None:
+        blockname = prefix + 'DREtAssoc'
+
+    def maker (name, prefix, object_name,
+               sgkey = default_sgkey,
+               getter = None,
+               assoc = None,
+               drcut = default_drcut):
+
+        if not getter:
+            getter = D3PDMakerCoreComps.SGDataVectorGetterTool \
+                     (name + '_Getter',
+                      TypeName = type_name,
+                      SGKey = sgkey)
+        if not assoc:
+            assoc = PhotonD3PDMaker.DREtAssociationTool (name + 'Assoc',
+                                                         Getter = getter,
+                                                         DRCut = drcut)
+
+        return D3PDMakerCoreComps.ContainedAssociationFillerTool (name,
+                                                         Prefix = prefix,
+                                                         Associator = assoc,
+                                                         Matched = matched)
+
+    obj = D3PDObject (maker, prefix)
+    parent.defineBlock (level, blockname, obj)
+    return obj
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/DiPhotonD3PDObject.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/DiPhotonD3PDObject.py
new file mode 100644
index 0000000000000000000000000000000000000000..a5d8df20e8a52f725f4c4a479fd1eee42fe7c003
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/DiPhotonD3PDObject.py
@@ -0,0 +1,229 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+# $Id$
+#
+# @file PhotonD3PDMaker/python/PhotonD3PDObject.py
+# @author Mike Hance <hance@hep.upenn.edu>
+# @date July, 2010
+# @brief Configure diphoton D3PD object.
+#
+
+
+from egammaD3PDAnalysis.PhotonUserDataConfig                import PhotonUserDataConfig
+from D3PDMakerCoreComps.D3PDObject                          import make_SGDataVector_D3PDObject
+from D3PDMakerCoreComps.release_version                     import release_version
+from D3PDMakerCoreComps.IndexMultiAssociation               import IndexMultiAssociation
+from D3PDMakerCoreComps.D3PDObject                          import D3PDObject
+from D3PDMakerConfig.D3PDMakerFlags                         import D3PDMakerFlags
+from D3PDMakerCoreComps.resolveSGKey                        import resolveSGKey
+from TriggerD3PDMaker.defineTriggerBits                     import defineTriggerBits
+from AthenaCommon.AlgSequence                               import AlgSequence
+from RecExConfig.RecFlags                                   import rec
+import egammaD3PDMaker
+import EventCommonD3PDMaker
+import D3PDMakerCoreComps
+import PhotonD3PDMaker
+
+DiPhotonD3PDObject = \
+                   make_SGDataVector_D3PDObject ('PAU::DiPhotonContainer',
+                                                 'PAUDiphotonCollection',
+                                                 'diphoton_',
+                                                 'DiPhotonD3PDObject')
+
+def _diphotonAlgHook (c, prefix, sgkey, typeName,
+                      seq = AlgSequence(D3PDMakerFlags.PreD3PDAlgSeqName()),
+                      *args, **kw):
+
+    from PhotonAnalysisUtils.PhotonAnalysisUtilsFlags import PAUflags
+    PAUflags.PhotonContainer = D3PDMakerFlags.PhotonSGKey()
+    
+    PAUflags.AlgSequence = seq.getName()
+    from PhotonAnalysisUtils.DiphotonAnalysisGetter import DiphotonAnalysisGetter
+    dip = DiphotonAnalysisGetter()
+    
+    return
+
+
+DiPhotonD3PDObject.defineHook (_diphotonAlgHook)
+
+
+
+
+from AthenaCommon.AppMgr import ToolSvc
+from AthenaCommon.DetFlags import DetFlags
+from AthenaCommon.SystemOfUnits import *
+from AthenaCommon.Constants import *
+from AthenaCommon.AppMgr import ServiceMgr
+
+
+from TrkTrackSummaryTool.AtlasTrackSummaryTool import AtlasTrackSummaryTool
+EMTrackIsolationTrackSummaryTool = AtlasTrackSummaryTool()
+ToolSvc += EMTrackIsolationTrackSummaryTool
+
+from TrkExTools.AtlasExtrapolator import AtlasExtrapolator
+EMTrackIsolationExtrapolator = AtlasExtrapolator()
+ToolSvc+=EMTrackIsolationExtrapolator
+
+EMIsolBuildTestBLayerTool = None
+if DetFlags.pixel_on():
+
+    from AthenaCommon.AthenaCommonFlags import athenaCommonFlags
+    from IOVDbSvc.CondDB import conddb
+    from InDetRecExample.InDetJobProperties import InDetFlags
+    from AthenaCommon.GlobalFlags import globalflags
+    
+    #
+    # --- Load PixelConditionsServices
+    #
+    # Load pixel conditions summary service
+    from PixelConditionsServices.PixelConditionsServicesConf import PixelConditionsSummarySvc
+    InDetPixelConditionsSummarySvc = PixelConditionsSummarySvc()
+      
+    # Load pixel special pixel map services
+    if athenaCommonFlags.isOnline() :
+        InDetPixelConditionsSummarySvc.UseSpecialPixelMap = False
+    else:
+        InDetPixelConditionsSummarySvc.UseSpecialPixelMap = True
+        if not conddb.folderRequested('/PIXEL/PixMapShort'):
+            conddb.addFolder("PIXEL_OFL","/PIXEL/PixMapShort")
+        if not conddb.folderRequested('/PIXEL/PixMapLong'):
+            conddb.addFolder("PIXEL_OFL","/PIXEL/PixMapLong")
+        if not conddb.folderRequested('/PIXEL/NoiseMapShort'):
+            conddb.addFolder("PIXEL_OFL","/PIXEL/NoiseMapShort")
+        if not conddb.folderRequested('/PIXEL/NoiseMapLong'):
+            conddb.addFolder("PIXEL_OFL","/PIXEL/NoiseMapLong")
+        if not conddb.folderRequested('/PIXEL/PixMapOverlay'):
+            conddb.addFolder("PIXEL_OFL","/PIXEL/PixMapOverlay")
+        from PixelConditionsServices.PixelConditionsServicesConf import SpecialPixelMapSvc
+        InDetSpecialPixelMapSvc = SpecialPixelMapSvc(DBFolders  = [ "/PIXEL/PixMapShort", "/PIXEL/PixMapLong" , "/PIXEL/NoiseMapShort", "/PIXEL/NoiseMapLong" ] ,
+                                                     SpecialPixelMapKeys = [ "SpecialPixelMap", "SpecialPixelMapLong", "NoiseMapShort", "NoiseMapLong" ] ,
+                                                     OverlayFolder       = "/PIXEL/PixMapOverlay",
+                                                     OverlayKey          = "PixMapOverlay")
+        ServiceMgr += InDetSpecialPixelMapSvc
+        if InDetFlags.doPrintConfigurables():
+            print InDetSpecialPixelMapSvc
+        
+        # Load pixel DCS information
+    if InDetFlags.usePixelDCS():
+        from PixelConditionsServices.PixelConditionsServicesConf import PixelDCSSvc
+        if athenaCommonFlags.isOnline():
+            if not conddb.folderRequested('/PIXEL/HLT/DCS/TEMPERATURE'):
+                conddb.addFolder("PIXEL_ONL","/PIXEL/HLT/DCS/TEMPERATURE")
+            if not conddb.folderRequested('/PIXEL/HLT/DCS/HV'):
+                conddb.addFolder("PIXEL_ONL","/PIXEL/HLT/DCS/HV")
+                    
+            InDetPixelDCSSvc =  PixelDCSSvc(RegisterCallback     = TRUE,
+                                            TemperatureFolder    = "/PIXEL/HLT/DCS/TEMPERATURE",
+                                            HVFolder             = "/PIXEL/HLT/DCS/HV",
+                                            TemperatureFieldName = "temperature",
+                                            HVFieldName          = "HV")
+        else:
+            if not conddb.folderRequested('/PIXEL/DCS/TEMPERATURE'):
+                conddb.addFolder("DCS_OFL","/PIXEL/DCS/TEMPERATURE")
+            if not conddb.folderRequested('/PIXEL/DCS/HV'):
+                conddb.addFolder("DCS_OFL","/PIXEL/DCS/HV")
+            if not conddb.folderRequested('/PIXEL/DCS/FSMSTATUS'):
+                conddb.addFolder("DCS_OFL","/PIXEL/DCS/FSMSTATUS")
+            if not conddb.folderRequested('/PIXEL/DCS/FSMSTATE'):
+                conddb.addFolder("DCS_OFL","/PIXEL/DCS/FSMSTATE")
+                
+            InDetPixelDCSSvc =  PixelDCSSvc(RegisterCallback     = TRUE,
+                                            TemperatureFolder    = "/PIXEL/DCS/TEMPERATURE",
+                                            HVFolder             = "/PIXEL/DCS/HV",
+                                            FSMStatusFolder      = "/PIXEL/DCS/FSMSTATUS",
+                                            FSMStateFolder       = "/PIXEL/DCS/FSMSTATE",
+                                            TemperatureFieldName = "temperature",
+                                            HVFieldName          = "HV",
+                                            FSMStatusFieldName   = "FSM_status",
+                                            FSMStateFieldName    = "FSM_state" )
+            ServiceMgr += InDetPixelDCSSvc
+            if InDetFlags.doPrintConfigurables():
+                print InDetPixelDCSSvc
+    
+        InDetPixelConditionsSummarySvc.UseDCS         = True
+        InDetPixelConditionsSummarySvc.IsActiveStates = [ 'READY' ]
+        InDetPixelConditionsSummarySvc.IsActiveStatus = [ 'OK', 'WARNING' ]
+    
+    
+    # Load Pixel BS errors service
+    if ( globalflags.DataSource == 'geant4' ) :
+        # Due to a "feature" in the BS encoder for simulation,
+        # the information of the BS error service
+        # is not reliable on MC.
+        InDetPixelConditionsSummarySvc.UseByteStream = False 
+    else :
+        from PixelConditionsServices.PixelConditionsServicesConf import PixelByteStreamErrorsSvc
+        InDetPixelByteStreamErrorsSvc = PixelByteStreamErrorsSvc()
+        if ( globalflags.InputFormat != 'bytestream' ):
+            InDetPixelByteStreamErrorsSvc.ReadingESD = True
+        InDetPixelConditionsSummarySvc.UseByteStream = True
+    
+        ServiceMgr += InDetPixelByteStreamErrorsSvc
+        if (InDetFlags.doPrintConfigurables()):
+            print InDetPixelByteStreamErrorsSvc
+                
+    # Register and printout configuration of  PixelConditionsSummarySvc
+    ServiceMgr += InDetPixelConditionsSummarySvc
+    if (InDetFlags.doPrintConfigurables()):
+        print InDetPixelConditionsSummarySvc
+
+
+    from InDetTestBLayer.InDetTestBLayerConf import InDet__InDetTestBLayerTool
+    EMIsolBuildTestBLayerTool = InDet__InDetTestBLayerTool(name= "EMIsolBuildTestBLayerTool",
+                                                           PixelSummarySvc = InDetPixelConditionsSummarySvc,
+                                                           Extrapolator    = EMTrackIsolationExtrapolator)
+    ToolSvc += EMIsolBuildTestBLayerTool
+
+
+from InDetTrackSelectorTool.InDetTrackSelectorToolConf import InDet__InDetDetailedTrackSelectorTool
+EMTrackIsolationPhotonTrackSelectorTool = InDet__InDetDetailedTrackSelectorTool(name = "EMTrackIsolationPhotonTrackSelectorTool",
+                                                                                IPd0Max              = 1.5*mm,
+                                                                                IPz0Max              = 3*mm,
+                                                                                pTMin                = 1000,
+                                                                                nHitBLayer           = 1,
+                                                                                nHitPix              = 0,
+                                                                                nHitSct              = 0,
+                                                                                nHitSi               = 9,
+                                                                                nHitTrt              = 0,
+                                                                                nHolesPixel          = 0,
+                                                                                nSharedBLayer        = 999,
+                                                                                nSharedPix           = 999,
+                                                                                nSharedSct           = 999,
+                                                                                nSharedSi            = 999,
+                                                                                useTrackQualityInfo  = False,
+                                                                                d0MaxPreselection    = 9999.,
+                                                                                TrackSummaryTool     = EMTrackIsolationTrackSummaryTool,
+                                                                                Extrapolator         = EMTrackIsolationExtrapolator,
+                                                                                InDetTestBLayerTool  = EMIsolBuildTestBLayerTool,
+                                                                                OutputLevel          = WARNING)
+ToolSvc += EMTrackIsolationPhotonTrackSelectorTool
+
+
+from TrackIsolationTools.TrackIsolationToolsConf import TrackIsolationTool
+EMTrackIsolationPhotonTrackIsolationTool = TrackIsolationTool(name = "EMTrackIsolationPhotonTrackIsolationTool",
+                                                              VertexContainer = "PAUDiphotonVertexCollection",
+                                                              DoTrackIsolation         = True,
+                                                              DoSumConversionTracks    = False,
+                                                              InnerCone                = 0.1,
+                                                              TrackParticleCollection  = "TrackParticleCandidate",
+                                                              ConversionContainer      = "AllPhotonsVxCandidates",
+                                                              CaloCellContainer        = "AODCellContainer",
+                                                              TrackSelector            = EMTrackIsolationPhotonTrackSelectorTool,
+                                                              InnerConeTrackSelector   = None)
+ToolSvc += EMTrackIsolationPhotonTrackIsolationTool
+print EMTrackIsolationPhotonTrackIsolationTool
+
+
+DiPhotonD3PDObject.defineBlock (0, 'PAUVariables',
+                                PhotonD3PDMaker.PAUDiPhotonFillerTool,
+                                PhotonTrackIsolationTool = EMTrackIsolationPhotonTrackIsolationTool
+                                )
+
+DiPhotonPhotonIndexAssoc = IndexMultiAssociation(DiPhotonD3PDObject,
+                                                 PhotonD3PDMaker.PAUDiPhotonAssociationTool,
+                                                 target = 'ph_',
+                                                 prefix = 'ph_',
+                                                 level = 1,
+                                                 blockname = "PhotonIndex",
+                                                 allowMissing = False)
+
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/EgammaTruthParticleD3PDObject.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/EgammaTruthParticleD3PDObject.py
new file mode 100644
index 0000000000000000000000000000000000000000..3ce20dee39e3b3fd8363929d728f5dfac9c3bd77
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/EgammaTruthParticleD3PDObject.py
@@ -0,0 +1,181 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+from AthenaCommon.AppMgr      import ToolSvc
+import PhotonD3PDMaker
+import D3PDMakerCoreComps
+from D3PDMakerCoreComps.D3PDObject import make_SGDataVector_D3PDObject
+from D3PDMakerConfig.D3PDMakerFlags                  import D3PDMakerFlags
+from PhotonAnalysisUtils.PhotonAnalysisUtilsFlags    import PAUflags
+import EventCommonD3PDMaker
+from AthenaCommon.Constants                          import WARNING, INFO, ERROR, VERBOSE
+import TruthD3PDMaker
+from TruthD3PDMaker.TruthParticleChildAssociation    import TruthParticleChildAssociation
+from TruthD3PDMaker.TruthParticleParentAssociation   import TruthParticleParentAssociation
+from D3PDMakerCoreComps.SimpleAssociation            import SimpleAssociation
+from D3PDMakerCoreComps.IndexAssociation             import IndexAssociation
+
+DVGetter = D3PDMakerCoreComps.SGDataVectorGetterTool
+
+# ---------------------------------------------------------------------------------
+# Now, setup a special collection for egamma truth objects.
+# This is messy, hopefully someday I can come back and clean this up.
+# 
+from PhotonAnalysisUtils.PhotonAnalysisUtilsConf import PAUcaloIsolationTool
+from PhotonD3PDMaker.PAUCaloIsolationTool import EMCaloIsoPtCorrectionTool
+PAUTruthCaloisolationtool = PAUcaloIsolationTool("PAUTruthCaloIsolationTool")
+PAUTruthCaloisolationtool.DoAreaCorrections = PAUflags.DoReRunJetFinding()
+PAUTruthCaloisolationtool.JetCollectionName = "Kt5TruthJets"
+PAUTruthCaloisolationtool.JetAreaEtaBins    = PAUflags.JetAreaEtaBins()
+PAUTruthCaloisolationtool.UseOldPtCorrections = PAUflags.UseOldPtCorrections()
+PAUTruthCaloisolationtool.UseOldAreaCorrections = True
+PAUTruthCaloisolationtool.EMCaloIsoPtCorrectionTool = EMCaloIsoPtCorrectionTool
+PAUTruthCaloisolationtool.OutputLevel       = WARNING 
+PAUTruthCaloisolationtool.JetAreaMomentName = PAUflags.JetAreaMomentName()
+ToolSvc += PAUTruthCaloisolationtool
+
+TruthParticlesSGKey = "SpclMC" # was D3PDMakerFlags.TruthParticlesSGKey() before...
+
+from AthenaCommon.AlgSequence import AlgSequence
+preseq = AlgSequence(D3PDMakerFlags.PreD3PDAlgSeqName())
+
+preseq += PhotonD3PDMaker.EgammaTruthParticleFilter("EgammaTruthParticleFilter",
+                                                    PhotonGetter  = DVGetter('TruthFilterPhotonGetter',
+                                                                             TypeName = 'PhotonContainer',
+                                                                             SGKey = D3PDMakerFlags.PhotonSGKey()),
+                                                    ElectronGetter = DVGetter('TruthFilterElectronGetter',
+                                                                              TypeName = 'ElectronContainer',
+                                                                              SGKey = D3PDMakerFlags.ElectronSGKey()),
+                                                    TruthGetter = DVGetter('TruthFilterTruthParticleGetter',
+                                                                           TypeName = 'TruthParticleContainer',
+                                                                           SGKey = TruthParticlesSGKey),
+                                                    PAUtruthTool                = ToolSvc.PAUtruthTool,
+                                                    OutputTruthCollectionName   = "FilteredEgammaTruthCollection")
+
+preseq += PhotonD3PDMaker.TruthExplorerAlg("PhotonD3PDTruthExplorer",
+                                           PhotonGetter  = DVGetter('TruthExplorerPhotonGetter',
+                                                                    TypeName = 'PhotonContainer',
+                                                                    SGKey = D3PDMakerFlags.PhotonSGKey()),
+                                           ElectronGetter = DVGetter('TruthExplorerElectronGetter',
+                                                                     TypeName = 'ElectronContainer',
+                                                                     SGKey = D3PDMakerFlags.ElectronSGKey()),
+                                           TruthParticleGetter = DVGetter('TruthExplorerTruthParticleGetter',
+                                                                          TypeName = 'TruthParticleContainer',
+                                                                          SGKey = "FilteredEgammaTruthCollection"),
+                                           PAUtruthTool                = ToolSvc.PAUtruthTool,
+                                           CalculateTruthCaloIsolation = PAUflags.FindLowPtTruthJets(),
+                                           RemoveNHardestJets          = PAUflags.JetAreaJetsToRemove(),
+                                           PAUCaloIsolationTool        = PAUTruthCaloisolationtool,
+                                           UDPrefix                    = "PhotonD3PDTruthUD::")
+
+
+EgammaTruthParticleD3PDObject = make_SGDataVector_D3PDObject \
+                                ('TruthParticleContainer',
+                                 D3PDMakerFlags.TruthParticlesSGKey(),
+                                 'egammaTruth_',
+                                 'EgammaTruthParticleD3PDObject')
+
+EgammaTruthParticleD3PDObject.defineBlock (0, 'TruthKin',
+                                           EventCommonD3PDMaker.FourMomFillerTool)
+
+EgammaTruthParticleD3PDObject.defineBlock (0, 'TruthInfo',
+                                           TruthD3PDMaker.TruthParticleFillerTool)
+
+ProdVertexAssoc = SimpleAssociation \
+                  (EgammaTruthParticleD3PDObject,
+                   TruthD3PDMaker.TruthParticleProdVertexAssociationTool,
+                   level = 1,
+                   prefix = 'vx_',
+                   blockname = 'ProdVert')
+ProdVertexAssoc.defineBlock (1, 'ProdVertPos',
+                             EventCommonD3PDMaker.GenVertexFillerTool)
+
+
+ChildAssoc = TruthParticleChildAssociation(
+    parent = EgammaTruthParticleD3PDObject,
+    prefix = 'child_',
+    # target = '', # filled by hook
+    level = 0 )
+def _TruthParticleChildAssocHook (c, prefix, *args, **kw):
+    assoc = getattr(c, c.name() + '_child_TruthParticleChildAssociation', None)
+    if assoc:
+        # This produces warnings, I'm not sure how to configure this properly to avoid the warnings....
+        indexer = getattr(assoc, assoc.name() + 'Index')
+        indexer.Target = prefix
+        return
+    EgammaTruthParticleD3PDObject.defineHook(_TruthParticleChildAssocHook)
+    
+ParentAssoc = TruthParticleParentAssociation(
+    parent = EgammaTruthParticleD3PDObject,
+    prefix = 'parent_',
+    # target = '', # filled by hook
+    level = 0 )
+def _TruthParticleParentAssocHook (c, prefix, *args, **kw):
+    assoc = getattr(c, c.name() + '_parent_TruthParticleParentAssociation', None)
+    if assoc:
+        # This produces warnings, I'm not sure how to configure this properly to avoid the warnings....
+        indexer = getattr(assoc, assoc.name() + 'Index')
+        indexer.Target = prefix
+        return
+    EgammaTruthParticleD3PDObject.defineHook(_TruthParticleParentAssocHook)
+
+# Link to the truth particle's parents in the mc_ block.
+doSimpleIndexing=False
+if doSimpleIndexing:
+    # in principle I feel like this should work, but I wonder if things are getting
+    # screwed up because I'm playing games with sorting the mc_ block.
+    EgammaTruthParticleD3PDObject.defineBlock(1, "MCIndex",
+                                              D3PDMakerCoreComps.IndexFillerTool,
+                                              Target="mc_",
+                                              prefix="mc_",
+                                              AllowMissing=True)
+else:
+    # something more complicated, this seems to do the association a bit better.
+    EgammaTruthParticleGenParticleAssociation = SimpleAssociation(EgammaTruthParticleD3PDObject,
+                                                                  TruthD3PDMaker.TruthParticleGenParticleAssociationTool,
+                                                                  level = 1)
+
+    IndexAssociation(EgammaTruthParticleGenParticleAssociation,
+                     TruthD3PDMaker.GenParticleTruthParticleAssociationTool,
+                     target="mc_",
+                     Target="mc_",
+                     prefix="mc_",
+                     level=1,
+                     blockname="EgammaTruthParticleMCIndexAssociation",
+                     allowMissing=True)
+    
+    
+EgammaTruthParticleD3PDObject.defineBlock (1, 'TruthIDInfo',
+                                           D3PDMakerCoreComps.UserDataFillerTool,
+                                           UDPrefix = "PhotonD3PDTruthUD::",
+                                           Vars = ['TruthConv' , '', 'int',
+                                                   'XTruthConv', '', 'float',
+                                                   'YTruthConv', '', 'float',
+                                                   'ZTruthConv', '', 'float',
+                                                   'RTruthConv', '', 'float',
+                                                   'isHardProcPhoton', '', 'int',
+                                                   'isBremPhoton'    , '', 'int',
+                                                   'isPromptPhoton'  , '', 'int',
+                                                   'PartonIsolation15_UE', '', 'float',
+                                                   'PartonIsolation20_UE', '', 'float',
+                                                   'PartonIsolation25_UE', '', 'float',
+                                                   'PartonIsolation30_UE', '', 'float',
+                                                   'PartonIsolation35_UE', '', 'float',
+                                                   'PartonIsolation40_UE', '', 'float',
+                                                   'PartonIsolation45_UE', '', 'float',
+                                                   'PartonIsolation60_UE', '', 'float',
+                                                   'PartonIsolation15', '', 'float',
+                                                   'PartonIsolation20', '', 'float',
+                                                   'PartonIsolation30', '', 'float',
+                                                   'PartonIsolation25', '', 'float',
+                                                   'PartonIsolation35', '', 'float',
+                                                   'PartonIsolation40', '', 'float',
+                                                   'PartonIsolation45', '', 'float',
+                                                   'PartonIsolation60', '', 'float',
+                                                   'ParticleIsolation40', '', 'float',
+                                                   'ParticleIsolation30', '', 'float',
+                                                   'ParticleIsolation20', '', 'float',
+                                                   'ParticleIsolation40_ED_corrected', '', 'float',
+                                                   'ParticleIsolation30_ED_corrected', '', 'float',
+                                                   'ParticleIsolation20_ED_corrected', '', 'float',
+                                                   'mother_pdgId', '', 'int'])
+     
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/ElectronToPhotonD3PDObject.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/ElectronToPhotonD3PDObject.py
new file mode 100644
index 0000000000000000000000000000000000000000..b8af1a8371e3e5b53a0f5fd138f9fbd3b88ccd69
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/ElectronToPhotonD3PDObject.py
@@ -0,0 +1,325 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+# $Id: ElectronToPhotonD3PDObject.py 587551 2014-03-13 19:09:27Z mhance $
+#
+# @file PhotonD3PDMaker/python/ElectronToPhotonD3PDObject.py
+# @author Mike Hance <hance@hep.upenn.edu>
+# @date July, 2010
+# @brief Configure electron->photon variables
+#
+
+
+from RecExConfig.RecFlags                 import rec
+from AthenaCommon.AlgSequence             import AlgSequence
+from AthenaCommon.AppMgr                  import ToolSvc
+from AthenaCommon.Include                 import include
+from D3PDMakerConfig.D3PDMakerFlags       import D3PDMakerFlags
+from D3PDMakerCoreComps.D3PDObject        import make_SGDataVector_D3PDObject
+from D3PDMakerCoreComps.SimpleAssociation import SimpleAssociation
+import CaloD3PDMaker
+import EventCommonD3PDMaker
+import egammaD3PDMaker
+from egammaD3PDMaker.isem_version         import isem_version
+from egammaD3PDMaker                      import egammaDetailFillerTool
+from ROOT                                 import egammaPID
+from ROOT                                 import egammaParameters
+from AthenaCommon.DetFlags                import DetFlags 
+from AthenaCommon.Constants               import WARNING, INFO, ERROR, VERBOSE
+
+from PhotonAnalysisUtils.PAU_AtlasExtrapolator import PAU_AtlasExtrapolator
+theAtlasExtrapolator = PAU_AtlasExtrapolator()
+
+# Set up the overall cluster correction tool
+doEgammaDefault=True
+
+if doEgammaDefault:
+    from egammaRec.EMClusterTool import egammaClusterTool
+    PhotonClusterTool = egammaClusterTool("MyPhotonClusterTool")
+
+else:
+    from egammaD3PDAnalysis.egammaSwTool import egammaSwTool
+    from CaloClusterCorrection.common import CALOCORR_JO, CALOCORR_COOL
+    myegammaSwTool = egammaSwTool('PhotonegammaSwTool',
+                                  suffix='EG',
+                                  version='v11_calh', #'@GLOBAL',
+                                  CaloCells=None,
+                                  source=None
+                                  )
+    ToolSvc += myegammaSwTool
+    
+    from egammaTools.egammaToolsConf import EMClusterTool
+    PhotonClusterTool = EMClusterTool(name                      = "MyPhotonClusterTool",
+                                      ClusterCorrectionToolName = myegammaSwTool.getFullName())
+
+ToolSvc += PhotonClusterTool
+
+
+
+
+
+
+# Set up the PID builder tool
+include("PhotonD3PDMaker/PhotonPIDTool_jobOptions.py")
+
+from InDetSecVxFinderTool.InDetSecVxFinderToolConf import InDet__InDetJetFitterUtils
+convUtils = InDet__InDetJetFitterUtils(name                   = "convUtils",
+                                       LinearizedTrackFactory = None,
+                                       Extrapolator           = None)
+ToolSvc += convUtils
+
+from egammaTools.EMClusterErrorsToolFactory import EMClusterErrorsToolFact
+PAUemclustererrorstool=EMClusterErrorsToolFact("EMClusterErrorsTool")
+ToolSvc += PAUemclustererrorstool
+
+from PhotonAnalysisUtils.PhotonAnalysisUtilsFlags import PAUflags
+PhotonsDetailsContainerName=PAUflags.PhotonsDetailsContainerName.StoredValue
+
+import EventKernel.ParticleDataType
+from egammaTools.egammaToolsConf import EMFourMomBuilder
+PAUPhotonFourMomBuilder=EMFourMomBuilder(name      = "PAUfourmombuilder");
+PAUPhotonFourMomBuilder.EMErrorDetailContainerName = PhotonsDetailsContainerName
+PAUPhotonFourMomBuilder.EMShowerContainerName      = PhotonsDetailsContainerName
+PAUPhotonFourMomBuilder.EMTrackFitContainerName    = PhotonsDetailsContainerName
+PAUPhotonFourMomBuilder.EMConvertContainerName     = PhotonsDetailsContainerName
+PAUPhotonFourMomBuilder.ConversionUtils            = convUtils
+PAUPhotonFourMomBuilder.dataType                   = EventKernel.ParticleDataType.Full
+PAUPhotonFourMomBuilder.EMClusterErrorsTool        = PAUemclustererrorstool
+ToolSvc += PAUPhotonFourMomBuilder
+
+if not rec.readAOD(): 
+    CaloCells = 'AllCalo' 
+else: 
+    CaloCells = 'AODCellContainer' 
+ 
+# second shower shape builder for post processing 
+# configure tool egammaShowerShape 
+from egammaCaloTools.egammaCaloToolsConf import egammaShowerShape 
+PAUegammaShowerShape = egammaShowerShape(name = "PAUegammashowershape", 
+                                         TypeAnalysis ="ClusterSeed", 
+                                         # calculate quantities base on information in the strips in a region 
+                                         # around the cluster. 
+                                         # Use 5 strips in phi and cover a region of +-1.1875 
+                                         # times 0.025 in eta (corresponds to 19 strips in em barrel) 
+                                         # Use 7*7 cluster for middle sampling 
+                                         # other samplings arew not used for the moment 
+                                         Neta=[0.,2.5,7,0.], 
+                                         Nphi=[0.,2.,7,0.], 
+                                         # Samplings to execute 
+                                         ExecAllVariables = True, 
+                                         ExecPreSampler = True, 
+                                         ExecEMFirst = True, 
+                                         ExecEMSecond = True, 
+                                         ExecEMThird = True, 
+                                         ExecEMCombined = True, 
+                                         ExecOtherVariables = True) 
+ToolSvc += PAUegammaShowerShape 
+ 
+# create tool CaloDepthTool 
+from CaloDetDescr.CaloDepthToolBase import CaloDepthToolFactory 
+theCaloDepthTool=CaloDepthToolFactory(depth='showerdefault') 
+ToolSvc += theCaloDepthTool 
+ 
+# add tool egammaqpoint 
+from egammaCaloTools.egammaCaloToolsConf import egammaqpoint 
+theegammaqpoint=egammaqpoint("egammaQpoint", 
+                             CalorimeterDepth=theCaloDepthTool.getName() ) 
+#theegammaqpoint+=theCaloDepthTool # don't do this!  It causes errors. 
+ToolSvc+=theegammaqpoint 
+ 
+# add tool egammaqgcld 
+from egammaCaloTools.egammaCaloToolsConf import egammaqgcld 
+theegammaqgcld=egammaqgcld("egammaQgcld", 
+                           CalorimeterDepth=theCaloDepthTool.getName() ) 
+#theegammaqgcld+=theCaloDepthTool 
+ToolSvc+=theegammaqgcld 
+ 
+# create tool CaloNoiseTool 
+from CaloTools.CaloNoiseToolDefault import CaloNoiseToolDefault 
+theCaloNoiseTool=CaloNoiseToolDefault('db') 
+ToolSvc += theCaloNoiseTool 
+ 
+# add tool egammaiso 
+from egammaCaloTools.egammaCaloToolsConf import egammaIso 
+theegammaiso=egammaIso("egammaIso", 
+                       CaloNoiseTool= theCaloNoiseTool) 
+ToolSvc += theegammaiso 
+ 
+from egammaTools.EMTrackIsolationToolBase import EMAltTrackIsolationToolBase
+theemalttrackisolationtool = EMAltTrackIsolationToolBase("emalttrackisolationtool")
+ToolSvc+=theemalttrackisolationtool 
+
+
+from egammaCaloTools.egammaIsoPtCorrectionToolBase import egammaIsoPtCorrectionToolBase 
+theegammaisoptcorrection=egammaIsoPtCorrectionToolBase("egammaIsoPtCorrection") 
+ToolSvc+=theegammaisoptcorrection 
+ 
+from CaloIdentifier import SUBCALO 
+from egammaTools.egammaToolsConf import EMShowerBuilder 
+PAUPhotonShowerBuilder = EMShowerBuilder(name                      = "PAUPhotonShowerBuilder", 
+                                         CellsName                 = CaloCells, 
+                                         CaloNums                  = [SUBCALO.LAREM, SUBCALO.LARHEC, SUBCALO.TILE], 
+                                         EMShowerContainerName     = PhotonsDetailsContainerName, 
+                                         UseCaloIsoTool            = False, 
+                                         UseTrackIsoTool           = False, 
+                                         Print                     = False, 
+                                         PointingTool              = theegammaqpoint, 
+                                         DepthTool                 = theegammaqgcld, 
+                                         ShowerShapeTool           = PAUegammaShowerShape,
+					 EMAltTrackIsolationTool   = theemalttrackisolationtool,
+                                         EMCaloIsoPtCorrectionTool = theegammaisoptcorrection)
+PAUPhotonShowerBuilder.OutputLevel = WARNING
+ToolSvc += PAUPhotonShowerBuilder
+
+
+# Track summary helper tool
+from InDetTrackHoleSearch.InDetTrackHoleSearchConf import InDet__InDetTrackHoleSearchTool
+PAUInDetHoleSearchTool = InDet__InDetTrackHoleSearchTool(name = "PAUInDetHoleSearchTool",
+                                                         Extrapolator = theAtlasExtrapolator)
+
+ToolSvc += PAUInDetHoleSearchTool
+
+#
+# Load the InDetTrackSummaryHelperTool
+#
+from InDetAssociationTools.InDetAssociationToolsConf import InDet__InDetPRD_AssociationToolGangedPixels
+PAUInDetPrdAssociationTool = InDet__InDetPRD_AssociationToolGangedPixels(name                           = "PAUInDetPrdAssociationTool",
+                                                                         PixelClusterAmbiguitiesMapName = 'PixelClusterAmbiguitiesMap')
+ToolSvc += PAUInDetPrdAssociationTool
+
+
+from InDetTrackSummaryHelperTool.InDetTrackSummaryHelperToolConf import InDet__InDetTrackSummaryHelperTool
+if DetFlags.haveRIO.TRT_on():
+        PAUInDetTrackSummaryHelperTool = InDet__InDetTrackSummaryHelperTool(name         = "PAUInDetSummaryHelper",
+                                                                            AssoTool     = PAUInDetPrdAssociationTool,
+                                                                            DoSharedHits = False,
+                                                                            HoleSearch   = PAUInDetHoleSearchTool)
+        ToolSvc += PAUInDetTrackSummaryHelperTool
+else:
+        PAUInDetTrackSummaryHelperTool = InDet__InDetTrackSummaryHelperTool(name         = "PAUInDetSummaryHelper",
+                                                                            AssoTool     = PAUInDetPrdAssociationTool,
+                                                                            DoSharedHits = False,
+                                                                            TRTStrawSummarySvc = "",
+                                                                            HoleSearch   = PAUInDetHoleSearchTool)
+        ToolSvc += PAUInDetTrackSummaryHelperTool
+        
+        
+ToolSvc += PAUInDetTrackSummaryHelperTool
+
+from TrkTrackSummaryTool.TrkTrackSummaryToolConf import Trk__TrackSummaryTool
+PAUInDetTrackSummaryTool = Trk__TrackSummaryTool(name = "PAUInDetTrackSummaryTool",
+                                                 InDetSummaryHelperTool = PAUInDetTrackSummaryHelperTool,
+                                                 doSharedHits           = False,
+                                                 InDetHoleSearchTool    = PAUInDetHoleSearchTool)
+ToolSvc += PAUInDetTrackSummaryTool
+
+# Helper Tool
+#
+from InDetConversionFinderTools.InDetConversionFinderToolsConf import InDet__ConversionFinderUtils
+InDetConversionHelper = InDet__ConversionFinderUtils(name = "ConversionFinderUtils")
+ToolSvc += InDetConversionHelper
+
+from InDetConversionFinderTools.InDetConversionFinderToolsConf import InDet__SingleTrackConversionTool
+PAUInDetSingleTrackConversion = InDet__SingleTrackConversionTool(name                       = "PAUSingleTrackConversionTool",
+                                                                 ConversionFinderHelperTool = InDetConversionHelper,
+                                                                 TrackSummaryTool           = PAUInDetTrackSummaryTool,
+                                                                 MinInitialHitRadius        = 0.,
+                                                                 MinRatioOfHLhits           = 0.)  #0.)  #0.95)
+ToolSvc += PAUInDetSingleTrackConversion
+
+from PhotonAnalysisUtils.PhotonAnalysisUtilsConf import ElectronToPhotonTool
+ElectronToPhotonTool = ElectronToPhotonTool("ElectronToPhotonTool",
+                                            ClusterTool = PhotonClusterTool,
+                                            PIDBuilderTool = ToolSvc.PhotonPIDBuilder,
+                                            FourMomentumTool = PAUPhotonFourMomBuilder,
+                                            EMShowerBuilderTool = PAUPhotonShowerBuilder,
+                                            SingleTrackConversionTool = PAUInDetSingleTrackConversion,
+                                            TrackParticleContainerName = D3PDMakerFlags.TrackSGKey())
+ToolSvc += ElectronToPhotonTool
+
+preseq = AlgSequence (D3PDMakerFlags.PreD3PDAlgSeqName())
+from PhotonAnalysisUtils.PhotonAnalysisUtilsConf import ElectronToPhotonAlg
+preseq += ElectronToPhotonAlg("ElectronToPhotonAlg",
+                              ElectronContainer = D3PDMakerFlags.ElectronSGKey(),
+                              ElectronToPhotonTool = ElectronToPhotonTool);
+
+
+ElectronToUnconvertedPhotonD3PDObject = make_SGDataVector_D3PDObject('PhotonContainer',
+                                                                     'PAUElectronToUnconvertedPhotonCollection',
+                                                                     'el_as_unconv_ph_');
+
+ElectronToConvertedPhotonD3PDObject = make_SGDataVector_D3PDObject('PhotonContainer',
+                                                                   'PAUElectronToConvertedPhotonCollection',
+                                                                   'el_as_conv_ph_');
+
+for newPhotonD3PDObject in [ElectronToUnconvertedPhotonD3PDObject,ElectronToConvertedPhotonD3PDObject]:
+    PhotonClusterAssoc = SimpleAssociation \
+                         (newPhotonD3PDObject,
+                          egammaD3PDMaker.egammaClusterAssociationTool)
+    PhotonClusterAssoc.defineBlock (0, 'ClusterKin', EventCommonD3PDMaker.FourMomFillerTool,
+                                    prefix = 'cl_',
+                                    WriteE = True,
+                                    WriteM = False)
+    PhotonClusterAssoc.defineBlock (0, 'Samplings', CaloD3PDMaker.ClusterEMSamplingFillerTool)
+
+    newPhotonD3PDObject.defineBlock(0, 'IsEM',  egammaD3PDMaker.egammaIsEMoneFillerTool)
+    if isem_version() == 1:
+        newPhotonD3PDObject.defineBlock (0, 'IsEMCuts',
+                                         egammaD3PDMaker.egammaIsEMFillerTool,
+                                         IsEM  = [egammaPID.PhotonTightOLDRel,
+                                                  'tight',
+                                                  ])
+    else:
+        newPhotonD3PDObject.defineBlock (0, 'IsEMCuts',
+                                         egammaD3PDMaker.egammaIsEMFillerTool,
+                                         IsEM  = [egammaPID.PhotonLoose,
+                                                  'loose',
+                                                  egammaPID.PhotonTight,
+                                                  'tight',
+                                                  egammaPID.PhotonTightIso,
+                                                  'tightIso',
+                                                  ])
+
+    newPhotonD3PDObject.defineBlock (0, 'HadLeakage',
+                                     egammaD3PDMaker.egammaDetailFillerTool,
+                                     Details = [egammaParameters.ethad,
+                                                'Ethad',
+                                                egammaParameters.ethad1,
+                                                'Ethad1',
+                                                ])
+    newPhotonD3PDObject.defineBlock (0, 'Layer1Shape',
+                                     egammaD3PDMaker.egammaDetailFillerTool,
+                                     Details = [egammaParameters.f1,
+                                                'f1',
+                                                egammaParameters.f1core,
+                                                'f1core',
+                                                egammaParameters.emins1,
+                                                'Emins1',
+                                                egammaParameters.fracs1,
+                                                'fside',
+                                                egammaParameters.e2tsts1,
+                                                'Emax2',
+                                                egammaParameters.weta1,
+                                                'ws3',
+                                                egammaParameters.wtots1,
+                                                'wstot',
+                                                egammaParameters.e132,
+                                                'E132',
+                                                egammaParameters.e1152,
+                                                'E1152',
+                                                egammaParameters.emaxs1,
+                                                'emaxs1',
+                                                ])
+    newPhotonD3PDObject.defineBlock (0, 'Layer1ShapeExtra',
+                                     egammaD3PDMaker.egammaLayer1ExtraFillerTool)
+    newPhotonD3PDObject.defineBlock (0, 'Layer2Shape',
+                                     egammaD3PDMaker.egammaDetailFillerTool,
+                                     Details = [egammaParameters.e233,
+                                                'E233',
+                                                egammaParameters.e237,
+                                                'E237',
+                                                egammaParameters.e277,
+                                                'E277',
+                                                egammaParameters.weta2,
+                                                'weta2',
+                                                ])
+
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PAUCaloIsolationTool.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PAUCaloIsolationTool.py
new file mode 100644
index 0000000000000000000000000000000000000000..c003fbf45393f6be11d0dbd342714e2724016cd6
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PAUCaloIsolationTool.py
@@ -0,0 +1,23 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+from AthenaCommon.Constants import WARNING, INFO, ERROR, VERBOSE
+from PhotonAnalysisUtils.PhotonAnalysisUtilsFlags import PAUflags
+from AthenaCommon.AppMgr      import ToolSvc
+
+# Calorimeter isolation tool for truth (hadron-level) isolation
+from egammaCaloTools.egammaIsoPtCorrectionToolBase import egammaIsoPtCorrectionToolBase
+EMCaloIsoPtCorrectionTool = egammaIsoPtCorrectionToolBase("egammaIsoPtCorrection")
+ToolSvc += EMCaloIsoPtCorrectionTool
+
+from PhotonAnalysisUtils.PhotonAnalysisUtilsConf import PAUcaloIsolationTool
+PAUCaloIsolationTool = PAUcaloIsolationTool("PAUCaloIsolationTool")
+PAUCaloIsolationTool.DoAreaCorrections = PAUflags.DoReRunJetFinding()
+PAUCaloIsolationTool.JetCollectionName = "Kt5TopoJets"
+PAUCaloIsolationTool.JetAreaEtaBins    = PAUflags.JetAreaEtaBins()
+PAUCaloIsolationTool.UseOldPtCorrections = PAUflags.UseOldPtCorrections()
+PAUCaloIsolationTool.UseOldAreaCorrections = True
+PAUCaloIsolationTool.EMCaloIsoPtCorrectionTool = EMCaloIsoPtCorrectionTool
+PAUCaloIsolationTool.OutputLevel       = WARNING
+PAUCaloIsolationTool.JetAreaMomentName = PAUflags.JetAreaMomentName()
+
+ToolSvc += PAUCaloIsolationTool
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PAUGammaAssociation.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PAUGammaAssociation.py
new file mode 100644
index 0000000000000000000000000000000000000000..87370abce03c1681594c9d0b91dc7a50b93896ec
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PAUGammaAssociation.py
@@ -0,0 +1,85 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+# $Id$
+#
+# @file EventCommonD3PDMaker/python/DRAssociation.py
+# @author scott snyder <snyder@bnl.gov>
+# @date Aug, 2009
+# @brief Helper for setting up a nearest-DR association to a contained object.
+#
+
+import D3PDMakerCoreComps
+import egammaD3PDMaker
+from D3PDMakerCoreComps.D3PDObject import D3PDObject
+
+
+def PAUGammaAssociation (parent,
+                         type_name,
+                         default_sgkey,
+                         prefix = '',
+                         matched = '',
+                         level = 0,
+                         blockname = None,
+                         *args, **kw):
+    """Helper for setting up an association from a photon to a PAU::gamma object.
+
+    We get a source object (Analysis::Photon or Analysis::Electron)
+    and a collection of target objects (PAU::gamma).
+    We pick the target object that links to the source object.
+    By default, the target collection is a DataVector from StoreGate.
+
+    parent: The parent D3PDobject or block.
+    type_name: The C++ type of the target object collection.
+    default_sgkey: Default StoreGate key for the target collection.
+    prefix: Prefix to add to the contained variables, if any.
+    matched: If not null, a flag variable with this name will
+             be created, set to true when the association succeeds.
+    level: Level of detail for the block.
+    blockname: Name for the block.
+
+    Extra arguments are passed to the association tool.
+
+    Here's an example.
+    
+    Usage is something like this:
+
+       PhotonPAUAssoc = PAUGammaAssociation (PhotonD3PDObject,
+                                             'PAU::gammaContainer',
+                                             'PAUgammaCollection',
+                                             prefix = 'PAU_',
+                                             level = 2,
+                                             blockname = 'PAU')
+       PhotonPAUAssoc.defineBlock (2, 'PAUVariables',
+                                   egammaD3PDMaker.PAUFillerTool)
+
+    The PAUGammaAssociation call makes the association.  We'll look in SG
+    for a PAU::gammaContainer called `PAUgammaCollection' and find the PAU::gamma
+    object from there that links to the photon.  If the photon prefix is `ph_',
+    then the PAUFillerTool will automatically create some variables, including a
+    'ph_PAU_matched' variable which indicates whether or not a match was found.
+"""
+    if blockname == None:
+        blockname = prefix + 'PAUGammaAssoc'
+
+    def maker (name, prefix, object_name,
+               sgkey = default_sgkey,
+               getter = None,
+               assoc = None):
+
+        if not getter:
+            getter = D3PDMakerCoreComps.SGDataVectorGetterTool \
+                     (name + '_Getter',
+                      TypeName = type_name,
+                      SGKey = sgkey)
+        if not assoc:
+            assoc = egammaD3PDMaker.PAUGammaAssociationTool (name + 'Assoc',
+                                                             Getter = getter)
+
+        return D3PDMakerCoreComps.ContainedAssociationFillerTool (name,
+                                                                  Prefix = prefix,
+                                                                  Associator = assoc,
+                                                                  Matched = matched)
+
+    obj = D3PDObject (maker, prefix)
+    parent.defineBlock (level, blockname, obj)
+    return obj
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PAUTruthPhotonAssociation.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PAUTruthPhotonAssociation.py
new file mode 100644
index 0000000000000000000000000000000000000000..95dcf0c9cdcc3ffad5e8cf947c08749d5bd1c47d
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PAUTruthPhotonAssociation.py
@@ -0,0 +1,44 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+# $Id$
+#
+
+import D3PDMakerCoreComps
+import PhotonD3PDMaker
+from D3PDMakerCoreComps.D3PDObject import D3PDObject
+
+
+def PAUTruthPhotonAssociation (parent,
+                         type_name,
+                         default_sgkey,
+                         prefix = '',
+                         matched = '',
+                         level = 0,
+                         blockname = None,
+                         *args, **kw):
+
+    if blockname == None:
+        blockname = prefix + 'PAUTruthPhotonAssoc'
+
+    def maker (name, prefix, object_name,
+               sgkey = default_sgkey,
+               getter = None,
+               assoc = None):
+
+        if not getter:
+            getter = D3PDMakerCoreComps.SGDataVectorGetterTool \
+                     (name + '_Getter',
+                      TypeName = type_name,
+                      SGKey = sgkey)
+        if not assoc:
+            assoc = PhotonD3PDMaker.PAUTruthPhotonAssociationTool (name + 'Assoc',
+                                                                   Getter = getter)
+            
+        return D3PDMakerCoreComps.ContainedAssociationFillerTool (name,
+                                                                  Prefix = prefix,
+                                                                  Associator = assoc,
+                                                                  Matched = matched)
+
+    obj = D3PDObject (maker, prefix)
+    parent.defineBlock (level, blockname, obj)
+    return obj
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonD3PD.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonD3PD.py
new file mode 100644
index 0000000000000000000000000000000000000000..c8d2f93f18232fb478f62213e6541f70ae8ec68e
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonD3PD.py
@@ -0,0 +1,223 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+import PhotonD3PDMaker
+import EventCommonD3PDMaker
+import TrackD3PDMaker
+import CaloD3PDMaker
+from PhotonD3PDMaker.PhotonD3PDMakerFlags            import PhotonD3PDMakerFlags
+from D3PDMakerConfig.D3PDMakerFlags                  import D3PDMakerFlags
+from RecExConfig.RecFlags                            import rec
+
+def _args (level, name, kwin, **kw):
+    kw = kw.copy()
+    kw['level'] = level
+    for (k, v) in kwin.items():
+        if k.startswith (name + '_'):
+            kw[k[len(name)+1:]] = v
+    return kw
+
+
+def PhotonD3PD (alg = None,
+                level = 10,
+                tuplename = 'photon',
+                file = 'photon.root',
+                stacoMuonContainer   = 'StacoMuonCollection', 
+                caloMuonContainer    = 'CaloMuonCollection',
+                CustomMETCollections = [],
+                **kw):
+
+    from AthenaCommon.AlgSequence import AlgSequence
+    preseq = AlgSequence(D3PDMakerFlags.PreD3PDAlgSeqName())
+
+    
+    #-------------------------------------------------------------------------------------
+    # Core Algorithm
+    #
+    # By default the user of this function should have created an algorithm already.
+    # But for backwards compatibility let the function create its own algorithm if
+    # needed...
+    if not alg:
+        from OutputStreamAthenaPool.MultipleStreamManager import MSMgr
+        alg = MSMgr.NewRootStream( tuplename, file )
+    #-------------------------------------------------------------------------------------
+
+
+    #-------------------------------------------------------------------------------------
+    # Some standard stuff.
+    #
+    from EventCommonD3PDMaker.EventInfoD3PDObject        import EventInfoD3PDObject
+    alg += EventInfoD3PDObject        (**_args (level, 'EventInfo'        , kw))
+
+    from CaloD3PDMaker.LArCollisionTimeD3PDObject        import LArCollisionTimeD3PDObject
+    alg += LArCollisionTimeD3PDObject (**_args (level, 'LArCollisionTime' , kw))
+
+    from CaloD3PDMaker.MBTSD3PDObject                    import MBTSD3PDObject
+    alg += MBTSD3PDObject             (**_args (level, 'MBTS'             , kw))
+
+    from CaloD3PDMaker.MBTSTimeD3PDObject                import MBTSTimeD3PDObject
+    alg += MBTSTimeD3PDObject         (**_args (level, 'MBTSTime'         , kw))
+
+    from CaloD3PDMaker.MBTSTriggerBitsD3PDObject         import MBTSTriggerBitsD3PDObject
+    alg += MBTSTriggerBitsD3PDObject  (**_args (    1, 'MBTSTriggerBits'  , kw))
+
+    from CaloD3PDMaker.CollisionDecisionD3PDObject       import CollisionDecisionD3PDObject
+    alg += CollisionDecisionD3PDObject(**_args (level, 'CollisionDecision', kw))
+
+    from TrackD3PDMaker.BeamSpotD3PDObject               import BeamSpotD3PDObject
+    alg += BeamSpotD3PDObject(10)
+
+    from TriggerD3PDMaker.BunchStructureMetadata         import addBunchStructureMetadata
+    addBunchStructureMetadata( alg )
+
+    from QcdD3PDMaker.QcdEventShapeD3PDObject            import EventShapeD3PDObject
+    alg += EventShapeD3PDObject(**_args(0,'rho',kw))
+
+    from TopInputsD3PDMaker.HforD3PDObject               import HforD3PDObject
+    alg += HforD3PDObject (**_args (0, 'HforInfo', kw))
+    #-------------------------------------------------------------------------------------
+
+
+    #-------------------------------------------------------------------------------------
+    # Diphoton information...  in order to run this, need to have setup the diphoton
+    # analysis algorithm.  See PhotonD3PD_prodJobOFragment.py.
+    #
+    from PhotonD3PDMaker.DiPhotonD3PDObject              import DiPhotonD3PDObject
+    alg += DiPhotonD3PDObject         (**_args (level, 'DiPhoton'         , kw))
+    #-------------------------------------------------------------------------------------
+
+
+    #-------------------------------------------------------------------------------------
+    # Primary vertex info.  May be missing in single-beam data.
+    #
+    from TrackD3PDMaker.VertexD3PDObject    import PrimaryVertexD3PDObject
+    alg += PrimaryVertexD3PDObject (**_args (0, 'PrimaryVertex', kw,
+                                             allowMissing = True,
+                                             sgkey = D3PDMakerFlags.VertexSGKey(),
+                                             prefix = 'PV_'))
+    from PhotonD3PDMaker.PhotonPVD3PDObject import PVD3PDObject
+    alg += PVD3PDObject (**_args (0, 'PrimaryVertex', kw,
+                                  allowMissing = True,
+                                  sgkey = D3PDMakerFlags.VertexSGKey(),
+                                  prefix = 'PhotonPV_'))
+    #-------------------------------------------------------------------------------------
+
+
+    #-------------------------------------------------------------------------------------
+    # For dumping tracks
+    #
+    from PhotonD3PDMaker.AddTracksToD3PD import AddTracksToD3PD
+    AddTracksToD3PD(alg)
+    #-------------------------------------------------------------------------------------
+
+
+    #-------------------------------------------------------------------------------------
+    # I'm not even sure what this stuff is....
+    #
+    from EventCommonD3PDMaker.LBMetadataConfig           import LBMetadataConfig
+    alg.MetadataTools += [LBMetadataConfig()]
+
+    # I think this is usually false, so leave it in for now
+    if D3PDMakerFlags.FilterCollCand():
+        from CaloD3PDMaker.CollisionFilterAlg import CollisionFilterAlg
+        alg.filterSeq += CollisionFilterAlg (tuplename + '_CollCandFilter')
+    #-------------------------------------------------------------------------------------
+
+
+    #-------------------------------------------------------------------------------------
+    # Trigger output.
+    #
+    if D3PDMakerFlags.DoTrigger():
+        from PhotonD3PDMaker.AddTriggerToD3PD import AddTriggerToD3PD
+        AddTriggerToD3PD(alg, **kw)
+    #-------------------------------------------------------------------------------------
+
+
+    #-------------------------------------------------------------------------------------
+    # Missing ET information
+    #
+    from PhotonD3PDMaker.AddMETToD3PD import AddMETToD3PD
+    AddMETToD3PD(alg,CustomMETCollections, **kw)
+    #-------------------------------------------------------------------------------------
+
+    
+    #-------------------------------------------------------------------------------------
+    # For dumping cells.  Note that cell filter is configured in prodJO
+    #
+    from CaloD3PDMaker.CaloCellD3PDObject import AllCaloCellD3PDObject
+    alg += AllCaloCellD3PDObject(**_args (3, 'SelCells', kw,
+                                          prefix="cell_",
+                                          sgkey=PhotonD3PDMakerFlags.SelectedCellsContainerName(),
+                                          include=['RawPosition']))
+    #-------------------------------------------------------------------------------------
+
+
+    #-------------------------------------------------------------------------------------
+    # Muon information
+    #
+    from PhotonD3PDMaker.AddMuonsToD3PD import AddMuonsToD3PD
+    AddMuonsToD3PD(alg, stacoMuonContainer, caloMuonContainer, **kw)
+    #-------------------------------------------------------------------------------------
+
+
+    #-------------------------------------------------------------------------------------
+    # Tau information
+    #
+    if PhotonD3PDMakerFlags.DumpTauInformation():
+        from TauD3PDMaker.TauD3PDObject                        import TauD3PDObject
+        from TauD3PDMaker.makeTrackFilterAlg                   import makeTrackFilterAlg
+        alg += TauD3PDObject(**_args ( 0, 'Tau', kw,
+                                       include=['Kinematics','Charge','PID','TauJet',
+                                                'TauCommonDetails','TauCalcVars']))
+        if not hasattr( preseq, "GoodTracks" ):
+            filter1 = makeTrackFilterAlg(TracksName = D3PDMakerFlags.TrackSGKey(),
+                                         OutputTracksName='GoodTracks',
+                                         ptCut=0.,nSCTPix=4)
+            preseq += filter1
+    #-------------------------------------------------------------------------------------
+
+
+    #-------------------------------------------------------------------------------------
+    # Jet information
+    #
+    # See prodJobOFragment for jet algorithm config.
+    #
+    from PhotonD3PDMaker.AddJetsToD3PD import AddJetsToD3PD
+    AddJetsToD3PD(alg, **kw)
+    #-------------------------------------------------------------------------------------
+
+
+    #-------------------------------------------------------------------------------------
+    # add some extra information to the photons
+    #
+    from PhotonD3PDMaker.AddPhotonsToD3PD import AddPhotonsToD3PD
+    AddPhotonsToD3PD(alg, **kw)
+    #-------------------------------------------------------------------------------------
+
+
+    #-------------------------------------------------------------------------------------
+    # add electron->photon extrapolation stuff
+    #
+    if PhotonD3PDMakerFlags.DumpElectronToPhoton():
+        from PhotonD3PDMaker.ElectronToPhotonD3PDObject import ElectronToUnconvertedPhotonD3PDObject,ElectronToConvertedPhotonD3PDObject
+        alg += ElectronToUnconvertedPhotonD3PDObject(**_args(0, 'ElectronToUnconvertedPhoton', kw))
+        alg += ElectronToConvertedPhotonD3PDObject  (**_args(0, 'ElectronToConvertedPhoton', kw))
+    #-------------------------------------------------------------------------------------
+
+
+    #-------------------------------------------------------------------------------------
+    # Electrons, including GSF electrons
+    #
+    from PhotonD3PDMaker.AddElectronsToD3PD import AddElectronsToD3PD
+    AddElectronsToD3PD(alg, **kw)
+    #-------------------------------------------------------------------------------------
+
+    
+    # ------------------------------------------------------------------------------------
+    # Some truth filters, dumpers, and so on.
+    #
+    if rec.doTruth():
+        from PhotonD3PDMaker.AddTruthToD3PD import AddTruthToD3PD
+        AddTruthToD3PD(alg, **kw)
+    #-------------------------------------------------------------------------------------
+
+    return alg
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonD3PDMakerFlags.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonD3PDMakerFlags.py
new file mode 100644
index 0000000000000000000000000000000000000000..85044691a9f664bd66c327aeb276f264b4930311
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonD3PDMakerFlags.py
@@ -0,0 +1,216 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+from AthenaCommon.JobProperties import JobProperty, JobPropertyContainer
+from AthenaCommon.JobProperties import jobproperties
+
+class TruthParticleFilters(JobProperty):
+    statusOn = True
+    allowedTypes = ['list']
+    StoredValue = []
+
+class JetCollections(JobProperty):
+    statusOn = True
+    allowedTypes = ['string','list']
+    StoredValue = ['AntiKt4TopoEMJets','AntiKt6TopoEMJets','AntiKt4LCTopoJets','AntiKt6LCTopoJets']
+
+class alltruthjets(JobProperty):
+    statusOn = True
+    allowedTypes = ['string','list']
+    StoredValue = []
+
+class FillR0p6Jets(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool']
+    StoredValue = True
+
+class DumpNearbyTracks(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool']
+    StoredValue = True
+
+class DumpAllTracks(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool']
+    StoredValue = False
+
+class ElectronDumpingLevel(JobProperty):
+    statusOn = True
+    allowedTypes = ['int']
+    StoredValue = 10
+
+class DumpElectronToPhoton(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool']
+    StoredValue = True
+
+class DumpLotsOfTriggerInfo(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool']
+    StoredValue = False
+
+class DumpTauInformation(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool']
+    StoredValue = True
+
+class DumpTriggerObjectsInfo(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool']
+    StoredValue = True
+
+class DumpDetailedIsolationVariables(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool']
+    StoredValue = False
+
+class FillFullJVF(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool']
+    StoredValue = True
+
+class ReCalculateJetMoments(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool']
+    StoredValue = False
+
+class FillFullMET(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool']
+    StoredValue = True
+
+class RemoveTopoClusterCandidates(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool']
+    StoredValue = True
+
+class Fill_Etcone_ED_corrected(JobProperty):
+    statusOn = True
+    allowedTypes = ['list']
+    StoredValue = [40]
+
+class Fill_Etcone_corrected(JobProperty):
+    statusOn = True
+    allowedTypes = ['list']
+    StoredValue = [40]
+
+class Fill_TopoEtcone_corrected(JobProperty):
+    statusOn = True
+    allowedTypes = ['list']
+    StoredValue = [20,30,40]
+
+class Fill_ED_info(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool']
+    StoredValue = True
+
+class ConfigureCaloDepthTool(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool']
+    StoredValue = True
+
+class CaloDepth(JobProperty):
+    statusOn = True
+    allowedTypes = ['str']
+    StoredValue = 'showerdefault'
+
+class EnableBTagging(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool']
+    StoredValue = True
+
+class BTaggingSuffix(JobProperty):
+    statusOn = True
+    allowedTypes = ['str']
+    StoredValue = ""
+
+class RetagTruthBJets(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool']
+    StoredValue = True
+
+class AdditionalMETOutputLevel(JobProperty):
+    statusOn = True
+    allowedTypes = ['int']
+    StoredValue = 2
+
+class FilterTracksForMET(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool']
+    StoredValue = False
+
+class SaveAllTruthParticles(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool']
+    StoredValue = True
+
+class CellDrCut(JobProperty):
+    statusOn = True
+    allowedTypes = ['float']
+    StoredValue = 0.4
+
+class SelectedCellsContainerName(JobProperty):
+    statusOn = True
+    allowedTypes = ['str']
+    StoredValue = "SelectedCells"
+
+class JetTagD3PD_CollectionPostfix(JobProperty):
+    statusOn = True
+    allowedTypes = ['str']
+    StoredValue = ""
+
+class FillMV3(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool']
+    StoredValue = True
+
+class FillJetFitterCharm(JobProperty):
+    statusOn = True
+    allowedTypes = ['bool']
+    StoredValue = True
+
+class PhotonD3PDMakerFlags(JobPropertyContainer):
+    pass
+
+jobproperties.add_Container(PhotonD3PDMakerFlags)
+list_jobproperties = [
+    TruthParticleFilters,
+    JetCollections,
+    DumpNearbyTracks,
+    DumpAllTracks,
+    ElectronDumpingLevel,
+    DumpElectronToPhoton,
+    DumpLotsOfTriggerInfo,
+    DumpTriggerObjectsInfo,
+    DumpDetailedIsolationVariables,
+    FillFullJVF,
+    ReCalculateJetMoments,
+    FillFullMET,
+    DumpTauInformation,
+    RemoveTopoClusterCandidates,
+    Fill_Etcone_ED_corrected,
+    Fill_Etcone_corrected,
+    Fill_TopoEtcone_corrected,
+    Fill_ED_info,
+    ConfigureCaloDepthTool,
+    CaloDepth,
+    EnableBTagging,
+    BTaggingSuffix,
+    RetagTruthBJets,
+    AdditionalMETOutputLevel,
+    FilterTracksForMET,
+    SaveAllTruthParticles,
+    FillR0p6Jets,
+    CellDrCut,
+    SelectedCellsContainerName,
+    JetTagD3PD_CollectionPostfix,
+    alltruthjets,
+    FillMV3,
+    FillJetFitterCharm
+    ]
+
+for i in list_jobproperties:
+    jobproperties.PhotonD3PDMakerFlags.add_JobProperty(i)
+
+del list_jobproperties
+
+PhotonD3PDMakerFlags=jobproperties.PhotonD3PDMakerFlags
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonMET.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonMET.py
new file mode 100644
index 0000000000000000000000000000000000000000..0cba542aaaa9abb1a527f0382838837e2a9b6831
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonMET.py
@@ -0,0 +1,527 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+from RecExConfig.RecFlags                            import rec
+from AthenaCommon.SystemOfUnits                      import GeV
+from AthenaPython.PyAthena                           import egammaPID
+from MissingET.METRefGetter_plup                     import make_METRefAlg
+from PhotonAnalysisUtils.PhotonNeuralNetworkTool     import PhotonNeuralNetworkTool
+from D3PDMakerConfig.D3PDMakerFlags                  import D3PDMakerFlags
+from AthenaCommon.AlgSequence                        import AlgSequence
+from QcdD3PDMaker.QcdD3PDMakerFlags                  import QcdD3PDMakerFlags
+from PhotonD3PDMaker.PhotonD3PDMakerFlags            import PhotonD3PDMakerFlags
+
+import D3PDMakerCoreComps
+import PhotonD3PDMaker
+
+import AthenaPython.PyAthena as PyAthena
+PyAthena.load_library('egammaEnumsDict')
+
+
+def addPhotonMET():
+    from AthenaCommon.AppMgr                             import ToolSvc
+
+    topSequence = AlgSequence()    
+
+    photongetter = D3PDMakerCoreComps.SGDataVectorGetterTool('photonTight_Getter',
+                                                             TypeName = 'PhotonContainer',
+                                                             SGKey = D3PDMakerFlags.PhotonSGKey())
+    ToolSvc += photongetter
+
+    electrongetter = D3PDMakerCoreComps.SGDataVectorGetterTool('electronTight_Getter',
+                                                               TypeName = 'ElectronContainer',
+                                                               SGKey = D3PDMakerFlags.ElectronSGKey())
+    ToolSvc += electrongetter
+
+    # -------------------------------------------------------------------------------------------
+    #
+    # Filters for NN!!!
+    #
+    # add a filter to select NN tight photons
+    #
+    photonFilterNNTight = PhotonD3PDMaker.PhotonFilter(OutputCollectionName="SelectedPhotonsNNTight",
+                                                       photonGetter = photongetter,
+                                                       ptCut = 20000,
+                                                       etaCut = 2.5,
+                                                       IsEM = 0,
+                                                       NNCut = True,
+                                                       PhotonNNTool = PhotonNeuralNetworkTool())
+    topSequence += photonFilterNNTight
+
+    #
+    # add a filter to select normal electrons
+    #
+    electrongetter = D3PDMakerCoreComps.SGDataVectorGetterTool('electronNNTight_Getter',
+                                                               TypeName = 'ElectronContainer',
+                                                               SGKey = D3PDMakerFlags.ElectronSGKey())
+    ToolSvc += electrongetter
+
+    #
+    # add a filter that will create both photon and electron containers, with proper overlap removal (OR)
+    #
+    egammaORFilter_NN = PhotonD3PDMaker.EgammaFilter('egammaOR_Filter_NN',
+                                                     OutputElectronCollectionName="SelectedORElectronsNNTight",
+                                                     ElectronGetter = electrongetter,
+                                                     ElectronPtCut = 10000,
+                                                     ElectronEtaCut = 2.47,
+                                                     ElectronIsEM = egammaPID.ElectronIDMediumPP,
+                                                     OutputPhotonCollectionName="SelectedORPhotonsNNTight",
+                                                     PhotonGetter = photongetter,
+                                                     PhotonPtCut = 20000,
+                                                     PhotonEtaCut = 2.37,
+                                                     PhotonIsEM = 0,
+                                                     PhotonNNCut = True,
+                                                     PhotonNNTool = PhotonNeuralNetworkTool())
+    topSequence += egammaORFilter_NN
+
+
+    #
+    # add a filter that will create both photon and electron containers, with proper overlap removal (OR)
+    # but using standard Tight
+    #    
+    egammaORFilter_tight = PhotonD3PDMaker.EgammaFilter('egamma_OR_Filter_tight',
+                                                        OutputElectronCollectionName="SelectedORElectronsTight",
+                                                        ElectronGetter = electrongetter,
+                                                        ElectronPtCut = 10000,
+                                                        ElectronEtaCut = 2.47,
+                                                        ElectronIsEM = egammaPID.ElectronIDMediumPP,
+                                                        OutputPhotonCollectionName="SelectedORPhotonsTight",
+                                                        PhotonGetter = photongetter,
+                                                        PhotonPtCut = 20000,
+                                                        PhotonEtaCut = 2.37,
+                                                        PhotonIsEM = egammaPID.PhotonIDTight,
+                                                        PhotonNNCut = False,
+                                                        PhotonNNTool = PhotonNeuralNetworkTool())
+    topSequence += egammaORFilter_tight                      
+    # add a filter that will create both photon and electron containers, 
+    # with proper overlap removal (OR) but using standard Loose   
+    egammaORFilter_loose = PhotonD3PDMaker.EgammaFilter('egamma_OR_Filter_loose',
+                                                        OutputElectronCollectionName="SelectedORElectronsLoose",
+                                                        ElectronGetter = electrongetter,
+                                                        ElectronPtCut = 10000,
+                                                        ElectronEtaCut = 2.47,
+                                                        ElectronIsEM = egammaPID.ElectronIDMediumPP,
+                                                        OutputPhotonCollectionName="SelectedORPhotonsLoose",
+                                                        PhotonGetter = photongetter,
+                                                        PhotonPtCut = 20000,
+                                                        PhotonEtaCut = 2.37,
+                                                        PhotonIsEM = egammaPID.PhotonIDLoose,
+                                                        PhotonNNCut = False,
+                                                        PhotonNNTool = PhotonNeuralNetworkTool())
+    topSequence += egammaORFilter_loose
+
+    # -------------------------------------------------------------------------------------------
+
+    METcollections=[]
+
+    # Toggle for setting some options that we used to enable for various STVF configurations,
+    # before the MET configuration changes in 17.2.7.4.1.
+    doOldConfiguration=False
+
+    # Loose photons
+    if PhotonD3PDMakerFlags.AdditionalMETOutputLevel() > 1:
+        suffix='_PhotonLoose_Calib_OR_stdvert'
+        MET_PhotonLoose_Calib_OR_stdvert = make_METRefAlg(_suffix=suffix)
+        MET_PhotonLoose_Calib_OR_stdvert.photon_doPhotonTool              = True
+        MET_PhotonLoose_Calib_OR_stdvert.gamma_noCut                      = True
+        MET_PhotonLoose_Calib_OR_stdvert.gamma_EgammaInputCollectionKey   = "SelectedORPhotonsLoose"
+        MET_PhotonLoose_Calib_OR_stdvert.gamma_EleInputCollectionKey      = "SelectedORElectronsLoose"
+        MET_PhotonLoose_Calib_OR_stdvert.gamma_calibType                  = "RefCalib"
+        MET_PhotonLoose_Calib_OR_stdvert.ele_noCut                        = True
+        MET_PhotonLoose_Calib_OR_stdvert.ele_EgammaInputCollectionKey     = "SelectedORElectronsLoose"
+        MET_PhotonLoose_Calib_OR_stdvert.ele_calibType                    = "RefCalib"
+        MET_PhotonLoose_Calib_OR_stdvert.jet_calibType                    = 'ExclRefCalib'
+        if doOldConfiguration:
+            MET_PhotonLoose_Calib_OR_stdvert.jet_UseCustomVxContainer         = False
+            MET_PhotonLoose_Calib_OR_stdvert.jet_JetInputCollectionKey        ='AntiKt4LCTopoJets'
+            MET_PhotonLoose_Calib_OR_stdvert.jet_JetPtCut                     = 20.0*GeV
+            MET_PhotonLoose_Calib_OR_stdvert.jet_ApplyJetScale                = "Yes"
+            MET_PhotonLoose_Calib_OR_stdvert.jet_UseJetMomentForScale         = True
+            MET_PhotonLoose_Calib_OR_stdvert.jet_JetMomentForScale            = "LCJES"
+            MET_PhotonLoose_Calib_OR_stdvert.jet_ApplyJetJVF                  = "Yes"
+            MET_PhotonLoose_Calib_OR_stdvert.jet_RunSoftJetsTool              = False
+            MET_PhotonLoose_Calib_OR_stdvert.cellout_calibType                ='Eflow'
+            MET_PhotonLoose_Calib_OR_stdvert.tau_calibType                    ='ExclRefCalib'
+            MET_PhotonLoose_Calib_OR_stdvert.cryo_ApplyCorrection             = "Off"
+            MET_PhotonLoose_Calib_OR_stdvert.muon_algorithm                   = "Staco"
+            MET_PhotonLoose_Calib_OR_stdvert.muon_isolationAlg                = "dRJet"
+        MET_PhotonLoose_Calib_OR_stdvert()
+        METcollections += [suffix]
+
+
+    # tight photons
+    if PhotonD3PDMakerFlags.AdditionalMETOutputLevel() > 1:
+        suffix='_PhotonTight_Calib_OR_stdvert'
+        MET_PhotonTight_Calib_OR_stdvert = make_METRefAlg(_suffix=suffix)
+        MET_PhotonTight_Calib_OR_stdvert.photon_doPhotonTool              = True
+        MET_PhotonTight_Calib_OR_stdvert.gamma_noCut                      = True
+        MET_PhotonTight_Calib_OR_stdvert.gamma_EgammaInputCollectionKey   = "SelectedORPhotonsTight"
+        MET_PhotonTight_Calib_OR_stdvert.gamma_EleInputCollectionKey      = "SelectedORElectronsTight"
+        MET_PhotonTight_Calib_OR_stdvert.gamma_calibType                  = "RefCalib"
+        MET_PhotonTight_Calib_OR_stdvert.ele_noCut                        = True
+        MET_PhotonTight_Calib_OR_stdvert.ele_EgammaInputCollectionKey     = "SelectedORElectronsTight"
+        MET_PhotonTight_Calib_OR_stdvert.ele_calibType                    = "RefCalib"
+        MET_PhotonTight_Calib_OR_stdvert.jet_calibType                    = 'ExclRefCalib'
+        if doOldConfiguration:
+            MET_PhotonTight_Calib_OR_stdvert.jet_UseCustomVxContainer         = False
+            MET_PhotonTight_Calib_OR_stdvert.jet_JetInputCollectionKey        ='AntiKt4LCTopoJets'
+            MET_PhotonTight_Calib_OR_stdvert.jet_JetPtCut                     = 20.0*GeV
+            MET_PhotonTight_Calib_OR_stdvert.jet_ApplyJetScale                = "Yes"
+            MET_PhotonTight_Calib_OR_stdvert.jet_UseJetMomentForScale         = True
+            MET_PhotonTight_Calib_OR_stdvert.jet_JetMomentForScale            = "LCJES"
+            MET_PhotonTight_Calib_OR_stdvert.jet_ApplyJetJVF                  = "Yes"
+            MET_PhotonTight_Calib_OR_stdvert.jet_RunSoftJetsTool              = False
+            MET_PhotonTight_Calib_OR_stdvert.cellout_calibType                ='Eflow'
+            MET_PhotonTight_Calib_OR_stdvert.tau_calibType                    ='ExclRefCalib'
+            MET_PhotonTight_Calib_OR_stdvert.cryo_ApplyCorrection             = "Off"
+            MET_PhotonTight_Calib_OR_stdvert.muon_algorithm                   = "Staco"
+            MET_PhotonTight_Calib_OR_stdvert.muon_isolationAlg                = "dRJet"
+        MET_PhotonTight_Calib_OR_stdvert()
+        METcollections += [suffix]
+
+    
+    # NNTight photons
+    if PhotonD3PDMakerFlags.AdditionalMETOutputLevel() > 1:
+        suffix = '_NNTight_Calib_OR_stdvert'
+        MET_NNTight_Calib_OR_stdvert = make_METRefAlg(_suffix=suffix)
+        MET_NNTight_Calib_OR_stdvert.photon_doPhotonTool              = True
+        MET_NNTight_Calib_OR_stdvert.gamma_noCut                      = True
+        MET_NNTight_Calib_OR_stdvert.gamma_EgammaInputCollectionKey   = "SelectedORPhotonsNNTight"
+        MET_NNTight_Calib_OR_stdvert.gamma_EleInputCollectionKey      = "SelectedORElectronsNNTight"
+        MET_NNTight_Calib_OR_stdvert.gamma_calibType                  = "RefCalib"
+        MET_NNTight_Calib_OR_stdvert.ele_noCut                        = True
+        MET_NNTight_Calib_OR_stdvert.ele_EgammaInputCollectionKey     = "SelectedORElectronsNNTight"
+        MET_NNTight_Calib_OR_stdvert.ele_calibType                    = "RefCalib"
+        MET_NNTight_Calib_OR_stdvert.jet_calibType                    = 'ExclRefCalib'
+        if doOldConfiguration:
+            MET_NNTight_Calib_OR_stdvert.jet_JetInputCollectionKey   ='AntiKt4LCTopoJets'
+            MET_NNTight_Calib_OR_stdvert.jet_JetPtCut                = 20.0*GeV
+            MET_NNTight_Calib_OR_stdvert.jet_ApplyJetScale           = "Yes"
+            MET_NNTight_Calib_OR_stdvert.jet_UseJetMomentForScale    = True
+            MET_NNTight_Calib_OR_stdvert.jet_JetMomentForScale       = "LCJES"
+            MET_NNTight_Calib_OR_stdvert.jet_ApplyJetJVF             = "Yes"
+            MET_NNTight_Calib_OR_stdvert.jet_RunSoftJetsTool         = False
+            MET_NNTight_Calib_OR_stdvert.cellout_calibType           ='Eflow'
+            MET_NNTight_Calib_OR_stdvert.tau_calibType               ='ExclRefCalib'
+            MET_NNTight_Calib_OR_stdvert.cryo_ApplyCorrection        = "Off"
+            MET_NNTight_Calib_OR_stdvert.muon_algorithm              = "Staco"
+            MET_NNTight_Calib_OR_stdvert.muon_isolationAlg           = "dRJet"
+        MET_NNTight_Calib_OR_stdvert()
+        METcollections += [suffix]
+
+
+    #-------------------------------------------------------------------------------------------------
+    # Probably not-needed collections, but kept for detailed studies if people need them.
+    # Use at your own risk!
+    #-------------------------------------------------------------------------------------------------
+
+    # Loose photons
+    if PhotonD3PDMakerFlags.AdditionalMETOutputLevel() > 3:
+        suffix='_PhotonLoose_EmScale'
+        MET_PhotonLoose_EmScale = make_METRefAlg(_suffix=suffix)
+        MET_PhotonLoose_EmScale.photon_doPhotonTool         = True
+        MET_PhotonLoose_EmScale.gamma_EtCut                 = 20.0*GeV;
+        MET_PhotonLoose_EmScale.gamma_isEM                  = egammaPID.PhotonIDLoose
+        MET_PhotonLoose_EmScale.gamma_calibType             = "EmScale"
+        MET_PhotonLoose_EmScale()
+        METcollections += [suffix]
+
+    # tight photons
+    if PhotonD3PDMakerFlags.AdditionalMETOutputLevel() > 3:
+        suffix='_PhotonTight_EmScale_stdvert'
+        MET_PhotonTight_EmScale_stdvert = make_METRefAlg(_suffix=suffix)
+        MET_PhotonTight_EmScale_stdvert.photon_doPhotonTool         = True
+        MET_PhotonTight_EmScale_stdvert.gamma_EtCut                 = 20.0*GeV;
+        MET_PhotonTight_EmScale_stdvert.gamma_isEM                  = egammaPID.PhotonIDTight
+        MET_PhotonTight_EmScale_stdvert.gamma_calibType             = "EmScale"
+        MET_PhotonTight_EmScale_stdvert.jet_UseCustomVxContainer    = False
+        MET_PhotonTight_EmScale_stdvert.jet_JetInputCollectionKey   ='AntiKt4LCTopoJets'
+        MET_PhotonTight_EmScale_stdvert.jet_JetPtCut                = 20.0*GeV
+        MET_PhotonTight_EmScale_stdvert.jet_ApplyJetScale           = "Yes"
+        MET_PhotonTight_EmScale_stdvert.jet_UseJetMomentForScale    = True
+        MET_PhotonTight_EmScale_stdvert.jet_JetMomentForScale       = "LCJES"
+        MET_PhotonTight_EmScale_stdvert.jet_ApplyJetJVF             = "Yes"
+        MET_PhotonTight_EmScale_stdvert.jet_RunSoftJetsTool         = False
+        MET_PhotonTight_EmScale_stdvert.jet_calibType               = 'ExclRefCalib'
+        MET_PhotonTight_EmScale_stdvert.ele_calibType               ='RefCalib'
+        MET_PhotonTight_EmScale_stdvert.cellout_calibType           ='Eflow'
+        MET_PhotonTight_EmScale_stdvert.tau_calibType               ='ExclRefCalib'
+        MET_PhotonTight_EmScale_stdvert.cryo_ApplyCorrection        = "Off"
+        MET_PhotonTight_EmScale_stdvert.muon_algorithm              = "Staco"
+        MET_PhotonTight_EmScale_stdvert.muon_isolationAlg           = "dRJet"
+        MET_PhotonTight_EmScale_stdvert()
+        METcollections += [suffix]
+    
+    if PhotonD3PDMakerFlags.AdditionalMETOutputLevel() > 3:
+        suffix='_PhotonTight_EmScale_newvert'
+        MET_PhotonTight_EmScale_newvert = make_METRefAlg(_suffix=suffix)
+        MET_PhotonTight_EmScale_newvert.photon_doPhotonTool         = True
+        MET_PhotonTight_EmScale_newvert.gamma_EtCut                 = 20.0*GeV;
+        MET_PhotonTight_EmScale_newvert.gamma_isEM                  = egammaPID.PhotonIDTight
+        MET_PhotonTight_EmScale_newvert.gamma_calibType             = "EmScale"
+        MET_PhotonTight_EmScale_newvert.jet_vxcontainerkey          = "PAUDiphotonVertexCollection"
+        MET_PhotonTight_EmScale_newvert.jet_UseCustomVxContainer    = True
+        MET_PhotonTight_EmScale_newvert.cellout_vxcontainerkey      = "PAUDiphotonVertexCollection"
+        MET_PhotonTight_EmScale_newvert.jet_JetInputCollectionKey   ='AntiKt4LCTopoJets'
+        MET_PhotonTight_EmScale_newvert.jet_JetPtCut                = 20.0*GeV
+        MET_PhotonTight_EmScale_newvert.jet_ApplyJetScale           = "Yes"
+        MET_PhotonTight_EmScale_newvert.jet_UseJetMomentForScale    = True
+        MET_PhotonTight_EmScale_newvert.jet_JetMomentForScale       = "LCJES"
+        MET_PhotonTight_EmScale_newvert.jet_ApplyJetJVF             = "Yes"
+        MET_PhotonTight_EmScale_newvert.jet_RunSoftJetsTool         = False
+        MET_PhotonTight_EmScale_newvert.jet_calibType               = 'ExclRefCalib'
+        MET_PhotonTight_EmScale_newvert.ele_calibType               ='RefCalib'
+        MET_PhotonTight_EmScale_newvert.cellout_calibType           ='Eflow'    
+        MET_PhotonTight_EmScale_newvert.tau_calibType               ='ExclRefCalib'
+        MET_PhotonTight_EmScale_newvert.cryo_ApplyCorrection        = "Off"
+        MET_PhotonTight_EmScale_newvert.muon_algorithm              = "Staco"
+        MET_PhotonTight_EmScale_newvert.muon_isolationAlg           = "dRJet"
+        MET_PhotonTight_EmScale_newvert()
+        METcollections += [suffix]
+    
+    if PhotonD3PDMakerFlags.AdditionalMETOutputLevel() > 3:
+        suffix='_PhotonTight_Calib_newvert'
+        MET_PhotonTight_Calib_newvert = make_METRefAlg(_suffix=suffix)
+        MET_PhotonTight_Calib_newvert.photon_doPhotonTool         = True
+        MET_PhotonTight_Calib_newvert.gamma_EtCut                 = 20.0*GeV;
+        MET_PhotonTight_Calib_newvert.gamma_isEM                  = egammaPID.PhotonIDTight
+        MET_PhotonTight_Calib_newvert.gamma_calibType             = "RefCalib"
+        MET_PhotonTight_Calib_newvert.jet_vxcontainerkey          = "PAUDiphotonVertexCollection"
+        MET_PhotonTight_Calib_newvert.jet_UseCustomVxContainer    = True
+        MET_PhotonTight_Calib_newvert.cellout_vxcontainerkey      = "PAUDiphotonVertexCollection"
+        MET_PhotonTight_Calib_newvert.jet_JetInputCollectionKey   ='AntiKt4LCTopoJets'
+        MET_PhotonTight_Calib_newvert.jet_JetPtCut                = 20.0*GeV
+        MET_PhotonTight_Calib_newvert.jet_ApplyJetScale           = "Yes"
+        MET_PhotonTight_Calib_newvert.jet_UseJetMomentForScale    = True
+        MET_PhotonTight_Calib_newvert.jet_JetMomentForScale       = "LCJES"
+        MET_PhotonTight_Calib_newvert.jet_ApplyJetJVF             = "Yes"
+        MET_PhotonTight_Calib_newvert.jet_RunSoftJetsTool         = False
+        MET_PhotonTight_Calib_newvert.jet_calibType               = 'ExclRefCalib'
+        MET_PhotonTight_Calib_newvert.ele_calibType               ='RefCalib'
+        MET_PhotonTight_Calib_newvert.cellout_calibType           ='Eflow'
+        MET_PhotonTight_Calib_newvert.tau_calibType               ='ExclRefCalib'
+        MET_PhotonTight_Calib_newvert.cryo_ApplyCorrection        = "Off"
+        MET_PhotonTight_Calib_newvert.muon_algorithm              = "Staco"
+        MET_PhotonTight_Calib_newvert.muon_isolationAlg           = "dRJet"
+        MET_PhotonTight_Calib_newvert()
+        METcollections += [suffix]
+    
+    if PhotonD3PDMakerFlags.AdditionalMETOutputLevel() > 3:
+        suffix='_PhotonTight_Calib_OR_newvert'
+        MET_PhotonTight_Calib_OR_newvert = make_METRefAlg(_suffix=suffix)
+        MET_PhotonTight_Calib_OR_newvert.photon_doPhotonTool              = True
+        MET_PhotonTight_Calib_OR_newvert.gamma_noCut                      = True
+        MET_PhotonTight_Calib_OR_newvert.gamma_EgammaInputCollectionKey   = "SelectedORPhotonsTight"
+        MET_PhotonTight_Calib_OR_newvert.gamma_EleInputCollectionKey      = "SelectedORElectronsTight"
+        MET_PhotonTight_Calib_OR_newvert.gamma_calibType                  = "RefCalib"
+        MET_PhotonTight_Calib_OR_newvert.ele_noCut                        = True
+        MET_PhotonTight_Calib_OR_newvert.ele_EgammaInputCollectionKey     = "SelectedORElectronsTight"
+        MET_PhotonTight_Calib_OR_newvert.ele_calibType                    = "RefCalib"
+        MET_PhotonTight_Calib_OR_newvert.jet_vxcontainerkey               = "PAUDiphotonVertexCollection"
+        MET_PhotonTight_Calib_OR_newvert.jet_UseCustomVxContainer         = True
+        MET_PhotonTight_Calib_OR_newvert.cellout_vxcontainerkey           = "PAUDiphotonVertexCollection"    
+        MET_PhotonTight_Calib_OR_newvert.jet_JetInputCollectionKey        ='AntiKt4LCTopoJets'
+        MET_PhotonTight_Calib_OR_newvert.jet_JetPtCut                     = 20.0*GeV
+        MET_PhotonTight_Calib_OR_newvert.jet_ApplyJetScale                = "Yes"
+        MET_PhotonTight_Calib_OR_newvert.jet_UseJetMomentForScale         = True
+        MET_PhotonTight_Calib_OR_newvert.jet_JetMomentForScale            = "LCJES"
+        MET_PhotonTight_Calib_OR_newvert.jet_ApplyJetJVF                  = "Yes"
+        MET_PhotonTight_Calib_OR_newvert.jet_RunSoftJetsTool              = False
+        MET_PhotonTight_Calib_OR_newvert.jet_calibType                    = 'ExclRefCalib'
+        MET_PhotonTight_Calib_OR_newvert.ele_calibType                    ='RefCalib'
+        MET_PhotonTight_Calib_OR_newvert.cellout_calibType                ='Eflow'
+        MET_PhotonTight_Calib_OR_newvert.tau_calibType                    ='ExclRefCalib'
+        MET_PhotonTight_Calib_OR_newvert.cryo_ApplyCorrection             = "Off"
+        MET_PhotonTight_Calib_OR_newvert.muon_algorithm                   = "Staco"
+        MET_PhotonTight_Calib_OR_newvert.muon_isolationAlg                = "dRJet"
+        MET_PhotonTight_Calib_OR_newvert()
+        METcollections += [suffix]
+
+    if PhotonD3PDMakerFlags.AdditionalMETOutputLevel() > 3:
+        suffix='_PhotonTight_EmScale_OR_newvert'
+        MET_PhotonTight_EmScale_OR_newvert = make_METRefAlg(_suffix=suffix)
+        MET_PhotonTight_EmScale_OR_newvert.photon_doPhotonTool              = True
+        MET_PhotonTight_EmScale_OR_newvert.gamma_noCut                      = True
+        MET_PhotonTight_EmScale_OR_newvert.gamma_EgammaInputCollectionKey   = "SelectedORPhotonsTight"
+        MET_PhotonTight_EmScale_OR_newvert.gamma_EleInputCollectionKey      = "SelectedORElectronsTight"
+        MET_PhotonTight_EmScale_OR_newvert.gamma_calibType                  = "EmScale"
+        MET_PhotonTight_EmScale_OR_newvert.ele_noCut                        = True
+        MET_PhotonTight_EmScale_OR_newvert.ele_EgammaInputCollectionKey     = "SelectedORElectronsTight"
+        MET_PhotonTight_EmScale_OR_newvert.ele_calibType                    = "RefCalib"
+        MET_PhotonTight_EmScale_OR_newvert.jet_vxcontainerkey               = "PAUDiphotonVertexCollection"
+        MET_PhotonTight_EmScale_OR_newvert.jet_UseCustomVxContainer         = True
+        MET_PhotonTight_EmScale_OR_newvert.cellout_vxcontainerkey           = "PAUDiphotonVertexCollection"
+        MET_PhotonTight_EmScale_OR_newvert.jet_JetInputCollectionKey        ='AntiKt4LCTopoJets'
+        MET_PhotonTight_EmScale_OR_newvert.jet_JetPtCut                     = 20.0*GeV
+        MET_PhotonTight_EmScale_OR_newvert.jet_ApplyJetScale                = "Yes"
+        MET_PhotonTight_EmScale_OR_newvert.jet_UseJetMomentForScale         = True
+        MET_PhotonTight_EmScale_OR_newvert.jet_JetMomentForScale            = "LCJES"
+        MET_PhotonTight_EmScale_OR_newvert.jet_ApplyJetJVF                  = "Yes"
+        MET_PhotonTight_EmScale_OR_newvert.jet_RunSoftJetsTool              = False
+        MET_PhotonTight_EmScale_OR_newvert.jet_calibType                    = 'ExclRefCalib'
+        MET_PhotonTight_EmScale_OR_newvert.ele_calibType                    ='RefCalib'
+        MET_PhotonTight_EmScale_OR_newvert.cellout_calibType                ='Eflow'
+        MET_PhotonTight_EmScale_OR_newvert.tau_calibType                    ='ExclRefCalib'
+        MET_PhotonTight_EmScale_OR_newvert.cryo_ApplyCorrection             = "Off"
+        MET_PhotonTight_EmScale_OR_newvert.muon_algorithm                   = "Staco"
+        MET_PhotonTight_EmScale_OR_newvert.muon_isolationAlg                = "dRJet"
+        MET_PhotonTight_EmScale_OR_newvert()
+        METcollections += [suffix]
+
+    if PhotonD3PDMakerFlags.AdditionalMETOutputLevel() > 3:
+        suffix='_PhotonTight_Calib'
+        MET_PhotonTight_Calib = make_METRefAlg(_suffix=suffix)
+        MET_PhotonTight_Calib.photon_doPhotonTool         = True
+        MET_PhotonTight_Calib.gamma_EtCut                 = 20.0*GeV;
+        MET_PhotonTight_Calib.gamma_isEM                  = egammaPID.PhotonIDTight
+        MET_PhotonTight_Calib.gamma_calibType             = "RefCalib"
+        MET_PhotonTight_Calib()
+        METcollections += [suffix]
+    
+    # NN tight photons
+    if PhotonD3PDMakerFlags.AdditionalMETOutputLevel() > 3:
+        suffix='_NNTight_EmScale_stdvert'
+        MET_NNTight_EmScale_stdvert = make_METRefAlg(_suffix=suffix)
+        MET_NNTight_EmScale_stdvert.photon_doPhotonTool              = True
+        MET_NNTight_EmScale_stdvert.gamma_noCut                      = True
+        MET_NNTight_EmScale_stdvert.gamma_EgammaInputCollectionKey   = "SelectedPhotonsNNTight"
+        MET_NNTight_EmScale_stdvert.gamma_calibType                  = "EmScale"
+        MET_NNTight_EmScale_stdvert.jet_JetInputCollectionKey   ='AntiKt4LCTopoJets'
+        MET_NNTight_EmScale_stdvert.jet_JetPtCut                = 20.0*GeV
+        MET_NNTight_EmScale_stdvert.jet_ApplyJetScale           = "Yes"
+        MET_NNTight_EmScale_stdvert.jet_UseJetMomentForScale    = True
+        MET_NNTight_EmScale_stdvert.jet_JetMomentForScale       = "LCJES"
+        MET_NNTight_EmScale_stdvert.jet_ApplyJetJVF             = "Yes"
+        MET_NNTight_EmScale_stdvert.jet_RunSoftJetsTool         = False
+        MET_NNTight_EmScale_stdvert.jet_calibType               = 'ExclRefCalib'
+        MET_NNTight_EmScale_stdvert.cellout_calibType           ='Eflow'
+        MET_NNTight_EmScale_stdvert.tau_calibType               ='ExclRefCalib'
+        MET_NNTight_EmScale_stdvert.cryo_ApplyCorrection        = "Off"
+        MET_NNTight_EmScale_stdvert.muon_algorithm              = "Staco"
+        MET_NNTight_EmScale_stdvert.muon_isolationAlg           = "dRJet"
+        MET_NNTight_EmScale_stdvert()
+        METcollections += [suffix]
+
+    if PhotonD3PDMakerFlags.AdditionalMETOutputLevel() > 3:
+        suffix='_NNTight_EmScale_OR_stdvert'
+        MET_NNTight_EmScale_OR_stdvert = make_METRefAlg(_suffix=suffix)
+        MET_NNTight_EmScale_OR_stdvert.photon_doPhotonTool              = True
+        MET_NNTight_EmScale_OR_stdvert.gamma_noCut                      = True
+        MET_NNTight_EmScale_OR_stdvert.gamma_EgammaInputCollectionKey   = "SelectedORPhotonsNNTight"
+        MET_NNTight_EmScale_OR_stdvert.gamma_EleInputCollectionKey      = "SelectedORElectronsNNTight"
+        MET_NNTight_EmScale_OR_stdvert.gamma_calibType                  = "EmScale"
+        MET_NNTight_EmScale_OR_stdvert.ele_noCut                        = True
+        MET_NNTight_EmScale_OR_stdvert.ele_EgammaInputCollectionKey     = "SelectedORElectronsNNTight"
+        MET_NNTight_EmScale_OR_stdvert.ele_calibType                    = "RefCalib"
+        MET_NNTight_EmScale_OR_stdvert.jet_JetInputCollectionKey   ='AntiKt4LCTopoJets'
+        MET_NNTight_EmScale_OR_stdvert.jet_JetPtCut                = 20.0*GeV
+        MET_NNTight_EmScale_OR_stdvert.jet_ApplyJetScale           = "Yes"
+        MET_NNTight_EmScale_OR_stdvert.jet_UseJetMomentForScale    = True
+        MET_NNTight_EmScale_OR_stdvert.jet_JetMomentForScale       = "LCJES"
+        MET_NNTight_EmScale_OR_stdvert.jet_ApplyJetJVF             = "Yes"
+        MET_NNTight_EmScale_OR_stdvert.jet_RunSoftJetsTool         = False
+        MET_NNTight_EmScale_OR_stdvert.jet_calibType               = 'ExclRefCalib'
+        MET_NNTight_EmScale_OR_stdvert.cellout_calibType           ='Eflow'
+        MET_NNTight_EmScale_OR_stdvert.tau_calibType               ='ExclRefCalib'
+        MET_NNTight_EmScale_OR_stdvert.cryo_ApplyCorrection        = "Off"
+        MET_NNTight_EmScale_OR_stdvert.muon_algorithm              = "Staco"
+        MET_NNTight_EmScale_OR_stdvert.muon_isolationAlg           = "dRJet"
+        MET_NNTight_EmScale_OR_stdvert()
+        METcollections += [suffix]
+
+    if PhotonD3PDMakerFlags.AdditionalMETOutputLevel() > 3:
+        suffix='_NNTight_EmScale_newvert'
+        MET_NNTight_EmScale_newvert = make_METRefAlg(_suffix=suffix)
+        MET_NNTight_EmScale_newvert.photon_doPhotonTool              = True
+        MET_NNTight_EmScale_newvert.gamma_noCut                      = True
+        MET_NNTight_EmScale_newvert.gamma_EgammaInputCollectionKey   = "SelectedPhotonsNNTight"
+        MET_NNTight_EmScale_newvert.gamma_calibType                  = "EmScale"
+        MET_NNTight_EmScale_newvert.jet_JetInputCollectionKey   ='AntiKt4LCTopoJets'
+        MET_NNTight_EmScale_newvert.jet_JetPtCut                = 20.0*GeV
+        MET_NNTight_EmScale_newvert.jet_ApplyJetScale           = "Yes"
+        MET_NNTight_EmScale_newvert.jet_UseJetMomentForScale    = True
+        MET_NNTight_EmScale_newvert.jet_JetMomentForScale       = "LCJES"
+        MET_NNTight_EmScale_newvert.jet_ApplyJetJVF             = "Yes"
+        MET_NNTight_EmScale_newvert.jet_RunSoftJetsTool         = False
+        MET_NNTight_EmScale_newvert.jet_calibType               = 'ExclRefCalib'
+        MET_NNTight_EmScale_newvert.cellout_calibType           ='Eflow'
+        MET_NNTight_EmScale_newvert.tau_calibType               ='ExclRefCalib'
+        MET_NNTight_EmScale_newvert.cryo_ApplyCorrection        = "Off"
+        MET_NNTight_EmScale_newvert.muon_algorithm              = "Staco"
+        MET_NNTight_EmScale_newvert.muon_isolationAlg           = "dRJet"
+        MET_NNTight_EmScale_newvert.jet_UseCustomVxContainer    = True
+        MET_NNTight_EmScale_newvert.jet_vxcontainerkey          = "PAUDiphotonVertexCollection"
+        MET_NNTight_EmScale_newvert.cellout_vxcontainerkey      = "PAUDiphotonVertexCollection"    
+        MET_NNTight_EmScale_newvert()
+        METcollections += [suffix]
+
+    if PhotonD3PDMakerFlags.AdditionalMETOutputLevel() > 3:
+        suffix='_NNTight_Calib'
+        MET_NNTight_Calib = make_METRefAlg(_suffix=suffix)
+        MET_NNTight_Calib.photon_doPhotonTool              = True
+        MET_NNTight_Calib.gamma_noCut                      = True
+        MET_NNTight_Calib.gamma_EgammaInputCollectionKey   = "SelectedPhotonsNNTight"
+        MET_NNTight_Calib.gamma_calibType                  = "RefCalib"
+        MET_NNTight_Calib()
+        METcollections += [suffix]
+
+    if PhotonD3PDMakerFlags.AdditionalMETOutputLevel() > 3:
+        suffix='_NNTight_Calib_newvert'
+        MET_NNTight_Calib_newvert = make_METRefAlg(_suffix=suffix)
+        MET_NNTight_Calib_newvert.photon_doPhotonTool              = True
+        MET_NNTight_Calib_newvert.gamma_noCut                      = True
+        MET_NNTight_Calib_newvert.gamma_EgammaInputCollectionKey   = "SelectedPhotonsNNTight"
+        MET_NNTight_Calib_newvert.gamma_calibType                  = "RefCalib"
+        MET_NNTight_Calib_newvert.jet_JetInputCollectionKey   ='AntiKt4LCTopoJets'
+        MET_NNTight_Calib_newvert.jet_JetPtCut                = 20.0*GeV
+        MET_NNTight_Calib_newvert.jet_ApplyJetScale           = "Yes"
+        MET_NNTight_Calib_newvert.jet_UseJetMomentForScale    = True
+        MET_NNTight_Calib_newvert.jet_JetMomentForScale       = "LCJES"
+        MET_NNTight_Calib_newvert.jet_ApplyJetJVF             = "Yes"
+        MET_NNTight_Calib_newvert.jet_RunSoftJetsTool         = False
+        MET_NNTight_Calib_newvert.jet_calibType               = 'ExclRefCalib'
+        MET_NNTight_Calib_newvert.cellout_calibType           ='Eflow'
+        MET_NNTight_Calib_newvert.tau_calibType               ='ExclRefCalib'
+        MET_NNTight_Calib_newvert.cryo_ApplyCorrection        = "Off"
+        MET_NNTight_Calib_newvert.muon_algorithm              = "Staco"
+        MET_NNTight_Calib_newvert.muon_isolationAlg           = "dRJet"
+        MET_NNTight_Calib_newvert.jet_UseCustomVxContainer    = True
+        MET_NNTight_Calib_newvert.jet_vxcontainerkey          = "PAUDiphotonVertexCollection"
+        MET_NNTight_Calib_newvert.cellout_vxcontainerkey      = "PAUDiphotonVertexCollection"    
+        MET_NNTight_Calib_newvert()
+        METcollections += [suffix]
+
+    if PhotonD3PDMakerFlags.AdditionalMETOutputLevel() > 3:
+        suffix = '_NNTight_Calib_OR_newvert'
+        MET_NNTight_Calib_OR_newvert = make_METRefAlg(_suffix=suffix)
+        MET_NNTight_Calib_OR_newvert.photon_doPhotonTool              = True
+        MET_NNTight_Calib_OR_newvert.gamma_noCut                      = True
+        MET_NNTight_Calib_OR_newvert.gamma_EgammaInputCollectionKey   = "SelectedORPhotonsNNTight"
+        MET_NNTight_Calib_OR_newvert.gamma_EleInputCollectionKey      = "SelectedORElectronsNNTight"
+        MET_NNTight_Calib_OR_newvert.gamma_calibType                  = "RefCalib"
+        MET_NNTight_Calib_OR_newvert.ele_noCut                        = True
+        MET_NNTight_Calib_OR_newvert.ele_EgammaInputCollectionKey     = "SelectedORElectronsNNTight"
+        MET_NNTight_Calib_OR_newvert.ele_calibType                    = "RefCalib"
+        MET_NNTight_Calib_OR_newvert.jet_JetInputCollectionKey   ='AntiKt4LCTopoJets'
+        MET_NNTight_Calib_OR_newvert.jet_JetPtCut                = 20.0*GeV
+        MET_NNTight_Calib_OR_newvert.jet_ApplyJetScale           = "Yes"
+        MET_NNTight_Calib_OR_newvert.jet_UseJetMomentForScale    = True
+        MET_NNTight_Calib_OR_newvert.jet_JetMomentForScale       = "LCJES"
+        MET_NNTight_Calib_OR_newvert.jet_ApplyJetJVF             = "Yes"
+        MET_NNTight_Calib_OR_newvert.jet_RunSoftJetsTool         = False
+        MET_NNTight_Calib_OR_newvert.jet_calibType               = 'ExclRefCalib'
+        MET_NNTight_Calib_OR_newvert.cellout_calibType           ='Eflow'
+        MET_NNTight_Calib_OR_newvert.tau_calibType               ='ExclRefCalib'
+        MET_NNTight_Calib_OR_newvert.cryo_ApplyCorrection        = "Off"
+        MET_NNTight_Calib_OR_newvert.muon_algorithm              = "Staco"
+        MET_NNTight_Calib_OR_newvert.muon_isolationAlg           = "dRJet"
+        MET_NNTight_Calib_OR_newvert.jet_UseCustomVxContainer    = True
+        MET_NNTight_Calib_OR_newvert.jet_vxcontainerkey          = "PAUDiphotonVertexCollection"
+        MET_NNTight_Calib_OR_newvert.cellout_vxcontainerkey      = "PAUDiphotonVertexCollection"    
+        MET_NNTight_Calib_OR_newvert()
+        METcollections += [suffix]
+
+
+    return METcollections
+
+
+
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonPVD3PDObject.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonPVD3PDObject.py
new file mode 100644
index 0000000000000000000000000000000000000000..f9d5c80e06c7c7a2a49e9c7afe461667f4fb53ea
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonPVD3PDObject.py
@@ -0,0 +1,54 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+import PhotonD3PDMaker
+import TrackD3PDMaker
+import D3PDMakerCoreComps
+import EventCommonD3PDMaker
+from D3PDMakerCoreComps.D3PDObject import D3PDObject
+from D3PDMakerCoreComps.D3PDObject import make_SGDataVector_D3PDObject
+from D3PDMakerConfig.D3PDMakerFlags import D3PDMakerFlags
+from PhotonD3PDMaker import PhotonD3PDMakerConf
+from TrackD3PDMaker import TrackD3PDMakerConf
+from TrackD3PDMaker.TrackD3PDMakerFlags import *
+from RecExConfig.RecFlags import rec
+
+def DefineVertexD3PDObject(object,
+                           trackTarget='trk',
+                           trackPrefix='trk_',
+                           trackType='Rec::TrackParticleContainer',
+                           flags=TrackD3PDFlags):
+
+    if trackType=='Rec::TrackParticleContainer':
+        vxTrackAtVertexTrackAssociationTool = TrackD3PDMaker.VxTrackAtVertexTrackParticleAssociationTool
+    if trackType=='TrackCollection':
+        vxTrackAtVertexTrackAssociationTool = TrackD3PDMaker.VxTrackAtVertexTrkTrackAssociationTool
+
+    # Kine
+    object.defineBlock (0, 'Kine', PhotonD3PDMaker.PhotonPVFillerTool)
+
+
+def BuildVertexD3PDObject(_prefix='vx_',
+                     _label='vx',
+                     _sgkey=D3PDMakerFlags.VertexSGKey(),
+                     trackTarget='trk',
+                     trackPrefix='trk_',
+                     trackType='Rec::TrackParticleContainer'):
+
+    object = make_SGDataVector_D3PDObject ('VxContainer',
+                                           _sgkey,
+                                           _prefix,
+                                           default_allowMissing = True)
+                                           
+    DefineVertexD3PDObject(object,
+                           trackTarget,
+                           trackPrefix,
+                           trackType)
+
+    return object
+
+PVD3PDObject = BuildVertexD3PDObject(_prefix='vx_',
+                                     _label='vx',
+                                     _sgkey='VxPrimaryCandidate',
+                                     trackTarget='trk',
+                                     trackPrefix='trk_',
+                                     trackType='Rec::TrackParticleContainer')
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonRecoveryAssociation.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonRecoveryAssociation.py
new file mode 100644
index 0000000000000000000000000000000000000000..68e5b2df1c1da3d4de78293e090f98622f8a9af9
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonRecoveryAssociation.py
@@ -0,0 +1,3 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+from egammaD3PDMaker.PhotonRecoveryAssociation import PhotonRecoveryAssociation
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonTrackD3PDObject.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonTrackD3PDObject.py
new file mode 100644
index 0000000000000000000000000000000000000000..74567a5c9d8d1273aff33dc04b3a9533c33ddf67
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonTrackD3PDObject.py
@@ -0,0 +1,43 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+import TrackD3PDMaker
+import PhotonD3PDMaker
+import D3PDMakerCoreComps
+import EventCommonD3PDMaker
+import TruthD3PDMaker
+from D3PDMakerCoreComps.D3PDObject import D3PDObject
+from D3PDMakerCoreComps.D3PDObject import make_SGDataVector_D3PDObject
+from D3PDMakerConfig.D3PDMakerFlags import D3PDMakerFlags
+from AthenaCommon.AppMgr import ToolSvc
+
+def PhotonTrackD3PDObject(_label='trkPhotonTrack',
+                          _prefix='trkPhotonTrack_',
+                          _sgkey='Tracks',
+                          _object_name='PhotonTrackD3PDObject',
+                          typeName='TrackCollection'):
+    
+    object = make_SGDataVector_D3PDObject (typeName,
+                                           _sgkey,
+                                           _prefix,
+                                           _object_name,
+                                           default_allowMissing = True,
+                                           default_label = _label,
+                                           allow_args = ['GenParticleTarget',
+                                                         'TruthParticleTarget',
+                                                         'StoreTruthInfo'])
+        
+    if typeName=='Rec::TrackParticleContainer':
+        ParametersAtBLFillerTool     = PhotonD3PDMaker.TrackParticleParametersAtDiPhotonVertex
+
+    object.defineBlock(0, _prefix+"ParametersAtBL",
+                       ParametersAtBLFillerTool)
+
+    return object
+
+
+
+PhotonTrackParticleD3PDObject = PhotonTrackD3PDObject(_label='trkPho',
+                                                      _prefix='trkPho_',
+                                                      _sgkey=D3PDMakerFlags.TrackSGKey(),
+                                                      _object_name='PhotonTrackParticleD3PDObject',
+                                                      typeName='Rec::TrackParticleContainer')
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonTruthParticleConfig.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonTruthParticleConfig.py
new file mode 100644
index 0000000000000000000000000000000000000000..76c29317fbeded06383d6f61eabdac667441204e
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonTruthParticleConfig.py
@@ -0,0 +1,77 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+# $Id$
+#
+# @file PhotonD3PDMaker/python/PhotonTruthParticleConfig.py
+# @author Mike Hance <hance@hep.upenn.edu>
+# @date August 2010
+# @brief Configure algorithms to build filtered PhotonTruthParticleContainer
+#        to write to D3PD.
+#
+
+
+import PhotonD3PDMaker
+import TruthD3PDAnalysis
+from D3PDMakerConfig.D3PDMakerFlags           import D3PDMakerFlags
+from PhotonD3PDMaker.PhotonD3PDMakerFlags     import PhotonD3PDMakerFlags
+from McParticleAlgs.JobOptCfg                 import createMcAodBuilder
+from RecExConfig.RecFlags                     import rec
+from AthenaCommon.AlgSequence                 import AlgSequence
+from RecExConfig.ObjKeyStore                  import cfgKeyStore
+from AthenaCommon                             import CfgMgr
+
+
+def PhotonTruthParticleConfig (seq = AlgSequence(D3PDMakerFlags.PreD3PDAlgSeqName()),
+                               sgkey = D3PDMakerFlags.TruthParticlesSGKey(),
+                               prefix = ''):
+    
+    if not rec.doTruth():
+        return
+
+    # Is the container already in SG?
+    if cfgKeyStore.isInInput ('TruthParticleContainer', sgkey):
+        return
+
+    algname = prefix + sgkey + 'Builder'
+    if hasattr (seq, algname):
+        return
+
+    filtname = prefix + sgkey + 'Filter'
+
+    if PhotonD3PDMakerFlags.SaveAllTruthParticles():
+
+      seq += createMcAodBuilder\
+             (algname,
+              inMcEvtCollection = D3PDMakerFlags.TruthSGKey(),
+              outMcEvtCollection = sgkey + '_GEN_D3PD',
+              outTruthParticles = sgkey,
+              filterTool = TruthD3PDAnalysis.TruthParticleFilterTool
+                                                 (filtname,
+                                                  DoPileup     = D3PDMakerFlags.TruthDoPileup(),
+                                                  WritePartons = D3PDMakerFlags.TruthWritePartons(),
+                                                  WriteHadrons = D3PDMakerFlags.TruthWriteHadrons(),
+                                                  WriteGeant   = D3PDMakerFlags.TruthWriteGeant(),
+                                                  GeantPhotonPtThresh = D3PDMakerFlags.TruthGeantPhotonPtThresh(),
+                                                 ),
+              cnvTool = CfgMgr.TruthParticleCnvTool('D3PDTruthParticleCnvTool'),
+              )
+
+    else:
+      seq += createMcAodBuilder\
+             (algname,
+              inMcEvtCollection = D3PDMakerFlags.TruthSGKey(),
+              outMcEvtCollection = sgkey + '_GEN_D3PD',
+              outTruthParticles = sgkey,
+              filterTool = PhotonD3PDMaker.PhotonTruthParticleFilterTool
+                                               (filtname,
+                                                DoPileup     = D3PDMakerFlags.TruthDoPileup(),
+                                                WritePartons = D3PDMakerFlags.TruthWritePartons(),
+                                                WriteHadrons = D3PDMakerFlags.TruthWriteHadrons(),
+                                                WriteGeant   = D3PDMakerFlags.TruthWriteGeant(),
+                                                ParticleFilters = PhotonD3PDMakerFlags.TruthParticleFilters()),
+              cnvTool = CfgMgr.TruthParticleCnvTool('D3PDTruthParticleCnvTool'),
+              )
+
+    
+    cfgKeyStore.addTransient ('TruthParticleContainer', sgkey)
+    return
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonTruthParticleD3PDObject.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonTruthParticleD3PDObject.py
new file mode 100644
index 0000000000000000000000000000000000000000..e97ab6d05f46bcab4537a5b33b34e5d158348e02
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/PhotonTruthParticleD3PDObject.py
@@ -0,0 +1,89 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+# $Id $
+#
+# @file PhotonD3PDMaker/python/PhotonTruthParticleD3PDObject.py
+# @author Mike Hance <mike.hance@cern.ch>
+# @date August 2010
+# @brief Define D3PD object for a collection of TruthParticle's, for photon analyses...  based on EventCommonD3PDMaker tools
+#
+
+
+import EventCommonD3PDMaker
+from PhotonD3PDMaker.PhotonD3PDMakerFlags                   import PhotonD3PDMakerFlags
+from PhotonD3PDMaker.PhotonTruthParticleConfig              import PhotonTruthParticleConfig
+from PhotonD3PDMaker.PAUTruthPhotonAssociation              import PAUTruthPhotonAssociation
+from D3PDMakerCoreComps.D3PDObject                          import make_SGDataVector_D3PDObject
+from D3PDMakerCoreComps.SimpleAssociation                   import SimpleAssociation
+from D3PDMakerConfig.D3PDMakerFlags                         import D3PDMakerFlags
+from AthenaCommon.AlgSequence                               import AlgSequence
+from TruthD3PDMaker.TruthParticleChildAssociation           import TruthParticleChildAssociation
+from TruthD3PDMaker.TruthParticleParentAssociation          import TruthParticleParentAssociation
+import PhotonD3PDMaker
+import TruthD3PDMaker
+from AthenaCommon.AppMgr import ToolSvc
+from PhotonAnalysisUtils.PhotonAnalysisUtilsFlags           import PAUflags
+preseq = AlgSequence (D3PDMakerFlags.PreD3PDAlgSeqName())
+from AthenaCommon.Constants import WARNING, INFO, ERROR, VERBOSE
+import D3PDMakerCoreComps
+DVGetter = D3PDMakerCoreComps.SGDataVectorGetterTool
+
+PhotonTruthParticleD3PDObject = make_SGDataVector_D3PDObject \
+                                ('TruthParticleContainer',
+                                 D3PDMakerFlags.TruthParticlesSGKey(),
+                                 'mc_',
+                                 'PhotonTruthParticleD3PDObject')
+
+def _PhotonTruthParticleAlgHook (c, prefix, sgkey,
+                                 seq = AlgSequence(D3PDMakerFlags.PreD3PDAlgSeqName()),
+                                 *args, **kw):
+    
+    PhotonTruthParticleConfig (seq = seq, prefix = prefix, sgkey = sgkey)
+    return
+
+PhotonTruthParticleD3PDObject.defineHook (_PhotonTruthParticleAlgHook)
+
+
+PhotonTruthParticleD3PDObject.defineBlock (0, 'TruthKin',
+                                           EventCommonD3PDMaker.FourMomFillerTool)
+
+PhotonTruthParticleD3PDObject.defineBlock (0, 'TruthInfo',
+                                           TruthD3PDMaker.TruthParticleFillerTool)
+
+ProdVertexAssoc = SimpleAssociation \
+                  (PhotonTruthParticleD3PDObject,
+                   TruthD3PDMaker.TruthParticleProdVertexAssociationTool,
+                   level = 1,
+                   prefix = 'vx_',
+                   blockname = 'ProdVert')
+ProdVertexAssoc.defineBlock (1, 'ProdVertPos',
+                             EventCommonD3PDMaker.GenVertexFillerTool)
+
+
+ChildAssoc = TruthParticleChildAssociation(
+    parent = PhotonTruthParticleD3PDObject,
+    prefix = 'child_',
+    # target = '', # filled by hook
+    level = 0 )
+
+def _TruthParticleChildAssocHook (c, prefix, *args, **kw):
+    assoc = getattr(c, c.name() + '_child_TruthParticleChildAssociation', None)
+    if assoc:
+        indexer = getattr(assoc, assoc.name() + 'Index')
+        indexer.Target = prefix
+        return
+PhotonTruthParticleD3PDObject.defineHook(_TruthParticleChildAssocHook)
+    
+ParentAssoc = TruthParticleParentAssociation(
+    parent = PhotonTruthParticleD3PDObject,
+    prefix = 'parent_',
+    # target = '', # filled by hook
+    level = 0 )
+
+def _TruthParticleParentAssocHook (c, prefix, *args, **kw):
+    assoc = getattr(c, c.name() + '_parent_TruthParticleParentAssociation', None)
+    if assoc:
+        indexer = getattr(assoc, assoc.name() + 'Index')
+        indexer.Target = prefix
+    return
+PhotonTruthParticleD3PDObject.defineHook(_TruthParticleParentAssocHook)
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/__init__.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..9d0bf0aae66d8dc20530f522bee8d4fe4674427a
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/__init__.py
@@ -0,0 +1,6 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+import PhotonD3PDMakerConf
+for k, v in PhotonD3PDMakerConf.__dict__.items():
+    if k.startswith ('D3PD__'):
+        globals()[k[6:]] = v
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/makeSorterAlg.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/makeSorterAlg.py
new file mode 100644
index 0000000000000000000000000000000000000000..9893f0f336466c4dbf75d11f8d3fb0af87bffd90
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/python/makeSorterAlg.py
@@ -0,0 +1,47 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+import D3PDMakerCoreComps
+import PhotonD3PDMaker
+
+def makeElectronSorterAlg( InputCollection,
+                           CollectionType,
+                           OutputCollectionName) :
+
+    newGetter = D3PDMakerCoreComps.SGDataVectorGetterTool(CollectionType+'_sorted',
+                                                          TypeName = CollectionType,
+                                                          SGKey = InputCollection);
+    
+    sorter = PhotonD3PDMaker.ElectronSorterAlg()
+    sorter.Getter               = newGetter
+    sorter.OutputKey            = OutputCollectionName
+
+    return sorter
+
+def makePhotonSorterAlg( InputCollection,
+                         CollectionType,
+                         OutputCollectionName) :
+
+    newGetter = D3PDMakerCoreComps.SGDataVectorGetterTool(CollectionType+'_sorted',
+                                                          TypeName = CollectionType,
+                                                          SGKey = InputCollection);
+    
+    sorter                      = PhotonD3PDMaker.PhotonSorterAlg()
+    sorter.Getter               = newGetter
+    sorter.OutputKey            = OutputCollectionName
+
+    return sorter
+
+def makeTruthParticleSorterAlg( InputCollection,
+                                CollectionType,
+                                OutputCollectionName) :
+
+    newGetter = D3PDMakerCoreComps.SGDataVectorGetterTool(CollectionType+'_sorted',
+                                                          TypeName = CollectionType,
+                                                          SGKey = InputCollection);
+    
+    sorter                      = PhotonD3PDMaker.TruthParticleSorterAlg()
+    sorter.Getter               = newGetter
+    sorter.OutputKey            = OutputCollectionName
+
+    return sorter
+
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/share/PhotonD3PDMaker_topOptions.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/share/PhotonD3PDMaker_topOptions.py
new file mode 100644
index 0000000000000000000000000000000000000000..505847c772ec8358e5e4f5720c727967c2bb43b4
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/share/PhotonD3PDMaker_topOptions.py
@@ -0,0 +1,71 @@
+# $Id $
+#
+# @file PhotonD3PDMaker/share/PhotonD3PDMaker_topOptions.py
+# @author Mike Hance <mike.hance@cern.ch>
+# @date Aug, 2010
+# @brief Example for building a photon D3PD from an AOD, based on other D3PDMaker tools
+#
+
+###################################################################
+# Define the input file here.
+#
+
+from AthenaCommon.AthenaCommonFlags import athenaCommonFlags
+athenaCommonFlags.FilesInput= ["AOD.pool.root"]
+
+athenaCommonFlags.EvtMax =100 
+
+###################################################################
+# Define the output file here.
+#
+
+if not globals().get('tupleFileOutput'):
+    tupleFileOutput = 'test.NTUP_PHOTON.root'
+
+from D3PDMakerConfig.D3PDProdFlags import prodFlags
+prodFlags.WritePhotonD3PD = True
+prodFlags.WritePhotonD3PD.FileName = tupleFileOutput
+prodFlags.WritePhotonD3PD.lock()
+
+
+###################################################################
+# Some options to increase the output
+#
+
+# These are some examples of how to set some options.
+# All of these specific choices are already set in PhotonD3PD.py, so
+# don't bother to re-set them here.
+#
+# Note: options set in this file will only get picked up if running
+# athena directly on this file - standard Reco_trf jobs will NOT
+# see any options set here!  To have your options propagated into
+# official production jobs, set the options in PhotonD3PD.py
+# or in PhotonD3PD_prodJobOFragment.py.
+#
+from PhotonD3PDMaker.PhotonD3PDMakerFlags import PhotonD3PDMakerFlags
+PhotonD3PDMakerFlags.AdditionalMETOutputLevel .set_Value_and_Lock(0)
+PhotonD3PDMakerFlags.DumpAllTracks            .set_Value_and_Lock(False)
+PhotonD3PDMakerFlags.FilterTracksForMET       .set_Value_and_Lock(False)
+PhotonD3PDMakerFlags.FillFullMET              .set_Value_and_Lock(False)
+PhotonD3PDMakerFlags.JetCollections           =['AntiKt4TopoEMJets','AntiKt4LCTopoJets']
+PhotonD3PDMakerFlags.JetCollections           .lock()
+# PhotonD3PDMakerFlags.DumpNearbyTracks     .set_Value_and_Lock(True )
+# PhotonD3PDMakerFlags.DumpAllTracks        .set_Value_and_Lock(True ) # if you want all the tracks!
+# PhotonD3PDMakerFlags.DumpLotsOfTriggerInfo.set_Value_and_Lock(False)
+    
+###################################################################
+# Make the D3PD.
+#
+
+from RecExConfig.RecFlags import rec
+rec.DPDMakerScripts.append("PhotonD3PDMaker/PhotonD3PD_prodJobOFragment.py")
+rec.doCBNT.set_Value_and_Lock(False)
+rec.doWriteESD.set_Value_and_Lock(False)
+rec.doWriteAOD.set_Value_and_Lock(False)
+rec.doAOD.set_Value_and_Lock(False)
+rec.doESD.set_Value_and_Lock(False)
+rec.doWriteTAG.set_Value_and_Lock(False)
+rec.doForwardDet.set_Value_and_Lock(False)
+include ("RecExCommon/RecExCommon_topOptions.py")
+
+
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/share/PhotonD3PDMaker_transform.sh b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/share/PhotonD3PDMaker_transform.sh
new file mode 100755
index 0000000000000000000000000000000000000000..4b924e43127e0ec1bb6b69ddc25bddaa2c31b2f2
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/share/PhotonD3PDMaker_transform.sh
@@ -0,0 +1,38 @@
+# $Id $
+
+maxevents=100
+# scratch2/mhance/data/mc12_8TeV.160008.PowhegPythia8_AU2CT10_ggH120_gamgam.merge.AOD.e1189_s1469_s1470_r3542_r3549_tid781414_00/AOD.781414._000035.pool.root.1
+inputfile="AOD.pool.root"
+
+preExecString="preExec=from@RecExConfig.RecFlags@import@rec"
+
+doZgamma=0
+if [[ $doZgamma != 0 ]]; then
+    preExecString="${preExecString},,from@PhotonD3PDMaker.PhotonD3PDMakerFlags@import@PhotonD3PDMakerFlags,,PhotonD3PDMakerFlags.AdditionalMETOutputLevel=1,,PhotonD3PDMakerFlags.DumpAllTracks=False,,PhotonD3PDMakerFlags.FilterTracksForMET=False,,PhotonD3PDMakerFlags.FillFullMET=False,,PhotonD3PDMakerFlags.FillR0p6Jets=False"
+fi
+
+doFPECheck=0
+if [[ $doFPECheck != 0 ]]; then
+    preExecString="${preExecString},,rec.doFloatingPointException.set_Value_and_Lock(True)"
+fi
+
+
+# run each test in its own subdirectory
+let dir=000
+mkdir ${dir}
+while [[ $? != 0 ]]; do
+    let dir=$(($dir+1))
+    mkdir ${dir}
+done
+
+pushd $dir
+
+Reco_trf.py \
+    inputAODFile=${inputfile} \
+    outputNTUP_PHOTONFile=test.NTUP_PHOTON.root \
+    autoConfiguration=everything \
+    ${preExecString} \
+    maxEvents=${maxevents} | tee test.NTUP_PHOTON.log 2>&1
+
+popd
+
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/share/PhotonD3PD_prodJobOFragment.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/share/PhotonD3PD_prodJobOFragment.py
new file mode 100644
index 0000000000000000000000000000000000000000..e58745a27d0be33235ddd8d0c25c71935cf9c87d
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/share/PhotonD3PD_prodJobOFragment.py
@@ -0,0 +1,212 @@
+# $Id: $
+#
+# This jobO fragment is meant to be called by Reco_trf.py in transformation jobs to
+# create the "Photon D3PD cart".
+
+# This jobO should not be included more than once:
+include.block( "PhotonD3PDMaker/PhotonD3PD_prodJobOFragment.py" )
+
+#-------------------------------------------------------------------------------------
+# Some configuration options:
+#
+# Some options to increase the output
+#
+from PhotonD3PDMaker.PhotonD3PDMakerFlags import PhotonD3PDMakerFlags
+
+PhotonD3PDMakerFlags.JetCollections = ['AntiKt4TopoEMJets','AntiKt4LCTopoJets']
+if PhotonD3PDMakerFlags.FillR0p6Jets():
+    PhotonD3PDMakerFlags.JetCollections += ['AntiKt6TopoEMJets','AntiKt6LCTopoJets']
+
+PhotonD3PDMakerFlags.EnableBTagging        = True
+
+PhotonD3PDMakerFlags.DumpNearbyTracks      = True
+PhotonD3PDMakerFlags.DumpLotsOfTriggerInfo = True
+
+PhotonD3PDMakerFlags.Fill_Etcone_ED_corrected = [15,20,25,30,35,40]
+PhotonD3PDMakerFlags.Fill_Etcone_corrected = [15,20,25,30,35,40]
+PhotonD3PDMakerFlags.Fill_ED_info = True
+
+PhotonD3PDMakerFlags.FillMV3 = False
+PhotonD3PDMakerFlags.FillJetFitterCharm = True
+
+from D3PDMakerConfig.D3PDMakerFlags import D3PDMakerFlags
+D3PDMakerFlags.MakeEgammaUserData.set_Value_and_Lock(True)
+
+# Some options to reduce the output
+#
+from TrackD3PDMaker.TrackD3PDMakerFlags import TrackD3PDFlags
+TrackD3PDFlags.storeTrackInfo                               .set_Value_and_Lock(False)
+TrackD3PDFlags.trackParametersAtPrimaryVertexLevelOfDetails .set_Value_and_Lock(1)
+TrackD3PDFlags.trackParametersAtBeamSpotLevelOfDetails      .set_Value_and_Lock(1)
+TrackD3PDFlags.storeTrackPredictionAtBLayer                 .set_Value_and_Lock(True)
+TrackD3PDFlags.vertexPositionLevelOfDetails                 .set_Value_and_Lock(1)
+TrackD3PDFlags.storeVertexKinematics                        .set_Value_and_Lock(True)
+TrackD3PDFlags.storeVertexTrackIndexAssociation             .set_Value_and_Lock(True)
+TrackD3PDFlags.storeVertexPurity                            .set_Value_and_Lock(False)
+TrackD3PDFlags.storeVertexFitQuality                        .set_Value_and_Lock(False)
+TrackD3PDFlags.storeVertexAssociation                       .set_Value_and_Lock(True)
+TrackD3PDFlags.storeTrackUnbiasedIPAtPV                     .set_Value_and_Lock(True)
+TrackD3PDFlags.trackParametersAtGlobalPerigeeLevelOfDetails .set_Value_and_Lock(1)
+
+# This will fill some very large branches of the track parameters for all tracks associated with each PV
+TrackD3PDFlags.storeVertexTrackAssociation                  .set_Value_and_Lock(False)
+
+# Not sure why the D3PDMaker can't figure this out.
+if rec.readESD():
+    CellsSGKey = D3PDMakerFlags.CellsSGKey()
+else:
+    CellsSGKey = "AODCellContainer"
+
+# Can almost certainly be removed later, but needed now for b-tagging warnings
+#from BTagging.BTaggingFlags import BTaggingFlags
+#BTaggingFlags.CalibrationTag = "BTagCalibALL-07-02"
+#-------------------------------------------------------------------------------------
+
+
+#-------------------------------------------------------------------------------------
+# Some algorithms that should run before the main algsequence
+#
+# configure MuonScatteringAngleSignificanceTool...
+include("JetTagD3PDMaker/MuonScatteringSigToolConfig.py")
+
+# next, let's sort some of the containers by E_T
+preseq = AlgSequence(D3PDMakerFlags.PreD3PDAlgSeqName())
+
+from PhotonD3PDMaker.makeSorterAlg import makeElectronSorterAlg,makePhotonSorterAlg
+
+photonsorter = makePhotonSorterAlg  (D3PDMakerFlags.PhotonSGKey()  , 'PhotonContainer'  , 'SortedPhotons')
+photonsorter.RemoveTopoClusterCandidates = PhotonD3PDMakerFlags.RemoveTopoClusterCandidates()
+preseq += photonsorter
+D3PDMakerFlags.PhotonSGKey = 'SortedPhotons,'+D3PDMakerFlags.PhotonSGKey()
+
+preseq += makeElectronSorterAlg(D3PDMakerFlags.ElectronSGKey(), 'ElectronContainer', 'SortedElectrons')
+D3PDMakerFlags.ElectronSGKey = 'SortedElectrons,'+D3PDMakerFlags.ElectronSGKey()
+
+# Diphoton algorithm
+from D3PDMakerConfig.D3PDMakerFlags import D3PDMakerFlags
+from PhotonAnalysisUtils.PhotonAnalysisUtilsFlags import PAUflags
+PAUflags.PhotonContainer = D3PDMakerFlags.PhotonSGKey()
+from AthenaCommon.AlgSequence import AlgSequence
+PAUflags.AlgSequence = AlgSequence().getName()
+from PhotonAnalysisUtils.DiphotonAnalysisGetter import DiphotonAnalysisGetter
+dip = DiphotonAnalysisGetter()
+
+# Add some custom MET collections
+from PhotonD3PDMaker.PhotonMET import addPhotonMET
+customMETCollections = addPhotonMET()
+
+# Cell filter
+from PhotonD3PDMaker.AddCellFilter import AddCellFilter
+AddCellFilter(PhotonD3PDMakerFlags.SelectedCellsContainerName(), preseq)
+#-------------------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------------------
+# A special block just for jet configuration....
+if rec.doTruth():
+    PhotonD3PDMakerFlags.alltruthjets = ['AntiKt4TruthJets', 'AntiKt4TruthWithMuNoIntJets']
+    if PhotonD3PDMakerFlags.FillR0p6Jets():
+        PhotonD3PDMakerFlags.alltruthjets += ['AntiKt6TruthJets', 'AntiKt6TruthWithMuNoIntJets']
+
+# this needs to come here to get the truth-jet flavor-tagging correct
+from PhotonD3PDMaker.ConfigureTaggingOptions import ConfigureTaggingOptions
+if PhotonD3PDMakerFlags.EnableBTagging():
+    ConfigureTaggingOptions(PhotonD3PDMakerFlags.alltruthjets(),
+                            PhotonD3PDMakerFlags.FillMV3(),
+                            PhotonD3PDMakerFlags.FillJetFitterCharm())
+
+# Create some new truth-jet collections
+#
+from JetRec.JetRecFlags import jetFlags
+jetFlags.doBTagging = False
+if rec.doTruth():
+    
+    from JetRec.JetGetters import make_StandardJetGetter
+    antikt4truthAlg = make_StandardJetGetter('AntiKt',
+                                             0.4,
+                                             'Truth',
+                                             globalSuff='WithMuNoInt',
+                                             disable=False,
+                                             includeMuons=True,
+                                             useInteractingOnly=False,
+                                             seq = preseq).jetAlgorithmHandle()
+    
+    if PhotonD3PDMakerFlags.FillR0p6Jets():
+        antikt6truthAlg = make_StandardJetGetter('AntiKt',
+                                                 0.6,
+                                                 'Truth',
+                                                 disable=False,
+                                                 seq = preseq).jetAlgorithmHandle() 
+        
+        antikt6truthAlg = make_StandardJetGetter('AntiKt',
+                                                 0.6,
+                                                 'Truth',
+                                                 globalSuff='WithMuNoInt',
+                                                 disable=False,
+                                                 includeMuons=True,
+                                                 useInteractingOnly=False,
+                                                 seq = preseq).jetAlgorithmHandle()
+
+    if PhotonD3PDMakerFlags.RetagTruthBJets() and PhotonD3PDMakerFlags.EnableBTagging():
+        if not 'JetTagD3PD_CollectionPostfix' in dir():
+            PhotonD3PDMakerFlags.JetTagD3PD_CollectionPostfix=PhotonD3PDMakerFlags.BTaggingSuffix()
+    elif not 'JetTagD3PD_CollectionPostfix' in dir():
+        PhotonD3PDMakerFlags.JetTagD3PD_CollectionPostfix=""
+
+if PhotonD3PDMakerFlags.EnableBTagging():
+    # now we can load the b-tagging algorithms
+    jetFlags.doBTagging = True
+    
+    include( "BTagging/BTagging_jobOptions.py" )
+
+    # however, the algorithms are added to the topSequence, which is useless for us,
+    # since we need to have the information available for an already-defined algorithm.
+    # so, take them out of the topSequence, and add them to the presequence.
+    from AthenaCommon.AlgSequence import AlgSequence
+    topSequence = AlgSequence()
+    for algitr in topSequence:
+        if algitr.getName().find("BJetBuilder") >= 0:
+            preseq += algitr
+            topSequence.remove(algitr)
+
+if PhotonD3PDMakerFlags.ReCalculateJetMoments() or PhotonD3PDMakerFlags.FillFullJVF():
+    # this just gets the JVF tool so we can reconfigure it
+    from JetMomentTools.SetupJetMomentTools  import getJetVertexAssociationTool
+    jvatool = getJetVertexAssociationTool('AntiKt', 0.4, 'Topo') # apparently the parameters here don't matter
+    
+    # this will change _jvtxf, _jvtxfFull
+    jvatool.AssociateToHighestJVF = False
+    jvatool.JetVtxTrackHelper.UniqueTrkVtxAssocBySumPt = False
+#-------------------------------------------------------------------------------------
+
+
+#-------------------------------------------------------------------------------------
+# Construct the stream and file names for the Photon D3PD:
+# Common import(s):
+from AthenaCommon.JobProperties import jobproperties
+prodFlags = jobproperties.D3PDProdFlags
+from PrimaryDPDMaker.PrimaryDPDHelpers import buildFileName
+
+# Set up a logger:
+from AthenaCommon.Logging import logging
+PhotonD3PDStream_msg = logging.getLogger( 'PhotonD3PD_prodJobOFragment' )
+
+# Check if the configuration makes sense:
+if prodFlags.WritePhotonD3PD.isVirtual:
+    PhotonD3PDStream_msg.error( "The Photon D3PD stream can't be virtual! " +
+                                "It's a configuration error!" )
+    raise NameError( "Photon D3PD set to be a virtual stream" )
+    pass
+
+streamName = prodFlags.WritePhotonD3PD.StreamName
+fileName   = buildFileName( prodFlags.WritePhotonD3PD )
+PhotonD3PDStream_msg.info( "Configuring PhotonD3PD with streamName '%s' and fileName '%s'" % \
+                           ( streamName, fileName ) )
+# Create the D3PD streams:
+from OutputStreamAthenaPool.MultipleStreamManager import MSMgr
+PhotonD3PDStream = MSMgr.NewRootStream( streamName, fileName, "photon" )
+
+# Now add all the content to this stream:
+from PhotonD3PDMaker.PhotonD3PD import PhotonD3PD
+PhotonD3PD( PhotonD3PDStream,
+            CustomMETCollections = customMETCollections)
+#-------------------------------------------------------------------------------------
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/share/PhotonPIDTool_jobOptions.py b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/share/PhotonPIDTool_jobOptions.py
new file mode 100644
index 0000000000000000000000000000000000000000..5034e7961a5981cb325cea912c055f3440984e32
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/share/PhotonPIDTool_jobOptions.py
@@ -0,0 +1,109 @@
+if not 'PhotonRecovery_egDetail_output'    in dir():
+    PhotonRecovery_egDetail_output    = "egDetailAODReco"
+
+# Set up the cut based photon ID tool
+from egammaPIDTools.egammaPhotonCutIDToolBase import egammaPhotonCutIDToolBase
+thephotoncutidtool = egammaPhotonCutIDToolBase("thephotoncutidtool")
+thephotoncutidtool.EMShowerContainerName = PhotonRecovery_egDetail_output
+thephotoncutidtool.EMConversionContainerName = PhotonRecovery_egDetail_output
+ToolSvc += thephotoncutidtool
+print      thephotoncutidtool
+
+# egammaElectronCutIDTool
+from egammaPIDTools.egammaElectronCutIDToolBase import egammaElectronCutIDToolBase
+therecoelectroncutid=egammaElectronCutIDToolBase("therecoelectroncutid")
+ToolSvc+=therecoelectroncutid
+print    therecoelectroncutid
+
+# egammaSoftElectronCutIDTool
+from egammaPIDTools.egammaSoftElectronCutIDToolBase import egammaSoftElectronCutIDToolBase
+therecosoftelectroncutid=egammaSoftElectronCutIDToolBase("therecosoftelectroncutid")            
+ToolSvc+=therecosoftelectroncutid
+print    therecosoftelectroncutid
+
+# EPi tool
+from egammaPIDTools.egammaEPiVariablesToolBase import egammaEPiVariablesToolBase
+therecoepivariables = egammaEPiVariablesToolBase("therecoepivariables")
+therecoepivariables.EMShowerContainerName = PhotonRecovery_egDetail_output
+therecoepivariables.EMTrackMatchContainerName= PhotonRecovery_egDetail_output
+ToolSvc += therecoepivariables
+print      therecoepivariables
+
+from egammaPIDTools.egammaIsolationMVATopToolBase import egammaIsolationMVATopToolBase
+theIsolationMVATopTool=egammaIsolationMVATopToolBase("theIsolationMVATopTool")
+theIsolationMVATopTool.EMShowerContainerName = PhotonRecovery_egDetail_output
+ToolSvc += theIsolationMVATopTool
+print      theIsolationMVATopTool
+
+# LogLikelihood
+from egammaPIDTools.egammaEPiLogLikelihoodToolBase import egammaEPiLogLikelihoodToolBase
+therecologlikelihood = egammaEPiLogLikelihoodToolBase("recologlikelihood")
+therecologlikelihood.egammaEPiVariablesToolName = therecoepivariables.getFullName()
+ToolSvc += therecologlikelihood
+print      therecologlikelihood
+
+# NeuralNetwork
+from egammaPIDTools.egammaEPiNeuralNetworkToolBase import egammaEPiNeuralNetworkToolBase
+thereconeuralnetwork = egammaEPiNeuralNetworkToolBase("recoNeuralNetwork")
+thereconeuralnetwork.egammaEPiVariablesToolName = therecoepivariables.getFullName()
+ToolSvc += thereconeuralnetwork
+print      thereconeuralnetwork
+    
+# LogLikelihoodToolSE
+from egammaPIDTools.egammaEPiLogLikelihoodSEToolBase import egammaEPiLogLikelihoodSEToolBase
+therecologlikelihoodse = egammaEPiLogLikelihoodSEToolBase("recoLogLikelihoodSE")
+therecologlikelihoodse.EMShowerContainerName = PhotonRecovery_egDetail_output
+therecologlikelihoodse.EMTrackMatchContainerName = PhotonRecovery_egDetail_output
+ToolSvc += therecologlikelihoodse
+print      therecologlikelihoodse
+
+# Hmatrix
+from egammaPIDTools.egammaHmatrixToolBase import egammaHmatrixToolBase
+therecohmatrix=egammaHmatrixToolBase("recoHmatrix")
+therecohmatrix.EMShowerContainerName = PhotonRecovery_egDetail_output
+ToolSvc += therecohmatrix
+print      therecohmatrix
+        
+# Boosted decision tree
+from egammaPIDTools.egammaEPiBoostedDecisionTreeToolBase import egammaEPiBoostedDecisionTreeToolBase
+therecoEPiBoostedDecisionTreeTool=egammaEPiBoostedDecisionTreeToolBase("recoEPiBoostedDecisionTreeTool")
+therecoEPiBoostedDecisionTreeTool.egammaEPiVariablesToolName=therecoepivariables.getFullName()
+ToolSvc += therecoEPiBoostedDecisionTreeTool
+print      therecoEPiBoostedDecisionTreeTool
+    
+# Fisher tool
+from egammaPIDTools.egammaEPiFisherToolBase import egammaEPiFisherToolBase
+therecoEPiFisherTool=egammaEPiFisherToolBase("recoEPiFisherTool")
+therecoEPiFisherTool.egammaEPiVariablesToolName=therecoepivariables.getFullName()
+ToolSvc += therecoEPiFisherTool
+print      therecoEPiFisherTool
+
+# Gamma Loglikelihood
+from egammaPIDTools.egammaGammaLogLikelihoodToolBase import egammaGammaLogLikelihoodToolBase
+therecoGammaLogLikelihoodTool= egammaGammaLogLikelihoodToolBase("recoGammaLogLikelihood")
+therecoGammaLogLikelihoodTool.EMShowerContainerName = PhotonRecovery_egDetail_output
+ToolSvc += therecoGammaLogLikelihoodTool
+print      therecoGammaLogLikelihoodTool
+     
+# Reconfigure the PID tools
+from egammaTools.egammaToolsConf import EMPIDBuilder
+PhotonPIDBuilder=EMPIDBuilder("PhotonPIDBuilder")
+PhotonPIDBuilder.egammaEPiRingerCaloTool = None
+PhotonPIDBuilder.EMShowerContainerName     = PhotonRecovery_egDetail_output
+PhotonPIDBuilder.EMTrackMatchContainerName = PhotonRecovery_egDetail_output
+PhotonPIDBuilder.EMConversionContainerName = PhotonRecovery_egDetail_output
+PhotonPIDBuilder.egammaEPiLogLikelihoodTool = therecologlikelihood.getFullName()
+PhotonPIDBuilder.egammaEPiNeuralNetworkTool = thereconeuralnetwork.getFullName()
+PhotonPIDBuilder.egammaEPiLogLikelihoodSETool = therecologlikelihoodse.getFullName()
+PhotonPIDBuilder.egammaIsolationMVATopTool = theIsolationMVATopTool.getFullName()
+PhotonPIDBuilder.egammaHmatrixTool = therecohmatrix.getFullName()
+PhotonPIDBuilder.egammaEPiBoostedDecisionTreeTool = therecoEPiBoostedDecisionTreeTool.getFullName()
+PhotonPIDBuilder.egammaEPiFisherTool = therecoEPiFisherTool.getFullName()
+PhotonPIDBuilder.egammaGamLogLikelihoodTool = therecoGammaLogLikelihoodTool.getFullName()
+PhotonPIDBuilder.egammaSoftElectronCutIDTool = therecosoftelectroncutid.getFullName()
+###PhotonPIDBuilder.egammaElectronCutIDTool = ""#therecoelectroncutid.getFullName()
+PhotonPIDBuilder.egammaPhotonCutIDTools = [thephotoncutidtool.getFullName()]
+#PhotonPIDBuilder.Extrapolator = myInDetExtrapolator
+ToolSvc += PhotonPIDBuilder
+print      PhotonPIDBuilder
+       
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/CellFilter.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/CellFilter.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..862bfc02fd2672ffc2759848209435a17a9d21d7
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/CellFilter.cxx
@@ -0,0 +1,210 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include <algorithm>
+
+#include "CellFilter.h"
+#include "egammaEvent/PhotonContainer.h"
+#include "egammaEvent/ElectronContainer.h"
+#include "egammaEvent/egammaPIDdefs.h"
+#include "DataModel/ConstDataVector.h"
+
+#include "D3PDMakerInterfaces/IObjGetterTool.h"
+
+#include "GaudiKernel/ISvcLocator.h"
+#include "GaudiKernel/StatusCode.h"
+ 
+#include "GaudiKernel/MsgStream.h"
+
+#include "AthenaKernel/errorcheck.h"
+
+#include "StoreGate/StoreGateSvc.h" 
+
+#define PI 2.*asin(1.)
+
+namespace D3PD{
+CellFilter::CellFilter(const std::string& name, 
+			 ISvcLocator* pSvcLocator) : 
+  Algorithm(name, pSvcLocator), 
+  m_inputCellsName("CellParticleCandidate"),
+  m_outputCellsName("SelectedCells"),
+  m_ptCut(10000),
+  m_etaCut(2.5),
+  m_deltaRCut(.6),
+  m_photonID(egammaPID::PhotonIDLoose),
+  m_electronID(egammaPID::ElectronIDMediumPP),
+  m_storeGate(0)
+{ 
+  declareProperty("InputCellCollectionName" ,m_inputCellsName);
+  declareProperty("OutputCellCollectionName",m_outputCellsName);
+  declareProperty("photonGetter"             ,m_ph_getter);
+  declareProperty("electronGetter"           ,m_el_getter);
+  declareProperty("ptCut"                    ,m_ptCut);
+  declareProperty("etaCut"                   ,m_etaCut);
+  declareProperty("deltaRCut"                ,m_deltaRCut);
+  declareProperty("photonID"                 ,m_photonID);
+  declareProperty("electronID"               ,m_electronID);
+  declareProperty("AcceptAll"                ,m_AcceptAll);
+}
+
+CellFilter::~CellFilter()
+{ }
+
+StatusCode CellFilter::initialize()
+{
+
+  MsgStream log(msgSvc(), name());
+
+
+  StatusCode sc;
+   
+   // get StoreGate 
+  sc = service("StoreGateSvc", m_storeGate);
+  if ( sc == StatusCode::FAILURE ) {
+    log<<MSG::ERROR << "   could not access StoreGate " << endreq;
+    return StatusCode::FAILURE;
+  }
+ 
+  // Retrieve the getter tool and configure it, saying that we want
+  // to get @c egamma objects from it.
+  CHECK( m_ph_getter.retrieve() );
+  CHECK( m_ph_getter->configureD3PD<Analysis::Photon>() );
+
+  // Retrieve the getter tool and configure it, saying that we want
+  // to get @c egamma objects from it.
+  CHECK( m_el_getter.retrieve() );
+  CHECK( m_el_getter->configureD3PD<Analysis::Electron>() );
+
+  return StatusCode::SUCCESS;
+    
+}
+
+
+StatusCode CellFilter::finalize()
+{
+
+ return StatusCode::SUCCESS;
+}
+
+///////////////
+StatusCode CellFilter::execute()
+{
+  MsgStream log( messageService(), name() );
+  log << MSG::DEBUG << " in execute" << endreq;
+
+  // Get the input cells container
+  const CaloCellContainer* cellcoll ;
+  StatusCode sc = m_storeGate->retrieve(cellcoll, m_inputCellsName) ; 
+  if(StatusCode::SUCCESS != sc ){
+    log<<MSG::ERROR<<" unable to retrieve CaloCell container: "<< m_inputCellsName <<endreq; 
+    return sc;
+  }
+
+  // Record the output cells container
+  ConstDataVector<CaloCellContainer>* outputCont =
+    new ConstDataVector<CaloCellContainer>(SG::VIEW_ELEMENTS) ;
+  sc = m_storeGate->record(outputCont, m_outputCellsName) ; 
+  if(StatusCode::SUCCESS != sc ) 
+    {
+      log<<MSG::ERROR<<" unable to record Cells container: "<< m_outputCellsName <<endreq; 
+      return sc;
+    }
+
+  // clean vectors
+  etas.clear();
+  phis.clear();
+
+  // a vector to keep cell of the cells from electrons and photons that pass our basic selection
+  std::vector<const CaloCell*> electron_muon_photon_cells;
+
+  // Get the photons
+  if (m_ph_getter->reset().isFailure()) {
+    REPORT_MESSAGE (MSG::ERROR) << "Can't reset input getter.";
+    return 0;
+  }
+
+  // now, loop over all the photons, store the eta and phi positions of qualifying photons
+  //const Analysis::Photon* eout = 0;
+  while ( const Analysis::Photon* obj = m_ph_getter->next<Analysis::Photon>()) {
+
+    if(fabs(obj->cluster()->etaBE(2))>m_etaCut) continue;
+    if(obj->cluster()->pt() < m_ptCut) continue;
+    if(!obj->passID((egammaPID::egammaIDQuality)m_photonID)) continue;
+
+    fillDirection((egamma*)obj);
+  }
+
+  // Get the electrons
+  if (m_el_getter->reset().isFailure()) {
+    REPORT_MESSAGE (MSG::ERROR) << "Can't reset input getter.";
+    return 0;
+  }
+
+  // now, loop over all the electrons, store the eta and phi positions of qualifying electrons
+  //const Analysis::Electron* eout = 0;
+  while ( const Analysis::Electron* obj = m_el_getter->next<Analysis::Electron>()) {
+
+    // only keep the rest of the cells if they're nearby an interesting electron
+    if(fabs(obj->cluster()->etaBE(2))>m_etaCut) continue;
+    if(obj->cluster()->pt() < m_ptCut) continue;
+    if(!obj->passID((egammaPID::egammaIDQuality)m_electronID)) continue;
+
+    fillDirection((egamma*)obj);
+  }
+
+
+  // if there are no qualifying photons/electrons/muons, no need to look any further
+  if(etas.size() == 0 && electron_muon_photon_cells.size() == 0) return sc;
+
+  // now loop over all the cells, and keep the ones that are within m_deltaRCut of at least one of the qualifying photons
+  CaloCellContainer::const_iterator f_cell = cellcoll->begin();
+  CaloCellContainer::const_iterator l_cell = cellcoll->end();
+  
+  for ( ; f_cell!=l_cell; ++f_cell) {
+    const CaloCell* cell = (*f_cell);
+
+    if(m_AcceptAll){
+      outputCont->push_back(const_cast<CaloCell*>(cell));
+      continue;
+    }
+
+    for(unsigned int i=0; i<etas.size(); i++){
+      float deltaR = sqrt( pow(etas[i]-cell->eta()            ,2.) +
+			   pow(acos(cos(phis[i]-cell->phi() )),2.) );
+      if( deltaR < m_deltaRCut ){
+	outputCont->push_back(const_cast<CaloCell*> (cell));
+	break;
+      }
+    }     
+  }
+
+  return sc;
+}
+
+void CellFilter::fillDirection(egamma* obj)
+{  
+  // consider both eta and phi directions, the egamma's object and the cluster ones
+
+  float eta = obj->eta();
+  float phi = obj->phi();
+  
+  etas.push_back(eta);
+  phis.push_back(phi);
+  
+  float eta_clus = obj->cluster()->eta();
+  float phi_clus = obj->cluster()->phi();
+  
+  etas.push_back(eta_clus);
+  phis.push_back(phi_clus);
+  
+}
+
+float CellFilter::correct_phi(float phi)
+{
+  if (phi>    PI) return phi-2.*PI;
+  if (phi<-1.*PI) return phi+2.*PI;
+  return phi;
+}
+
+}
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/CellFilter.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/CellFilter.h
new file mode 100644
index 0000000000000000000000000000000000000000..3b19a44421d82c4ba8da8572720dcb0bbfa56cd5
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/CellFilter.h
@@ -0,0 +1,61 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef CELLFILTER_H
+#define CELLFILTER_H
+
+#include "GaudiKernel/Algorithm.h"
+
+#include "Identifier/Identifier.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "D3PDMakerInterfaces/ICollectionGetterTool.h"
+
+#include "egammaEvent/egamma.h"
+#include "egammaEvent/egammaPIDdefs.h"
+#include "muonEvent/Muon.h"
+#include "CaloEvent/CaloCell.h"
+
+class StoreGateSvc; 
+
+namespace D3PD{
+class IObjGetterTool;
+
+class CellFilter: public Algorithm
+{
+public:    
+
+    CellFilter(const std::string& name, ISvcLocator* pSvcLocator);
+    virtual ~CellFilter();
+    StatusCode initialize();
+    StatusCode execute();
+    StatusCode finalize();
+
+private: 
+
+    std::string     m_inputCellsName;     //cell container
+    std::string     m_outputCellsName;    //output Cell container
+
+    float           m_ptCut;               //min photon/electron pt
+    float           m_etaCut;              //max photon/electron eta
+    float           m_deltaRCut;           //max difference in dR between photon/electron and cell
+
+    long            m_photonID;            //ID cut to be applied on photons
+    long            m_electronID;          //ID cut to be applied on electrons
+
+    bool            m_AcceptAll;
+
+    std::vector<float> etas;
+    std::vector<float> phis;
+
+    StoreGateSvc* m_storeGate; 
+
+    ToolHandle<D3PD::ICollectionGetterTool> m_ph_getter;
+    ToolHandle<D3PD::ICollectionGetterTool> m_el_getter;
+
+    float correct_phi(float phi);
+    void fillDirection(egamma* obj);
+};
+}
+
+#endif
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ClusterFillerTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ClusterFillerTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..5b76c8cc54a067ed44d69463c3ea583e7a97a139
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ClusterFillerTool.cxx
@@ -0,0 +1,125 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/ClusterFillerTool.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Aug, 2009
+ * @brief Block filler tool for a four-momentum.
+ */
+
+
+#include "ClusterFillerTool.h"
+#include "CaloEvent/CaloCluster.h"
+#include "CaloEvent/CaloSamplingHelper.h"
+#include "EventKernel/ISignalState.h"
+#include "EventKernel/SignalStateHelper.h"
+#include "AthenaKernel/errorcheck.h"
+#include "CaloEvent/CaloSamplingHelper.h"
+#include <typeinfo>
+
+
+namespace D3PD {
+
+
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  ClusterFillerTool::ClusterFillerTool (const std::string& type,
+					const std::string& name,
+					const IInterface* parent)
+    : BlockFillerTool<CaloCluster> (type, name, parent)
+  {
+    declareProperty ("SignalState",   m_signalState = P4SignalState::UNKNOWN,
+		     "Signal state of the object to read.  "
+		     "Use the default of UNKNOWN to not change the state.");
+    declareProperty ("UseCaloSamplings", m_useCaloSamplings,
+		     "Calorimeter sampling layers with which to calculate isolation.");
+
+    book().ignore(); // Avoid coverity warnings
+  }
+
+
+  /**
+   * @brief Book variables for this block.
+   */
+  StatusCode ClusterFillerTool::book()
+  {
+    CHECK( addVariable ("E",     m_E)  );
+    CHECK( addVariable ("Et",    m_Et)  );
+
+    CHECK( addVariable ("eta",   m_eta) );
+    CHECK( addVariable ("phi",   m_phi) );
+
+    // check to make sure the calorimeter samplings we've been
+    // given are valid
+    CaloSamplingHelper::getSamplingList(m_caloSamplings);
+    for(std::vector<int>::iterator i=m_useCaloSamplings.begin(); 
+	i != m_useCaloSamplings.end(); ){
+      if(std::find(m_caloSamplings.begin(), m_caloSamplings.end(), 
+		   (CaloSampling::CaloSample)*i) == m_caloSamplings.end()){
+	REPORT_MESSAGE (MSG::WARNING)
+	  << "Requested calorimeter sampling " << (int)(*i)
+	  << " which is not a valid sampling number.  Ignoring it.";
+	i = m_useCaloSamplings.erase(i);
+      }
+      else ++i;
+    }
+
+    return StatusCode::SUCCESS;
+  }
+
+
+  /**
+   * @brief Fill one block --- type-safe version.
+   * @param p The input object.
+   *
+   * This is called once per object.  The caller
+   * is responsible for arranging that all the pointers for booked variables
+   * are set appropriately upon entry.
+   */
+  StatusCode ClusterFillerTool::fill (const CaloCluster& p)
+  {
+    SignalStateHelper sshelper (static_cast<P4SignalState::State>(m_signalState));
+    if (m_signalState != P4SignalState::UNKNOWN) {
+      const ISignalState* ss = dynamic_cast<const ISignalState*> (&p);
+      if (ss)
+	sshelper.controlObject (ss);
+      else {
+	REPORT_MESSAGE (MSG::WARNING)
+	  << "Requested signal state " << m_signalState
+	  << " for object of type " << typeid(p).name()
+	  << "; but it does not derive from ISignalState.";
+      }
+    }
+
+    *m_eta   = static_cast<float> (p.eta());
+    *m_phi   = static_cast<float> (p.phi());
+
+    if(m_caloSamplings.size() == 0){
+      *m_E     = static_cast<float> (p.e());
+      *m_Et    = static_cast<float> (p.et());
+    }
+    else{
+      float e=0., et=0.;
+      
+      for(unsigned int sampling=0; sampling<m_caloSamplings.size(); sampling++){
+	float st = 1./cosh(*m_eta);
+	e  += p.eSample(m_caloSamplings[sampling]);
+	et += p.eSample(m_caloSamplings[sampling])*st;
+      }
+
+      *m_E = e;
+      *m_Et = et;
+    }
+
+    return StatusCode::SUCCESS;
+  }
+
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ClusterFillerTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ClusterFillerTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..69255a7669570e198580d607274c2c3b27f5c50b
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ClusterFillerTool.h
@@ -0,0 +1,89 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/ClusterFillerTool.h
+ * @brief Block filler tool for a four-momentum.
+ */
+
+#ifndef PHOTOND3PDMAKER_CLUSTERFILLERTOOL_H
+#define PHOTOND3PDMAKER_CLUSTERFILLERTOOL_H
+
+#include <vector>
+
+#include "D3PDMakerUtils/BlockFillerTool.h"
+#include "CaloGeoHelpers/CaloSampling.h"
+
+class CaloCluster;
+
+
+namespace D3PD {
+
+
+  /**
+   * @brief Block filler tool for a cluster
+   *
+   */
+class ClusterFillerTool
+  : public BlockFillerTool<CaloCluster>
+  {
+  public:
+    /**
+     * @brief Standard Gaudi tool constructor.
+     * @param type The name of the tool type.
+     * @param name The tool name.
+     * @param parent The tool's Gaudi parent.
+     */
+    ClusterFillerTool (const std::string& type,
+		       const std::string& name,
+		       const IInterface* parent);
+
+
+    /// Book variables for this block.
+    virtual StatusCode book();
+
+
+    /**
+     * @brief Fill one block --- type-safe version.
+     * @param p The input object.
+     *
+     * This is called once per object.  The caller
+     * is responsible for arranging that all the pointers for booked variables
+     * are set appropriately upon entry.
+     */
+    virtual StatusCode fill (const CaloCluster& c);
+
+
+  private:
+    /// Property: Signal state of the object to read.
+    int m_signalState;
+
+    /// Variable: Energy.
+    float* m_E;
+
+    /// Variable: Transverse energy (E*sin(theta)).
+    float* m_Et;
+
+    /// Variable: Pseudorapidity.
+    float* m_eta;
+
+    /// Variable: Azimuth.
+    float* m_phi;
+
+    /// Variable: Available calo samplings
+    std::vector<CaloSampling::CaloSample> m_caloSamplings;
+
+    /// Property: samplings to consider
+    std::vector<int> m_useCaloSamplings;
+
+  };
+
+
+} // namespace D3PD
+
+
+#endif // not PHOTOND3PDMAKER_CLUSTERFILLERTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ConversionNeutralPerigeeAssociationTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ConversionNeutralPerigeeAssociationTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..0652a101f6cabcd6243523da3d921a3adbcf5191
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ConversionNeutralPerigeeAssociationTool.cxx
@@ -0,0 +1,75 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: ConversionNeutralPerigeeAssociationTool.cxx
+/**
+ * @file PhotonD3PDMaker/src/ConversionNeutralPerigeeAssociationTool.cxx
+ * @author Jean-Francois Marchand <jean-francois.marchand@cern.ch>
+ * @date November 2012
+ * @brief Associate MeasuredNeutralPerigee to conversion vertex
+ */
+
+
+#include "ConversionNeutralPerigeeAssociationTool.h"
+#include "EventKernel/INavigable4Momentum.h"
+#include "AthenaKernel/errorcheck.h"
+
+#include "VxVertex/VxContainer.h"
+#include "VxVertex/ExtendedVxCandidate.h"
+//#include "InDetSecVxFinderTool/InDetJetFitterUtils.h"
+#include "egammaUtils/EMConversionUtils.h"
+
+namespace D3PD {
+
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  ConversionNeutralPerigeeAssociationTool::ConversionNeutralPerigeeAssociationTool
+  (const std::string& type,
+   const std::string& name,
+   const IInterface* parent)
+    : Base (type, name, parent)//,
+      //m_convUtils ("InDet::InDetJetFitterUtils/InDetJetFitterUtils")
+  {
+    //declareProperty("ConversionUtils", m_convUtils, "Tool for creating neutral perigee.");
+  }
+  
+  StatusCode ConversionNeutralPerigeeAssociationTool::initialize()
+  {
+    CHECK( Base::initialize() );
+    //CHECK( m_convUtils.retrieve() );
+    return StatusCode::SUCCESS;
+  }
+
+  /**
+   * @brief Return the target object.
+   * @param p The source object for the association.
+   *
+   * Return the target of the association, or 0.
+   */
+  const Trk::NeutralPerigee *ConversionNeutralPerigeeAssociationTool::get (const Trk::VxCandidate& VxConv)
+  {
+    const Trk::NeutralPerigee* perigee = 0;
+
+    //if (dynamic_cast<const Trk::ExtendedVxCandidate*>(&VxConv)) {
+      // This method is gone in current devval.
+      //perigee = m_convUtils->createNeutralPerigee(VxConv);
+    //} else
+    {
+      perigee = EMConversionUtils::createPhotonParameters(&VxConv);
+    }
+    if (!perigee) return 0;
+
+    const Trk::NeutralPerigee* nperigee = dynamic_cast<const Trk::NeutralPerigee*>(perigee);
+
+    return nperigee;
+  }
+  
+} // namespace D3PD
+
+
+
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ConversionNeutralPerigeeAssociationTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ConversionNeutralPerigeeAssociationTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..9abf964ce2b9ef18eb442c4023e025d9ed218794
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ConversionNeutralPerigeeAssociationTool.h
@@ -0,0 +1,73 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: ConversionNeutralPerigeeAssociationTool.h
+/**
+ * @file PhotonD3PDMaker/src/ConversionNeutralPerigeeAssociationTool.h
+ * @author Jean-Francois Marchand <jean-francois.marchand@cern.ch>
+ * @date November 2012
+ * @brief Associate MeasuredNeutralPerigee to conversion vertex
+ */
+
+#ifndef PHOTOND3PDMAKER_CONVERSIONNEUTRALPERIGEEASSOCIATIONTOOL_H
+#define PHOTOND3PDMAKER_CONVERSIONNEUTRALPERIGEEASSOCIATIONTOOL_H
+
+#include "D3PDMakerUtils/SingleAssociationTool.h"
+#include "TrkNeutralParameters/NeutralParameters.h"
+#include "GaudiKernel/ToolHandle.h"
+
+namespace Trk {
+  class VxCandidate;
+  class ExtendedVxCandidate;
+}
+
+namespace InDet{
+//class InDetJetFitterUtils;
+}
+
+
+namespace D3PD {
+
+  /**
+   * @brief Associate from a VxTrackAtVertex to a MeasuredPerigee.
+   */
+  class ConversionNeutralPerigeeAssociationTool
+    : public SingleAssociationTool<Trk::VxCandidate, Trk::NeutralPerigee>
+  {
+  public:
+    typedef SingleAssociationTool<Trk::VxCandidate, Trk::NeutralPerigee> Base;
+    
+    /**
+     * @brief Standard Gaudi tool constructor.
+     * @param type The name of the tool type.
+     * @param name The tool name.
+     * @param parent The tool's Gaudi parent.
+     */
+    ConversionNeutralPerigeeAssociationTool (const std::string& type,
+				      const std::string& name,
+				      const IInterface* parent);
+
+    StatusCode initialize();
+
+    /**
+     * @brief Return the target object.
+     * @param p The source object for the association.
+     *
+     * Return the target of the association, or 0.
+     */
+    virtual const Trk::NeutralPerigee* get (const Trk::VxCandidate& p);
+
+  private:
+    //ToolHandle<InDet::InDetJetFitterUtils> m_convUtils;
+
+  };
+  
+  
+} // namespace D3PD
+
+
+
+#endif // not PHOTOND3PDMAKER_CONVERSIONNEUTRALPERIGEEASSOCIATIONTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ConversionPerigeeAssociationTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ConversionPerigeeAssociationTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..d2cec375e7b3556fd6b4ad11b365ab8de63498f3
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ConversionPerigeeAssociationTool.cxx
@@ -0,0 +1,51 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: ConversionPerigeeAssociationTool.cxx
+/**
+ * @file PhotonD3PDMaker/src/ConversionPerigeeAssociationTool.cxx
+ * @author Jean-Francois Marchand <jean-francois.marchand@cern.ch>
+ * @date November 2012
+ * @brief Associate Perigee to conversions tracks
+ */
+
+
+#include "ConversionPerigeeAssociationTool.h"
+#include "Particle/TrackParticle.h"
+#include "VxVertex/VxTrackAtVertex.h"
+#include "EventKernel/INavigable4Momentum.h"
+#include "AthenaKernel/errorcheck.h"
+
+
+namespace D3PD {
+
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  ConversionPerigeeAssociationTool::ConversionPerigeeAssociationTool
+  (const std::string& type,
+   const std::string& name,
+   const IInterface* parent)
+    : Base (type, name, parent)
+  {
+  }
+  
+  /**
+   * @brief Return the target object.
+   * @param p The source object for the association.
+   *
+   * Return the target of the association, or 0.
+   */
+const Trk::Perigee *ConversionPerigeeAssociationTool::get (const Trk::VxTrackAtVertex& track)
+  {
+    return dynamic_cast<const Trk::Perigee*>(track.perigeeAtVertex());
+  }
+  
+} // namespace D3PD
+
+
+
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ConversionPerigeeAssociationTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ConversionPerigeeAssociationTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..83191ed10d2adc1fddd6a8a9512f08dffc6c717a
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ConversionPerigeeAssociationTool.h
@@ -0,0 +1,60 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: ConversionPerigeeAssociationTool.h
+/**
+ * @file PhotonD3PDMaker/src/ConversionPerigeeAssociationTool.h
+ * @author Jean-Francois Marchand <jean-francois.marchand@cern.ch>
+ * @date November 2012
+ * @brief Associate Perigee to conversions tracks
+ */
+
+#ifndef PHOTOND3PDMAKER_CONVERSIONPERIGEEASSOCIATIONTOOL_H
+#define PHOTOND3PDMAKER_CONVERSIONPERIGEEASSOCIATIONTOOL_H
+
+#include "D3PDMakerUtils/SingleAssociationTool.h"
+#include "TrkParameters/TrackParameters.h"
+
+namespace Trk {
+  class VxTrackAtVertex;
+}
+
+namespace D3PD {
+
+  /**
+   * @brief Associate from a VxTrackAtVertex to a Perigee.
+   */
+  class ConversionPerigeeAssociationTool
+    : public SingleAssociationTool<Trk::VxTrackAtVertex, Trk::Perigee>
+  {
+  public:
+    typedef SingleAssociationTool<Trk::VxTrackAtVertex, Trk::Perigee> Base;
+    
+    /**
+     * @brief Standard Gaudi tool constructor.
+     * @param type The name of the tool type.
+     * @param name The tool name.
+     * @param parent The tool's Gaudi parent.
+     */
+    ConversionPerigeeAssociationTool (const std::string& type,
+				      const std::string& name,
+				      const IInterface* parent);
+    
+    /**
+     * @brief Return the target object.
+     * @param p The source object for the association.
+     *
+     * Return the target of the association, or 0.
+     */
+    virtual const Trk::Perigee* get (const Trk::VxTrackAtVertex& p);
+  };
+  
+  
+} // namespace D3PD
+
+
+
+#endif // not PHOTOND3PDMAKER_CONVERSIONPERIGEEASSOCIATIONTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/DREtAssociationTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/DREtAssociationTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..c9c1aa9c35fb40ed8254f0edb54b3f9b4aa179cc
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/DREtAssociationTool.cxx
@@ -0,0 +1,103 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: DREtAssociationTool.cxx 547010 2013-05-07 07:44:50Z jmarchan $
+/**
+ * @file PhotonD3PDMaker/src/DREtAssociationTool.cxx
+ * @author Mike Hance, based on DRAssociationTool by Scott Snyder
+ * @date Mar. 2010
+ * @brief Associate to highest E_T particle in a cone of size dR.
+ */
+
+
+#include "DREtAssociationTool.h"
+#include "FourMomUtils/P4Helpers.h"
+#include "EventKernel/INavigable4Momentum.h"
+#include "AthenaKernel/errorcheck.h"
+
+#include "egammaEvent/Photon.h"
+#include "CaloEvent/CaloCluster.h"
+
+namespace D3PD {
+
+
+/**
+ * @brief Standard Gaudi tool constructor.
+ * @param type The name of the tool type.
+ * @param name The tool name.
+ * @param parent The tool's Gaudi parent.
+ */
+DREtAssociationTool::DREtAssociationTool (const std::string& type,
+					  const std::string& name,
+					  const IInterface* parent)
+  : Base (type, name, parent),
+    m_getter (this)
+{
+  declareProperty ("Getter", m_getter,
+                   "ICollectionGetterTool instance defining "
+                   "the target collection");
+  declareProperty ("DRCut", m_drcut = 999,
+                   "DR cut for the association");
+}
+
+
+/**
+ * @brief Standard Gaudi initialize method.
+ */
+StatusCode DREtAssociationTool::initialize()
+{
+  // Retrieve the getter tool and configure it, saying that we want
+  // to get @c INavigable4Momentum objects from it.
+  CHECK( m_getter.retrieve() );
+  CHECK( m_getter->configureD3PD<INavigable4Momentum>() );
+  return Base::initialize();
+}
+
+
+/**
+ * @brief Create any needed tuple variables.
+ */
+StatusCode DREtAssociationTool::book ()
+{
+  CHECK( addVariable ("dr", m_dr) );
+  return StatusCode::SUCCESS;
+}
+
+
+/**
+ * @brief Return the target object.
+ * @param p The source object for the association.
+ *
+ * Return the target of the association, or 0.
+ */
+const INavigable4Momentum*
+DREtAssociationTool::get (const INavigable4Momentum& p)
+{
+  *m_dr = -1;
+
+  if (m_getter->reset().isFailure()) {
+    REPORT_MESSAGE (MSG::ERROR) << "Can't reset input getter.";
+    return 0;
+  }
+
+  const Analysis::Photon* pho = dynamic_cast< const Analysis::Photon* >(&p);
+
+  const INavigable4Momentum* pout = 0;
+  float max_pt = 0.;
+  while ( const INavigable4Momentum* obj =
+          m_getter->next<INavigable4Momentum>())
+  {
+    float dr = (pho && pho->cluster()) ? static_cast<float> (P4Helpers::deltaR (*pho->cluster(), *obj)) : static_cast<float> (P4Helpers::deltaR (p, *obj));
+ 
+    if (dr < m_drcut && obj->pt() > max_pt) {
+      max_pt = obj->pt();
+      * m_dr = dr;
+      pout = obj;
+    }
+  }
+  return pout;
+}
+
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/DREtAssociationTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/DREtAssociationTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..34887f35c9b833d79dc9b21772baed328d7b1840
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/DREtAssociationTool.h
@@ -0,0 +1,98 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: DREtAssociationTool.h 354541 2011-03-26 04:55:52Z mhance $
+/**
+ * @file EventCommonD3PDMaker/src/DREtAssociationTool.h
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Aug, 2009
+ * @brief Associate to particle closest in DR.
+ */
+
+
+#ifndef PHOTOND3PDMAKER_DRASSOCIATIONTOOL_H
+#define PHOTOND3PDMAKER_DRASSOCIATIONTOOL_H
+
+
+#include "D3PDMakerInterfaces/ICollectionGetterTool.h"
+#include "D3PDMakerUtils/SingleAssociationTool.h"
+#include "EventKernel/INavigable4Momentum.h"
+#include "GaudiKernel/ToolHandle.h"
+
+
+namespace D3PD {
+
+
+/**
+ * @brief Associate to particle closest in DR.
+ *
+ * This is a single association tool.
+ * Given an @c INavigable4Momentum object and a container of such objects,
+ * return the object in the container closest in DR to the input object.
+ * Optionally, a DR cut may be set; the association fails if there
+ * are no objects within that cut.
+ *
+ * Parameters:
+ *  Getter - ICollectionGetterTool instance defining the target collection.
+ *  DRCut  - DR cut for the association.  (default: 999)
+ *
+ * This tool will create a tuple variable `dr' giving the distance
+ * in DR to the associated object.
+ */
+class DREtAssociationTool
+  : public SingleAssociationTool<INavigable4Momentum>
+{
+public:
+  typedef SingleAssociationTool<INavigable4Momentum> Base;
+
+
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  DREtAssociationTool (const std::string& type,
+		       const std::string& name,
+		       const IInterface* parent);
+
+
+  /// Standard Gaudi initialize method.
+  virtual StatusCode initialize();
+
+
+  /**
+   * @brief Create any needed tuple variables.
+   */
+  virtual StatusCode book();
+
+
+  /**
+   * @brief Return the target object.
+   * @param p The source object for the association.
+   *
+   * Return the target of the association, or 0.
+   */
+  virtual const INavigable4Momentum* get (const INavigable4Momentum& p);
+
+
+private:
+  /// Property: The getter for the target collection.
+  ToolHandle<ICollectionGetterTool> m_getter;
+
+  /// Property: DR cut.
+  float m_drcut;
+
+  /// Variable: DR to associated object.
+  float* m_dr;
+};
+
+
+} // namespace D3PD
+
+
+
+#endif // not PHOTOND3PDMAKER_DRASSOCIATIONTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/EgammaFilter.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/EgammaFilter.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..f2aea4b1855386b9ed490dbebb1e9da306aff66d
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/EgammaFilter.cxx
@@ -0,0 +1,188 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include <algorithm>
+
+#include "EgammaFilter.h"
+#include "Particle/TrackParticle.h"
+#include "TrkTrackSummary/TrackSummary.h"
+#include "Particle/TrackParticleContainer.h"
+#include "egammaEvent/PhotonContainer.h"
+#include "egammaEvent/ElectronContainer.h"
+#include "egammaEvent/egammaPIDdefs.h"
+#include "muonEvent/MuonContainer.h"
+
+#include "TrkTrack/LinkToTrack.h"
+#include "TrkParticleBase/TrackParticleBaseCollection.h"
+#include "TrkParticleBase/TrackParticleBase.h"
+#include "TrkParticleBase/LinkToTrackParticleBase.h"
+#include "VxVertex/VxTrackAtVertex.h"
+
+#include "GaudiKernel/ISvcLocator.h"
+#include "GaudiKernel/StatusCode.h"
+ 
+#include "GaudiKernel/MsgStream.h"
+
+#include "AthenaKernel/errorcheck.h"
+
+#include "StoreGate/StoreGateSvc.h" 
+
+namespace D3PD{
+EgammaFilter::EgammaFilter(const std::string& name, 
+			   ISvcLocator* pSvcLocator) : 
+  Algorithm(name, pSvcLocator), 
+  m_storeGate(0),
+  m_ph_getter(),
+  m_el_getter(),
+  m_PhotonNNTool("PhotonNeuralNetworkTool")
+{ 
+  declareProperty("OutputPhotonCollectionName"     , m_outputPhotonCollName   = "SelectedPhotons"       );
+  declareProperty("PhotonGetter"                   , m_ph_getter                                        );
+  declareProperty("PhotonPtCut"                    , m_photon_ptCut           = 20000.                  );
+  declareProperty("PhotonEtaCut"                   , m_photon_etaCut          = 2.5                     );
+  declareProperty("PhotonIsEM"                     , m_photon_IsEM            = egammaPID::PhotonIDLoose);
+  declareProperty("PhotonNNCut"                    , m_photon_NNCut           = true                   );
+
+  declareProperty("OutputElectronCollectionName"   , m_outputElectronCollName = "SelectedElectrons"     );
+  declareProperty("ElectronGetter"                 , m_el_getter                                        );
+  declareProperty("ElectronPtCut"                  , m_electron_ptCut         = 20000.                  );
+  declareProperty("ElectronEtaCut"                 , m_electron_etaCut        = 2.5                     );
+  declareProperty("ElectronIsEM"                   , m_electron_IsEM          = egammaPID::ElectronIDMediumPP );
+
+  declareProperty ("PhotonNNTool"                  , m_PhotonNNTool,
+		   "Photon neural-network helper tool.");
+}
+
+EgammaFilter::~EgammaFilter()
+{ }
+
+StatusCode EgammaFilter::initialize()
+{
+
+  MsgStream log(msgSvc(), name());
+
+
+  StatusCode sc;
+   
+  // get StoreGate 
+  sc = service("StoreGateSvc", m_storeGate);
+  if ( sc == StatusCode::FAILURE ) {
+    log<<MSG::ERROR << "   could not access StoreGate " << endreq;
+    return StatusCode::FAILURE;
+  }
+ 
+  // Retrieve the getter tool and configure it, saying that we want
+  // to get @c PAU::egamma objects from it.
+  CHECK( m_ph_getter.retrieve() );
+  CHECK( m_ph_getter->configureD3PD<Analysis::Photon>() );
+
+  CHECK( m_el_getter.retrieve() );
+  CHECK( m_el_getter->configureD3PD<Analysis::Electron>() );
+
+  CHECK( m_PhotonNNTool.retrieve() );
+
+  return StatusCode::SUCCESS;
+    
+}
+
+
+StatusCode EgammaFilter::finalize()
+{
+
+ return StatusCode::SUCCESS;
+}
+
+///////////////
+StatusCode EgammaFilter::execute()
+{
+  MsgStream log( messageService(), name() );
+  log << MSG::DEBUG << " in execute" << endreq;
+
+  // Record the output photon container
+  egammaContainer* outputPhotonCont = new egammaContainer(SG::VIEW_ELEMENTS) ;
+  CHECK( m_storeGate->record(outputPhotonCont, m_outputPhotonCollName) ); 
+
+
+  // Get the photons
+  if (m_ph_getter->reset().isFailure()) {
+    REPORT_MESSAGE (MSG::ERROR) << "Can't reset input getter.";
+    return StatusCode::FAILURE;
+  }
+
+  // loop over all the photons, keep the ones that pass
+  while ( const Analysis::Photon* obj = m_ph_getter->next<Analysis::Photon>() ) {
+    if(acceptPhoton(obj)){
+      outputPhotonCont->push_back(const_cast<Analysis::Photon*> (obj)); 
+    }
+  }
+
+
+  // now, loop over all the electrons, keep the ones that pass and that don't overlap with photons
+  // we've already accepted
+  egammaContainer* outputElectronCont = new egammaContainer(SG::VIEW_ELEMENTS) ;
+  CHECK( m_storeGate->record(outputElectronCont, m_outputElectronCollName) ); 
+
+  if (m_el_getter->reset().isFailure()) {
+    REPORT_MESSAGE (MSG::ERROR) << "Can't reset input getter.";
+    return StatusCode::FAILURE;
+  }
+
+  while ( const Analysis::Electron* obj = m_el_getter->next<Analysis::Electron>()) {
+    if(acceptElectron(obj)){
+      bool isOverlap = false;
+      for(egammaContainer::const_iterator photonIter = outputPhotonCont->begin();
+	  photonIter != outputPhotonCont->end();
+	  ++photonIter){
+	if(IsOverlap(obj, *photonIter)){
+	  isOverlap = true;
+	  break;
+	}
+      }
+      if(!isOverlap)
+	outputElectronCont->push_back(const_cast<Analysis::Electron*> (obj)); 
+    }
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+
+// Keep photons that satisfy all of the requirements.
+bool EgammaFilter::acceptPhoton(const Analysis::Photon* photon){
+  if(!photon->cluster()) 
+    return false;
+  if(photon->cluster()->pt() < m_photon_ptCut) 
+    return false;
+  if(fabs(photon->cluster()->etaBE(2)) > m_photon_etaCut) 
+    return false;
+  
+  if(m_photon_IsEM != 0 && !photon->passID((egammaPID::egammaIDQuality)m_photon_IsEM)) 
+    return false;
+  if(m_photon_NNCut  && !m_PhotonNNTool->Passes(photon)) 
+    return false;
+  
+  return true;
+}
+
+// Keep electrons that satisfy all of the requirements.
+bool EgammaFilter::acceptElectron(const Analysis::Electron* electron){
+  if(!electron->cluster()) 
+    return false;
+  if(electron->cluster()->pt() < m_electron_ptCut) 
+    return false;
+  if(fabs(electron->cluster()->etaBE(2)) > m_electron_etaCut) 
+    return false;
+  
+  if(m_electron_IsEM != 0 && !electron->passID((egammaPID::egammaIDQuality)m_electron_IsEM)) 
+    return false;
+  
+  return true;
+}
+
+
+bool EgammaFilter::IsOverlap(const egamma* el, const egamma* ph){
+  return el->hasSameAthenaBarCodeExceptVersion(*ph);
+}
+
+}
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/EgammaFilter.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/EgammaFilter.h
new file mode 100644
index 0000000000000000000000000000000000000000..d871b1377fea7aa85533721a2b6ac7e6a2997d3e
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/EgammaFilter.h
@@ -0,0 +1,67 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef EGAMMAFILTER_H
+#define EGAMMAFILTER_H
+
+#include "GaudiKernel/Algorithm.h"
+
+#include "Identifier/Identifier.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "D3PDMakerInterfaces/ICollectionGetterTool.h"
+
+#include "PhotonAnalysisUtils/IPhotonNeuralNetworkTool.h"
+
+#include "egammaEvent/egamma.h"
+#include "egammaEvent/Photon.h"
+#include "egammaEvent/Electron.h"
+
+#include "muonEvent/Muon.h"
+
+class StoreGateSvc; 
+
+namespace D3PD{
+class EgammaFilter: public Algorithm
+{
+public:    
+
+    EgammaFilter(const std::string& name, ISvcLocator* pSvcLocator);
+    virtual ~EgammaFilter();
+    StatusCode initialize();
+    StatusCode execute();
+    StatusCode finalize();
+
+private: 
+
+    std::string     m_outputPhotonCollName;      //output container
+
+    float           m_photon_ptCut;               //min photon/electron pt
+    float           m_photon_etaCut;              //max photon/electron eta
+    long            m_photon_IsEM;                //isEM cut to be applied on photons
+    bool            m_photon_NNCut;               //neural net requirement
+
+    std::string     m_outputElectronCollName;      //output container
+
+    float           m_electron_ptCut;               //min electron/electron pt
+    float           m_electron_etaCut;              //max electron/electron eta
+    long            m_electron_IsEM;                //isEM cut to be applied on electrons 
+
+    StoreGateSvc* m_storeGate; 
+
+    ToolHandle<D3PD::ICollectionGetterTool> m_ph_getter;
+    ToolHandle<D3PD::ICollectionGetterTool> m_el_getter;
+
+    bool           acceptPhoton  (const Analysis::Photon* ph);
+    bool           acceptElectron(const Analysis::Electron* el);
+
+    bool           IsOverlap(const egamma* ph, const egamma* el);
+
+    /// Property: NN tool
+    ToolHandle<IPhotonNeuralNetworkTool> m_PhotonNNTool;
+
+};
+
+}
+
+#endif
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/EgammaTruthParticleFilter.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/EgammaTruthParticleFilter.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..9331dd2dd11d86664bc9718eb71746f20b4c0780
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/EgammaTruthParticleFilter.cxx
@@ -0,0 +1,122 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include <algorithm>
+
+#include "EgammaTruthParticleFilter.h"
+#include "egammaEvent/Photon.h"
+#include "egammaEvent/Electron.h"
+#include "McParticleEvent/TruthParticle.h"
+#include "McParticleEvent/TruthParticleContainer.h"
+
+#include "GaudiKernel/ISvcLocator.h"
+#include "GaudiKernel/StatusCode.h"
+ 
+#include "GaudiKernel/MsgStream.h"
+
+#include "AthenaKernel/errorcheck.h"
+
+#include "StoreGate/StoreGateSvc.h" 
+
+#define PI 2.*asin(1.)
+
+namespace D3PD{
+EgammaTruthParticleFilter::EgammaTruthParticleFilter(const std::string& name, 
+			 ISvcLocator* pSvcLocator) : 
+  AthAlgorithm(name, pSvcLocator), 
+  m_outputTruthName("EgammaTruth"),
+  m_ph_getter(this),
+  m_el_getter(this),
+  m_truth_getter(this)
+{ 
+  declareProperty("OutputTruthCollectionName",m_outputTruthName);
+  declareProperty("PhotonGetter"             ,m_ph_getter);
+  declareProperty("ElectronGetter"           ,m_el_getter);
+  declareProperty("TruthGetter"              ,m_truth_getter);
+  declareProperty ("PAUtruthTool", m_PAUtruthTool,
+                   "PAU truth tool.");
+  declareProperty("PhotonPtCut", m_ptCut=500);
+}
+
+EgammaTruthParticleFilter::~EgammaTruthParticleFilter()
+{ }
+
+StatusCode EgammaTruthParticleFilter::initialize()
+{
+
+  // Retrieve the getter tool and configure it, saying that we want
+  // to get @c PAU::egamma objects from it.
+  CHECK( m_ph_getter.retrieve() );
+  CHECK( m_ph_getter->configureD3PD<Analysis::Photon>() );
+
+  // Retrieve the getter tool and configure it, saying that we want
+  // to get @c PAU::egamma objects from it.
+  CHECK( m_el_getter.retrieve() );
+  CHECK( m_el_getter->configureD3PD<Analysis::Electron>() );
+
+  return StatusCode::SUCCESS;
+    
+}
+
+
+StatusCode EgammaTruthParticleFilter::finalize()
+{
+ return StatusCode::SUCCESS;
+}
+
+StatusCode EgammaTruthParticleFilter::AddTruthParticle(const TruthParticle* tp, TruthParticleContainer* outputCont){
+  if(tp && m_kept_truth.find(tp) == m_kept_truth.end()){
+    outputCont->push_back(const_cast<TruthParticle*>(tp));
+    m_kept_truth.insert(tp);
+  }
+  return StatusCode::SUCCESS;
+}
+
+///////////////
+StatusCode EgammaTruthParticleFilter::execute()
+{
+  MsgStream log( messageService(), name() );
+  log << MSG::DEBUG << " in execute" << endreq;
+
+  m_kept_truth.clear();
+
+  // Record the output tracks container
+  TruthParticleContainer* outputCont = new TruthParticleContainer(SG::VIEW_ELEMENTS);
+  CHECK ( evtStore()->record(outputCont, m_outputTruthName) );
+
+  // now, loop over all the photons, store the eta and phi positions of qualifying photons
+  CHECK ( m_ph_getter->reset() );
+  while ( const Analysis::Photon* obj = m_ph_getter->next<Analysis::Photon>()) {
+    CHECK( AddTruthParticle(m_PAUtruthTool->getTruthMatch(obj), outputCont) );
+    if (obj->conversion()) { // in case of converted photon, we want to keep the 2 truth objects mathced to the conversions tracks
+      for (unsigned int i=0 ; i<m_PAUtruthTool->getTruthConvMatch(obj).size() ; i++) {
+	CHECK( AddTruthParticle(m_PAUtruthTool->getTruthConvMatch(obj).at(i), outputCont) );
+      }
+    }
+  }
+
+  // now, loop over all the electrons, store the eta and phi positions of qualifying electrons
+  CHECK ( m_el_getter->reset() );
+  while ( const Analysis::Electron* obj = m_el_getter->next<Analysis::Electron>()) {
+    CHECK ( AddTruthParticle(m_PAUtruthTool->getTruthMatch(obj), outputCont) );
+  }
+
+  // finally, check the rest of the truth particles for "interesting" candidates
+  CHECK ( m_truth_getter->reset() );
+  while ( const TruthParticle* tp = m_truth_getter->next<TruthParticle>()) {
+    
+    if ( tp == 0 || 
+	 tp->genParticle() == 0 ||
+	 tp->pdgId() != 22 || 
+	 !(m_PAUtruthTool->isFinalStatePhotonMC(tp)) ||
+	 (tp->pdgId()==22 && tp->pt()<m_ptCut) )  
+      continue;
+
+    CHECK ( AddTruthParticle(tp, outputCont) );
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+}
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/EgammaTruthParticleFilter.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/EgammaTruthParticleFilter.h
new file mode 100644
index 0000000000000000000000000000000000000000..9d4d8eed8f690f4576a956450f54f22d1ce7e7b8
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/EgammaTruthParticleFilter.h
@@ -0,0 +1,52 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef EGAMMATRUTHPARTICLEFILTER_H
+#define EGAMMATRUTHPARTICLEFILTER_H
+
+#include "AthenaBaseComps/AthAlgorithm.h"
+
+#include "Identifier/Identifier.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "D3PDMakerInterfaces/ICollectionGetterTool.h"
+
+#include "PhotonAnalysisUtils/IPAUtruthTool.h"
+
+class StoreGateSvc; 
+class TruthParticle;
+class TruthParticleContainer;
+
+namespace D3PD{
+class EgammaTruthParticleFilter: public AthAlgorithm
+{
+public:    
+
+    EgammaTruthParticleFilter(const std::string& name, ISvcLocator* pSvcLocator);
+    virtual ~EgammaTruthParticleFilter();
+    StatusCode initialize();
+    StatusCode execute();
+    StatusCode finalize();
+
+private: 
+
+    StatusCode AddTruthParticle(const TruthParticle* tp, TruthParticleContainer* outputCont);
+
+    std::string     m_inputTruthName;     //truth container
+    std::string     m_outputTruthName;    //output truth container
+
+    /// Property: truth tool
+    ToolHandle<IPAUtruthTool> m_PAUtruthTool;
+
+    ToolHandle<D3PD::ICollectionGetterTool> m_ph_getter;
+    ToolHandle<D3PD::ICollectionGetterTool> m_el_getter;
+    ToolHandle<D3PD::ICollectionGetterTool> m_truth_getter;
+
+    float m_ptCut;
+
+    std::set<const TruthParticle*> m_kept_truth;
+
+};
+}
+
+#endif
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ElectronFilter.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ElectronFilter.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..d1c671d10131b5be3820c8188c8d4a6990539d2f
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ElectronFilter.cxx
@@ -0,0 +1,139 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include <algorithm>
+
+#include "ElectronFilter.h"
+#include "Particle/TrackParticle.h"
+#include "TrkTrackSummary/TrackSummary.h"
+#include "Particle/TrackParticleContainer.h"
+#include "egammaEvent/ElectronContainer.h"
+#include "egammaEvent/ElectronContainer.h"
+#include "egammaEvent/egammaPIDdefs.h"
+#include "muonEvent/MuonContainer.h"
+
+#include "TrkTrack/LinkToTrack.h"
+#include "TrkParticleBase/TrackParticleBaseCollection.h"
+#include "TrkParticleBase/TrackParticleBase.h"
+#include "TrkParticleBase/LinkToTrackParticleBase.h"
+#include "VxVertex/VxTrackAtVertex.h"
+
+#include "GaudiKernel/ISvcLocator.h"
+#include "GaudiKernel/StatusCode.h"
+ 
+#include "GaudiKernel/MsgStream.h"
+
+#include "AthenaKernel/errorcheck.h"
+
+#include "StoreGate/StoreGateSvc.h" 
+
+#define PI 2.*asin(1.)
+
+namespace D3PD{
+ElectronFilter::ElectronFilter(const std::string& name, 
+			   ISvcLocator* pSvcLocator) : 
+  Algorithm(name, pSvcLocator), 
+  m_storeGate(0),
+  m_el_getter()
+{ 
+  declareProperty("OutputCollectionName"     , m_outputCollName   = "SelectedElectrons"      );
+  declareProperty("electronGetter"           , m_el_getter                                   );
+  declareProperty("ptCut"                    , m_ptCut            = 20000.                   );
+  declareProperty("etaCut"                   , m_etaCut           = 2.5                      );
+  declareProperty("IsEM"                     , m_IsEM             = egammaPID::ElectronLoose );
+  declareProperty("Indices"                  , m_indices                                     );
+  declareProperty("RejectAll"                , m_RejectAll        = false                    );
+  declareProperty("AcceptAll"                , m_AcceptAll        = false                    );
+}
+
+ElectronFilter::~ElectronFilter()
+{ }
+
+StatusCode ElectronFilter::initialize()
+{
+
+  MsgStream log(msgSvc(), name());
+
+
+  StatusCode sc;
+   
+   // get StoreGate 
+  sc = service("StoreGateSvc", m_storeGate);
+  if ( sc == StatusCode::FAILURE ) {
+    log<<MSG::ERROR << "   could not access StoreGate " << endreq;
+    return StatusCode::FAILURE;
+  }
+ 
+  // Retrieve the getter tool and configure it, saying that we want
+  // to get @c PAU::egamma objects from it.
+  CHECK( m_el_getter.retrieve() );
+  CHECK( m_el_getter->configureD3PD<Analysis::Electron>() );
+
+  return StatusCode::SUCCESS;
+    
+}
+
+
+StatusCode ElectronFilter::finalize()
+{
+
+ return StatusCode::SUCCESS;
+}
+
+///////////////
+StatusCode ElectronFilter::execute()
+{
+  MsgStream log( messageService(), name() );
+  log << MSG::DEBUG << " in execute" << endreq;
+
+  // Record the output tracks container
+  egammaContainer* outputCont = new egammaContainer(SG::VIEW_ELEMENTS) ;
+  StatusCode sc = m_storeGate->record(outputCont, m_outputCollName) ; 
+  if(StatusCode::SUCCESS != sc ) {
+    log<<MSG::ERROR<<" unable to record output container: "<< m_outputCollName <<endreq; 
+    return sc;
+  }
+
+
+  // Get the electrons
+  if (m_el_getter->reset().isFailure()) {
+    REPORT_MESSAGE (MSG::ERROR) << "Can't reset input getter.";
+    return 0;
+  }
+
+  // now, loop over all the electrons, store the eta and phi positions of qualifying electrons
+  int numAcceptedObjects=0;
+  while ( const Analysis::Electron* obj = m_el_getter->next<Analysis::Electron>()) {
+    if(accept(obj)){
+      if(m_indices.size()==0 || 
+	 std::find(m_indices.begin(),m_indices.end(),numAcceptedObjects)!=m_indices.end()){
+	outputCont->push_back(const_cast<Analysis::Electron*> (obj)); 
+      }
+      ++numAcceptedObjects;
+    }
+  }
+
+  return sc;
+}
+
+
+// Keep electrons that satisfy all of the requirements.
+bool ElectronFilter::accept(const Analysis::Electron* electron){
+  if(m_RejectAll)
+    return false;
+  if(m_AcceptAll)
+    return true;
+
+  if(!electron->cluster()) 
+    return false;
+  if(electron->cluster()->pt() < m_ptCut) 
+    return false;
+  
+  if(m_IsEM != 0 && !electron->passID((egammaPID::egammaIDQuality)m_IsEM)) 
+    return false;
+
+  return true;
+}
+
+}
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ElectronFilter.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ElectronFilter.h
new file mode 100644
index 0000000000000000000000000000000000000000..20211bb86807ec20f09a3b00790e5dac18b8a731
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ElectronFilter.h
@@ -0,0 +1,56 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ELECTRONFILTER_H
+#define ELECTRONFILTER_H
+
+#include "GaudiKernel/Algorithm.h"
+
+#include "Identifier/Identifier.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "D3PDMakerInterfaces/ICollectionGetterTool.h"
+
+#include "egammaEvent/egamma.h"
+#include "egammaEvent/Electron.h"
+
+#include "muonEvent/Muon.h"
+
+class StoreGateSvc; 
+
+namespace D3PD{
+class ElectronFilter: public Algorithm
+{
+public:    
+
+    ElectronFilter(const std::string& name, ISvcLocator* pSvcLocator);
+    virtual ~ElectronFilter();
+    StatusCode initialize();
+    StatusCode execute();
+    StatusCode finalize();
+
+private: 
+
+    std::string     m_outputCollName;      //output container
+
+    float           m_ptCut;               //min photon/electron pt
+    float           m_etaCut;              //max photon/electron eta
+
+    long            m_IsEM;                //isEM cut to be applied on photons
+
+    std::vector<int> m_indices;            //only keep a few photons that pass all other requirements, by index
+
+    StoreGateSvc* m_storeGate; 
+
+    bool            m_RejectAll;
+    bool            m_AcceptAll;
+
+    ToolHandle<D3PD::ICollectionGetterTool> m_el_getter;
+
+    bool           accept(const Analysis::Electron* el);
+
+};
+
+}
+
+#endif
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ElectronSorterAlg.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ElectronSorterAlg.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..8a1b3117f4bc886c1194c2926cb004eeb3be34d1
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ElectronSorterAlg.cxx
@@ -0,0 +1,31 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/ElectronSorterAlg.cxx
+ * @author Mike Hance
+ * @date Feb, 2010
+ * @brief sorting by pt
+ */
+
+
+#include "ElectronSorterAlg.h"
+
+
+namespace D3PD {
+
+
+/**
+ * @brief Standard Gaudi algorithm constructor.
+ * @param name The algorithm name.
+ * @param svcloc The service locator.
+ */
+ElectronSorterAlg::ElectronSorterAlg (const std::string& name,
+                                      ISvcLocator* svcloc)
+  : IN4MSorterAlg<ElectronContainer> (name, svcloc)
+{
+}
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ElectronSorterAlg.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ElectronSorterAlg.h
new file mode 100644
index 0000000000000000000000000000000000000000..1da59606f00cf374ec9c0a59b08fa94985a66cfd
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ElectronSorterAlg.h
@@ -0,0 +1,48 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/ElectronSorterAlg.h
+ * @author Mike Hance
+ * @date Feb, 2011
+ * @brief sort by pt
+ */
+
+
+#ifndef PHOTOND3PDMAKER_ELECTRONSORTERALG_H
+#define PHOTOND3PDMAKER_ELECTRONSORTERALG_H
+
+
+#include "IN4MSorterAlg.h"
+#include "egammaEvent/ElectronContainer.h"
+
+
+namespace D3PD {
+
+
+/**
+ * @brief Recalculate OQ flags for Electron objects.
+ */
+class ElectronSorterAlg
+  : public IN4MSorterAlg<ElectronContainer>
+{
+public:
+  /**
+   * @brief Standard Gaudi algorithm constructor.
+   * @param name The algorithm name.
+   * @param svcloc The service locator.
+   */
+  ElectronSorterAlg (const std::string& name,
+                     ISvcLocator* svcloc);
+
+};
+
+
+} // namespace D3PD
+
+
+#endif // not PHOTOND3PDMAKER_ELECTRONSORTERALG_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/GSFOriginalTrackParticleAssociationTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/GSFOriginalTrackParticleAssociationTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..f3070cd4b0a492ba3ec0e55dbba7d81365c696c5
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/GSFOriginalTrackParticleAssociationTool.cxx
@@ -0,0 +1,88 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id $
+/**
+ * @file egammaD3PDMaker/src/GSFOriginalTrackParticleAssociationTool.cxx
+ * @author Mike Hance <mike.hance@cern.ch>
+ * @date March, 2012
+ * @brief Associate from a GSF fitted track to the original trackparticle
+ */
+
+
+#include "GSFOriginalTrackParticleAssociationTool.h"
+#include "D3PDMakerInterfaces/IObjGetterTool.h"
+#include "ParticleEvent/TrackParticleAssocs.h"
+#include "AthenaKernel/errorcheck.h"
+
+
+namespace D3PD {
+
+
+/**
+ * @brief Standard Gaudi tool constructor.
+ * @param type The name of the tool type.
+ * @param name The tool name.
+ * @param parent The tool's Gaudi parent.
+ */
+GSFOriginalTrackParticleAssociationTool::GSFOriginalTrackParticleAssociationTool
+  (const std::string& type,
+   const std::string& name,
+   const IInterface* parent)
+    : Base (type, name, parent),
+      m_assocGetter (this)
+{
+  declareProperty ("AssocGetter", m_assocGetter,
+		   "Getter for the association object.");
+}
+
+
+/**
+ * @brief Standard Gaudi initialize method.
+ */
+StatusCode GSFOriginalTrackParticleAssociationTool::initialize()
+{
+  CHECK( Base::initialize() );
+  CHECK( m_assocGetter.retrieve() );
+  CHECK( m_assocGetter->configureD3PD<TrackParticleAssocs> () );
+  return StatusCode::SUCCESS;
+}
+
+
+/**
+ * @brief Return the target object.
+ * @param p The source object for the association.
+ *
+ * Return the target of the association, or 0.
+ */
+const Rec::TrackParticle*
+GSFOriginalTrackParticleAssociationTool::get (const Rec::TrackParticle& track)
+{
+
+  if (track.info().trackFitter() != Trk::TrackInfo::GaussianSumFilter)
+    return &track;
+
+  const TrackParticleAssocs* assocs = m_assocGetter->get<TrackParticleAssocs>();
+  if (!assocs) {
+    REPORT_MESSAGE (MSG::WARNING) << "Can't find GSF track association.";
+    return &track;
+  }
+
+  TrackParticleAssocs::asso_iterator beg = assocs->beginAssociation (&track);
+  TrackParticleAssocs::asso_iterator end = assocs->endAssociation (&track);
+  const Rec::TrackParticle* ret = 0;
+  if (beg != end && beg.isValid())
+    ret = dynamic_cast<const Rec::TrackParticle*> (*beg);
+  m_assocGetter->releaseObject (assocs);
+  if (!ret) {
+    REPORT_MESSAGE (MSG::WARNING)
+      << "Can't find original track for GSF refitted track.";
+    return &track;
+  }
+
+  return ret;
+}
+
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/GSFOriginalTrackParticleAssociationTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/GSFOriginalTrackParticleAssociationTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..1850d524628a815ffa1f420e31a5972ac01ad08b
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/GSFOriginalTrackParticleAssociationTool.h
@@ -0,0 +1,75 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id $
+/**
+ * @file egammaD3PDMaker/src/GSFOriginalTrackParticleAssociationTool.h
+ * @author Mike Hance <mike.hance@cern.ch>
+ * @date March, 2012
+ * @brief Associate from a GSF fitted track to the original trackparticle
+ */
+
+
+#ifndef EGAMMAD3PDMAKER_GSFOLDTRACKPARTICLEASSOCIATIONTOOL_H
+#define EGAMMAD3PDMAKER_GSFOLDTRACKPARTICLEASSOCIATIONTOOL_H
+
+
+#include "D3PDMakerUtils/SingleAssociationTool.h"
+#include "GaudiKernel/ToolHandle.h"
+
+namespace Rec {
+  class TrackParticle;
+}
+
+
+namespace D3PD {
+
+class IObjGetterTool;
+
+
+/**
+ * @brief Associate from a GSF fitted track to the original trackparticle
+ */
+class GSFOriginalTrackParticleAssociationTool
+  : public SingleAssociationTool<Rec::TrackParticle, Rec::TrackParticle>
+{
+public:
+  typedef SingleAssociationTool<Rec::TrackParticle, Rec::TrackParticle> Base;
+
+
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  GSFOriginalTrackParticleAssociationTool (const std::string& type,
+					   const std::string& name,
+					   const IInterface* parent);
+
+
+  /// @brief Standard Gaudi initialize method.
+  virtual StatusCode initialize();
+
+  /**
+   * @brief Return the target object.
+   * @param p The source object for the association.
+   *
+   * Return the target of the association, or 0.
+   */
+  virtual const Rec::TrackParticle* get (const Rec::TrackParticle& track);
+
+private:
+  /// Property: Getter for the association object.
+  ToolHandle<IObjGetterTool> m_assocGetter;
+};
+
+
+} // namespace D3PD
+
+
+
+#endif // not EGAMMAD3PDMAKER_GSFORIGINALTRACKPARTICLEASSOCIATIONTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/IN4MSorterAlg.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/IN4MSorterAlg.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..9e3c3b34937a93356c3e0a47cb117d24831b9ed7
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/IN4MSorterAlg.cxx
@@ -0,0 +1,79 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/IN4MSorterAlg.cxx
+ * @author Mike Hance
+ * @date Feb, 2011
+ * @brief This is a template class, and can't be used directly as an Algorithm.
+ *        Derive a non-templated class from this to actually use.
+ */
+
+
+#include "IN4MSorterAlg.h"
+#include "D3PDMakerInterfaces/ICollectionGetterTool.h"
+#include "egammaEvent/egamma.h"
+#include "AthenaKernel/errorcheck.h"
+
+
+namespace D3PD {
+
+
+/**
+ * @brief Standard Gaudi algorithm constructor.
+ * @param name The algorithm name.
+ * @param svcloc The service locator.
+ */
+IN4MSorterAlgBase::IN4MSorterAlgBase (const std::string& name,
+                                          ISvcLocator* svcloc)
+  : AthAlgorithm (name, svcloc),
+    m_getter (this)
+{
+  declareProperty ("OutputKey", m_outputkey,
+                   "SG key for output container.");
+
+  declareProperty ("Getter", m_getter,
+                   "Getter instance for the input egamma objects.");
+}
+
+
+/**
+ * @brief Standard Gaudi @c initialize method.
+ */
+StatusCode IN4MSorterAlgBase::initialize()
+{
+  CHECK( AthAlgorithm::initialize() );
+  CHECK( m_getter.retrieve() );
+  CHECK( m_getter->configureD3PD<INavigable4Momentum>() );
+
+  return StatusCode::SUCCESS;
+}
+
+
+/**
+ * @brief Standard Gaudi execute method.
+ */
+StatusCode IN4MSorterAlgBase::execute()
+{
+  CHECK (m_getter->reset() );
+
+  while (const INavigable4Momentum* in4m = m_getter->next<INavigable4Momentum>()) {
+    CHECK (this->addElement(in4m));
+  }
+
+  CHECK (this->commit());
+
+  return StatusCode::SUCCESS;
+}
+
+
+bool IN4MEtSort::operator()(const INavigable4Momentum* a,
+			    const INavigable4Momentum* b){
+  volatile double apt = a->pt();
+  volatile double bpt = b->pt();
+  return bpt < apt;
+}
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/IN4MSorterAlg.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/IN4MSorterAlg.h
new file mode 100644
index 0000000000000000000000000000000000000000..763b76f6c63d4a31e622723bdc65428ea956e080
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/IN4MSorterAlg.h
@@ -0,0 +1,123 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file egammaD3PDAnalysis/src/egammaRedoOQAlg.h
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Dec, 2010
+ * @brief Recalculate OQ flags for Electron objects.
+ *        This is a template class, and can't be used directly as an Algorithm.
+ *        Derive a non-templated class from this to actually use.
+ */
+
+
+#ifndef PHOTOND3PDMAKER_IN4MSORTERALG_H
+#define PHOTOND3PDMAKER_IN4MSORTERALG_H
+
+
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "D3PDMakerInterfaces/ICollectionGetterTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include <string>
+
+
+class INavigable4Momentum;
+
+namespace D3PD {
+
+
+class ICollectionGetterTool;
+
+class IN4MEtSort{
+public:
+  inline IN4MEtSort () {};
+  bool operator() (const INavigable4Momentum* a,
+		   const INavigable4Momentum* b);
+};
+
+
+/**
+ * @brief Helper, to factor out non-template dependent code.
+ *        Don't use this directly.
+ */
+class IN4MSorterAlgBase
+  : public AthAlgorithm
+{
+public:
+  /**
+   * @brief Standard Gaudi algorithm constructor.
+   * @param name The algorithm name.
+   * @param svcloc The service locator.
+   */
+  IN4MSorterAlgBase (const std::string& name,
+		     ISvcLocator* svcloc);
+
+
+  /// Standard Gaudi initialize method.
+  StatusCode initialize();
+
+
+  /// Standard Gaudi execute method.
+  StatusCode execute();
+
+protected:
+  /// Store the output list in SG.
+  virtual StatusCode commit () = 0;
+
+
+  /// Property: SG key for output container.
+  std::string m_outputkey;
+
+  /// Store the element in the output list
+  virtual StatusCode addElement(const INavigable4Momentum* ptr) = 0;
+
+private:
+  /// Property: Getter for input egamma objects.
+  ToolHandle<ICollectionGetterTool> m_getter;
+};
+
+
+/**
+ * @brief Recalculate OQ flags for Electron objects.
+ *        This is a template class, and can't be used directly as an Algorithm.
+ *        Derive a non-templated class from this to actually use.
+ */
+template <typename CONT>
+class IN4MSorterAlg
+  : public IN4MSorterAlgBase
+{
+public:
+  /**
+   * @brief Standard Gaudi algorithm constructor.
+   * @param name The algorithm name.
+   * @param svcloc The service locator.
+   */
+  IN4MSorterAlg (const std::string& name,
+                   ISvcLocator* svcloc);
+
+
+protected:
+  typedef typename CONT::base_value_type Element;
+
+
+  /// Store the output list in SG.
+  virtual StatusCode commit ();
+
+  /// Store the element in the output list
+  virtual StatusCode addElement(const INavigable4Momentum* ptr);
+
+private:
+  /// The output list being accumulated.
+  CONT* m_outlist;
+};
+
+}
+
+
+#include "IN4MSorterAlg.icc"
+
+#endif // not PHOTOND3PDMAKER_IN4MSORTERALG_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/IN4MSorterAlg.icc b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/IN4MSorterAlg.icc
new file mode 100644
index 0000000000000000000000000000000000000000..12e223acea30de1ec9659143dd073bd7940300f5
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/IN4MSorterAlg.icc
@@ -0,0 +1,76 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/IN4MSorterAlg.icc
+ * @author Mike Hance
+ * @date Feb, 2011
+ * @brief This is a template class, and can't be used directly as an Algorithm.
+ *        Derive a non-templated class from this to actually use.
+ */
+
+
+#include <functional>
+#include "DataModel/OwnershipPolicy.h"
+#include "AthenaKernel/errorcheck.h"
+
+
+namespace D3PD {
+
+
+/**
+ * @brief Standard Gaudi algorithm constructor.
+ * @param name The algorithm name.
+ * @param svcloc The service locator.
+ */
+template <typename CONT>
+IN4MSorterAlg<CONT>::IN4MSorterAlg (const std::string& name,
+                                        ISvcLocator* svcloc)
+  : IN4MSorterAlgBase (name, svcloc),
+    m_outlist (0)
+{
+}
+
+
+/**
+ * @brief Store the element in the output list
+ */
+template <typename CONT>
+StatusCode IN4MSorterAlg<CONT>::addElement (const INavigable4Momentum* ptr)
+{
+
+  const Element* elt = dynamic_cast<const Element*>(ptr);
+
+  if (!m_outlist)
+    m_outlist = new CONT(SG::VIEW_ELEMENTS);
+
+  m_outlist->push_back(elt);
+
+  return StatusCode::SUCCESS;
+}
+
+
+/**
+ * @brief Store the output list in SG.
+ */
+template <typename CONT>
+StatusCode IN4MSorterAlg<CONT>::commit ()
+{
+  if (!m_outlist)
+    m_outlist = new CONT;
+  else{
+    IN4MEtSort comp;
+    m_outlist->sort(comp);
+  }
+
+  CHECK( evtStore()->record (m_outlist, m_outputkey) );
+  
+  m_outlist = 0;
+  return StatusCode::SUCCESS;
+}
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/NeutralPerigeeCovarianceAssociationTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/NeutralPerigeeCovarianceAssociationTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..d07a4df5cbed66fcb83b0ae3982627b648d65138
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/NeutralPerigeeCovarianceAssociationTool.cxx
@@ -0,0 +1,44 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: NeutralPerigeeCovarianceAssociationTool.cxx
+/**
+ * @file PhotonD3PDMaker/src/NeutralPerigeeCovarianceAssociationTool.cxx
+ * @author Jean-Francois Marchand <jean-francois.marchadn@cern.ch>
+ * @date Nov, 2012
+ * @brief Associate from a NeutralPerigee to its covariance matrix.
+ */
+
+#include "NeutralPerigeeCovarianceAssociationTool.h"
+#include "AthenaKernel/errorcheck.h"
+
+
+namespace D3PD {
+
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  NeutralPerigeeCovarianceAssociationTool::NeutralPerigeeCovarianceAssociationTool
+  (const std::string& type,
+   const std::string& name,
+   const IInterface* parent)
+    : Base (type, name, parent)
+  {
+  }
+  
+  /**
+   * @brief Return the target object.
+   * @param p The source object for the association.
+   *
+   * Return the target of the association, or 0.
+   */
+   const AmgSymMatrix(5) *NeutralPerigeeCovarianceAssociationTool::get (const Trk::NeutralPerigee& p)
+   {
+     return p.covariance();
+   }
+  
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/NeutralPerigeeCovarianceAssociationTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/NeutralPerigeeCovarianceAssociationTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..46931bf511226cdbd301421eacf22aa89107f64e
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/NeutralPerigeeCovarianceAssociationTool.h
@@ -0,0 +1,57 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: NeutralPerigeeCovarianceAssociationTool.h
+/**
+ * @file PhotonD3PDMaker/src/PerigeeCovarianceAssociationTool.h
+ * @author Jean-Francois Marchadn <jean-francois.marchand@cern.ch>
+ * @date Nov, 2012
+ * @brief Associate from a NeutralPerigee to its ErrorMatrix.
+ */
+#ifndef PHOTOND3PDMAKER_NEUTRALPERIGEECOVARIANCEASSOCIATIONTOOL_H
+#define PHOTOND3PDMAKER_NEUTRALPERIGEECOVARIANCEASSOCIATIONTOOL_H
+
+#include "D3PDMakerUtils/SingleAssociationTool.h"
+#include "TrkNeutralParameters/NeutralParameters.h"
+
+
+namespace D3PD {
+
+  /**
+   * @brief Associate from a Perigee to its ErrorMatrix.
+   */
+  class NeutralPerigeeCovarianceAssociationTool
+    : public SingleAssociationTool<Trk::NeutralPerigee, AmgSymMatrix(5)>
+    {
+    public:
+      typedef SingleAssociationTool<Trk::NeutralPerigee, AmgSymMatrix(5)> Base;
+      
+      /**
+       * @brief Standard Gaudi tool constructor.
+       * @param type The name of the tool type.
+       * @param name The tool name.
+       * @param parent The tool's Gaudi parent.
+       */
+      NeutralPerigeeCovarianceAssociationTool (const std::string& type,
+					       const std::string& name,
+					       const IInterface* parent);
+      
+      
+      /**
+       * @brief Return the target object.
+       * @param p The source object for the association.
+       *
+       * Return the target of the association, or 0.
+       */
+      virtual const AmgSymMatrix(5)* get (const Trk::NeutralPerigee& p);
+    };
+  
+  
+} // namespace D3PD
+
+
+
+#endif // not PHOTOND3PDMAKER_NEUTRALPERIGEECOVARIANCEASSOCIATIONTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/NeutralPerigeeFillerTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/NeutralPerigeeFillerTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..a22aae2b0b531acbad45209b147b533ae8de59a3
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/NeutralPerigeeFillerTool.cxx
@@ -0,0 +1,77 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "NeutralPerigeeFillerTool.h"
+#include "AthenaKernel/errorcheck.h"
+
+namespace D3PD {
+
+
+NeutralPerigeeFillerTool::NeutralPerigeeFillerTool (const std::string& type,
+						    const std::string& name,
+						    const IInterface* parent)
+  : D3PD::BlockFillerTool<Trk::NeutralPerigee> (type, name, parent)
+{
+  // Avoid coverity warnings.
+  m_fillPerigee = true;
+  m_fillMomentum = true;
+  m_fillThetaAndQoverP = true;
+  m_fillPhi = true;
+  book().ignore();
+
+  declareProperty ("FillPerigee", m_fillPerigee=true);
+  declareProperty ("FillMomentum", m_fillMomentum=false);
+  declareProperty ("FillThetaAndQoverP", m_fillThetaAndQoverP=true);
+  declareProperty ("FillPhi", m_fillPhi=true,
+                   "Should the phi variable be filled?");
+  declareProperty ("DefaultValue", m_defaultValue=0,
+                   "Default value to which to set unfilled variables.");
+}
+
+StatusCode NeutralPerigeeFillerTool::book()
+{
+  // track parameters at perigee
+  if(m_fillPerigee){
+    CHECK( addVariable ("d0", m_d0, "", m_defaultValue) );
+    CHECK( addVariable ("z0", m_z0, "", m_defaultValue) );
+    if (m_fillPhi)
+      CHECK( addVariable ("phi", m_phi, "", m_defaultValue) );
+    if(m_fillThetaAndQoverP){
+      CHECK( addVariable ("theta", m_theta, "", m_defaultValue) );
+      CHECK( addVariable ("qoverp", m_qoverp, "", m_defaultValue) );
+    }
+  }
+
+  if(m_fillMomentum){
+    CHECK( addVariable ("pt", m_pt, "", m_defaultValue) );
+    CHECK( addVariable ("eta", m_eta, "", m_defaultValue) );
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode NeutralPerigeeFillerTool::fill (const Trk::NeutralPerigee& perigee)
+{
+  // track parameters at perigee
+  if(m_fillPerigee){
+    *m_d0 = perigee.parameters()[Trk::d0];
+    *m_z0 = perigee.parameters()[Trk::z0];
+    if (m_fillPhi)
+      *m_phi = perigee.parameters()[Trk::phi0];
+    if(m_fillThetaAndQoverP){
+      *m_theta = perigee.parameters()[Trk::theta];
+      *m_qoverp = perigee.parameters()[Trk::qOverP];
+    }
+  }
+
+  if(m_fillMomentum){
+    *m_pt = perigee.pT();
+    *m_eta = perigee.eta();
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/NeutralPerigeeFillerTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/NeutralPerigeeFillerTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..5539e1c4345f5e4ba13643967a82add92ca41764
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/NeutralPerigeeFillerTool.h
@@ -0,0 +1,54 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef PHOTOND3PDMAKER_NEUTRALPERIGEEFILLERTOOL_H
+#define PHOTOND3PDMAKER_NEUTRALPERIGEEFILLERTOOL_H
+
+#include "D3PDMakerUtils/BlockFillerTool.h"
+#include "TrkNeutralParameters/NeutralParameters.h"
+
+
+namespace D3PD {
+  
+  class NeutralPerigeeFillerTool
+    : public D3PD::BlockFillerTool<Trk::NeutralPerigee>
+  {
+  public:
+    NeutralPerigeeFillerTool (const std::string& type,
+			      const std::string& name,
+			      const IInterface* parent);
+    
+    virtual StatusCode book();
+    
+    virtual StatusCode fill (const Trk::NeutralPerigee &p);
+    
+  private:
+    
+    bool m_fillMomentum;
+    bool m_fillPerigee;
+    bool m_fillThetaAndQoverP;
+    
+    /// Parameter: Should the phi variable be filled?
+    bool m_fillPhi;
+      
+    /// Parameter: Value to which to set variables if they don't get filled.
+    float m_defaultValue;
+      
+    /* NTuple variables: **/
+    // track parameters at perigee
+    float *m_d0;
+    float *m_z0;
+    float *m_phi;
+    float *m_theta;
+    float *m_qoverp;
+    
+    // momentum
+    float *m_pt;
+    float *m_eta;
+    
+  }; // class NeutralPerigeeFillerTool
+  
+} // namespace D3PD
+
+#endif // not PHOTOND3PDMAKER_NEUTRALPERIGEEFILLERTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUConversionFillerTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUConversionFillerTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..d47c574ce3ea83d5e2acae6efad2af57a07ce7a6
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUConversionFillerTool.cxx
@@ -0,0 +1,168 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/PAUConversionFillerTool.h
+ * @author Mike Hance <hance@hep.upenn.edu>
+ * @date January, 2011
+ * @brief Fill PAU related variables
+ */
+
+
+#include "PAUConversionFillerTool.h"
+#include "AthenaKernel/errorcheck.h"
+
+#include "PhotonAnalysisUtils/PAUegamma.h"
+
+namespace D3PD {
+
+
+/**
+ * @brief Standard Gaudi tool constructor.
+ * @param type The name of the tool type.
+ * @param name The tool name.
+ * @param parent The tool's Gaudi parent.
+ */
+PAUConversionFillerTool::PAUConversionFillerTool (const std::string& type,
+						  const std::string& name,
+						  const IInterface* parent)
+  : BlockFillerTool<PAU::egamma> (type, name, parent)
+{
+  book().ignore(); // Avoid coverity warnings.
+}
+
+
+/**
+ * @brief Book variables for this block.
+ */
+StatusCode PAUConversionFillerTool::book()
+{
+  CHECK( addVariable ("convTrk1_chi2"               , m_convTrk1_chi2 	              ) );
+  CHECK( addVariable ("convTrk2_chi2"               , m_convTrk2_chi2      	      ) );
+  CHECK( addVariable ("convTrk1_expectHitInBLayer"  , m_convTrk1_expectHitInBLayer    ) );
+  CHECK( addVariable ("convTrk1_numTRTOutliers"     , m_convTrk1_numTRTOutliers       ) );
+  CHECK( addVariable ("convTrk1_numTRTHTHits"       , m_convTrk1_numTRTHTHits         ) );
+  CHECK( addVariable ("convTrk1_numTRTHTOutliers"   , m_convTrk1_numTRTHTOutliers     ) );
+  CHECK( addVariable ("convTrk2_expectHitInBLayer"  , m_convTrk2_expectHitInBLayer    ) );
+  CHECK( addVariable ("convTrk2_numTRTOutliers"     , m_convTrk2_numTRTOutliers       ) );
+  CHECK( addVariable ("convTrk2_numTRTHTHits"       , m_convTrk2_numTRTHTHits         ) );
+  CHECK( addVariable ("convTrk2_numTRTHTOutliers"   , m_convTrk2_numTRTHTOutliers     ) );
+  CHECK( addVariable ("convTrk1_trtPID"             , m_convTrk1_trtPID 	      ) );
+  CHECK( addVariable ("convTrk2_trtPID"             , m_convTrk2_trtPID 	      ) );
+  CHECK( addVariable ("convTrk1_trtPIDHT"           , m_convTrk1_trtPIDHT 	      ) );
+  CHECK( addVariable ("convTrk2_trtPIDHT"           , m_convTrk2_trtPIDHT 	      ) );
+  CHECK( addVariable ("convTrk1_trtPIDToT"          , m_convTrk1_trtPIDToT 	      ) );
+  CHECK( addVariable ("convTrk2_trtPIDToT"          , m_convTrk2_trtPIDToT 	      ) );
+  CHECK( addVariable ("convTrk1_ToTvar"             , m_convTrk1_ToTvar 	      ) );
+  CHECK( addVariable ("convTrk2_ToTvar"             , m_convTrk2_ToTvar 	      ) );
+  CHECK( addVariable ("convTrk1_trtRatioHT"         , m_convTrk1_trtRatioHT 	      ) );
+  CHECK( addVariable ("convTrk2_trtRatioHT"         , m_convTrk2_trtRatioHT 	      ) );
+  CHECK( addVariable ("convTrk1_charge"             , m_convTrk1_charge 	      ) );
+  CHECK( addVariable ("convTrk2_charge"             , m_convTrk2_charge 	      ) );
+  CHECK( addVariable ("convTrk1_DeltaEta_track_calo", m_convTrk1_DeltaEta_track_calo  ) );
+  CHECK( addVariable ("convTrk2_DeltaEta_track_calo", m_convTrk2_DeltaEta_track_calo  ) );
+  CHECK( addVariable ("convTrk1_DeltaPhi_track_calo", m_convTrk1_DeltaPhi_track_calo  ) );
+  CHECK( addVariable ("convTrk2_DeltaPhi_track_calo", m_convTrk2_DeltaPhi_track_calo  ) );
+
+  CHECK( addVariable ("XConv"                       , m_XConv                         ) );
+  CHECK( addVariable ("YConv"                       , m_YConv                         ) );
+  CHECK( addVariable ("conv_chi2"                   , m_conv_chi2 		      ) );
+  CHECK( addVariable ("conv_dcottheta"              , m_conv_dcottheta 	              ) );
+  CHECK( addVariable ("conv_dphi"                   , m_conv_dphi 		      ) );
+  CHECK( addVariable ("conv_dist"                   , m_conv_dist 		      ) );
+  CHECK( addVariable ("conv_DR1R2"                  , m_conv_DR1R2 		      ) );
+  CHECK( addVariable ("conv_p"                      , m_conv_p        		      ) );
+  CHECK( addVariable ("conv_phi"                    , m_conv_phi       		      ) );
+  CHECK( addVariable ("conv_theta"                  , m_conv_theta     		      ) );
+  CHECK( addVariable ("conv_perr"                   , m_conv_perr     		      ) );
+  CHECK( addVariable ("conv_phierr"                 , m_conv_phierr    		      ) );
+  CHECK( addVariable ("conv_thetaerr"               , m_conv_thetaerr  		      ) );
+  CHECK( addVariable ("conv_GSF_p"                  , m_conv_GSF_p    		      ) );
+  CHECK( addVariable ("conv_GSF_phi"                , m_conv_GSF_phi   		      ) );
+  CHECK( addVariable ("conv_GSF_theta"              , m_conv_GSF_theta 		      ) );
+  CHECK( addVariable ("conv_GSF_perr"               , m_conv_GSF_perr 		      ) );
+  CHECK( addVariable ("conv_GSF_phierr"             , m_conv_GSF_phierr		      ) );
+  CHECK( addVariable ("conv_GSF_thetaerr"           , m_conv_GSF_thetaerr             ) );
+  CHECK( addVariable ("conv_DNA_p"                  , m_conv_DNA_p    		      ) );
+  CHECK( addVariable ("conv_DNA_phi"                , m_conv_DNA_phi   		      ) );
+  CHECK( addVariable ("conv_DNA_theta"              , m_conv_DNA_theta 		      ) );
+  CHECK( addVariable ("conv_DNA_perr"               , m_conv_DNA_perr 		      ) );
+  CHECK( addVariable ("conv_DNA_phierr"             , m_conv_DNA_phierr		      ) );
+  CHECK( addVariable ("conv_DNA_thetaerr"           , m_conv_DNA_thetaerr             ) );
+
+  return StatusCode::SUCCESS;
+}
+
+
+/**
+ * @brief Fill one block --- type-safe version.
+ * @param p The input object.
+ *
+ * This is called once per object.  The caller
+ * is responsible for arranging that all the pointers for booked variables
+ * are set appropriately upon entry.
+ */
+StatusCode PAUConversionFillerTool::fill (const PAU::egamma& p)
+{
+
+  * m_convTrk1_chi2 	           = p.convTrk1_chi2 	            ;
+  * m_convTrk2_chi2      	   = p.convTrk2_chi2      	    ;
+  * m_convTrk1_expectHitInBLayer   = p.convTrk1_expectHitInBLayer   ;
+  * m_convTrk1_numTRTOutliers      = p.convTrk1_numTRTOutliers      ;
+  * m_convTrk1_numTRTHTHits        = p.convTrk1_numTRTHTHits        ;
+  * m_convTrk1_numTRTHTOutliers    = p.convTrk1_numTRTHTOutliers    ;
+  * m_convTrk2_expectHitInBLayer   = p.convTrk2_expectHitInBLayer   ;
+  * m_convTrk2_numTRTOutliers      = p.convTrk2_numTRTOutliers      ;
+  * m_convTrk2_numTRTHTHits        = p.convTrk2_numTRTHTHits        ;
+  * m_convTrk2_numTRTHTOutliers    = p.convTrk2_numTRTHTOutliers    ;
+  * m_convTrk1_trtPID 	           = p.convTrk1_trtPID 	            ;
+  * m_convTrk2_trtPID 	           = p.convTrk2_trtPID 	            ;
+  * m_convTrk1_trtPIDHT 	   = p.convTrk1_trtPIDHT 	    ;
+  * m_convTrk2_trtPIDHT 	   = p.convTrk2_trtPIDHT 	    ;
+  * m_convTrk1_trtPIDToT 	   = p.convTrk1_trtPIDToT 	    ;
+  * m_convTrk2_trtPIDToT 	   = p.convTrk2_trtPIDToT 	    ;
+  * m_convTrk1_ToTvar 	           = p.convTrk1_ToTvar 	            ;
+  * m_convTrk2_ToTvar 	           = p.convTrk2_ToTvar 	            ;
+  * m_convTrk1_trtRatioHT 	   = p.convTrk1_trtRatioHT 	    ;
+  * m_convTrk2_trtRatioHT 	   = p.convTrk2_trtRatioHT 	    ;
+  * m_convTrk1_charge 	           = p.convTrk1_charge 	            ;
+  * m_convTrk2_charge 	           = p.convTrk2_charge 	            ;
+  * m_convTrk1_DeltaEta_track_calo = p.convTrk1_DeltaEta_track_calo ;
+  * m_convTrk2_DeltaEta_track_calo = p.convTrk2_DeltaEta_track_calo ;
+  * m_convTrk1_DeltaPhi_track_calo = p.convTrk1_DeltaPhi_track_calo ;
+  * m_convTrk2_DeltaPhi_track_calo = p.convTrk2_DeltaPhi_track_calo ;
+
+  * m_XConv                        = p.Xconv                        ;
+  * m_YConv                        = p.Yconv                        ;
+  * m_conv_chi2 		   = p.convChi2 		    ;
+  * m_conv_dcottheta 	           = p.convDcottheta 	            ;
+  * m_conv_dphi 		   = p.convDphi 		    ;
+  * m_conv_dist 		   = p.convDist 		    ;
+  * m_conv_DR1R2 		   = p.convDR1R2 		    ;
+  * m_conv_p    		   = p.convp    		    ;
+  * m_conv_phi    		   = p.convphi    		    ;
+  * m_conv_theta    		   = p.convtheta    		    ;
+  * m_conv_perr    		   = p.convperr    		    ;
+  * m_conv_phierr    		   = p.convphierr    		    ;
+  * m_conv_thetaerr    		   = p.convthetaerr    		    ;
+  * m_conv_GSF_p    		   = p.convp_GSF    		    ;
+  * m_conv_GSF_phi    		   = p.convphi_GSF    		    ;
+  * m_conv_GSF_theta   		   = p.convtheta_GSF   		    ;
+  * m_conv_GSF_perr   		   = p.convperr_GSF   		    ;
+  * m_conv_GSF_phierr  		   = p.convphierr_GSF  		    ;
+  * m_conv_GSF_thetaerr		   = p.convthetaerr_GSF		    ;
+  * m_conv_DNA_p    		   = p.convp_DNA    		    ;
+  * m_conv_DNA_phi    		   = p.convphi_DNA    		    ;
+  * m_conv_DNA_theta   		   = p.convtheta_DNA   		    ;
+  * m_conv_DNA_perr   		   = p.convperr_DNA   		    ;
+  * m_conv_DNA_phierr  		   = p.convphierr_DNA  		    ;
+  * m_conv_DNA_thetaerr		   = p.convthetaerr_DNA		    ;
+
+
+  return StatusCode::SUCCESS;
+}
+
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUConversionFillerTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUConversionFillerTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..ea8ec91978ed77558ab7ad57b4c44cd52e3c1824
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUConversionFillerTool.h
@@ -0,0 +1,126 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/PAUConversionFillerTool.h
+ * @author Mike Hance <hance@hep.upenn.edu>
+ * @date March, 2010
+ * @brief Fill PAU related variables
+ */
+
+
+#ifndef PHOTOND3PDMAKER_PAUCONVERSIONFILLERTOOL_H
+#define PHOTOND3PDMAKER_PAUCONVERSIONFILLERTOOL_H
+
+
+#include "D3PDMakerUtils/BlockFillerTool.h"
+#include <vector>
+#include <string>
+
+namespace PAU{
+  class egamma;
+}
+
+
+namespace D3PD {
+
+
+/**
+ * @brief Fill author code and related flags.
+ */
+class PAUConversionFillerTool
+  : public BlockFillerTool<PAU::egamma>
+{
+public:
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  PAUConversionFillerTool (const std::string& type,
+			   const std::string& name,
+			   const IInterface* parent);
+
+
+  /// Book variables for this block.
+  virtual StatusCode book();
+
+
+  /**
+   * @brief Fill one block --- type-safe version.
+   * @param p The input object.
+   *
+   * This is called once per object.  The caller
+   * is responsible for arranging that all the pointers for booked variables
+   * are set appropriately upon entry.
+   */
+  virtual StatusCode fill (const PAU::egamma& p);
+
+
+private:
+  float
+    * m_convTrk1_chi2, 
+    * m_convTrk2_chi2, 
+    * m_convTrk1_expectHitInBLayer, 
+    * m_convTrk1_numTRTOutliers, 
+    * m_convTrk1_numTRTHTHits, 
+    * m_convTrk1_numTRTHTOutliers, 
+    * m_convTrk2_expectHitInBLayer, 
+    * m_convTrk2_numTRTOutliers, 
+    * m_convTrk2_numTRTHTHits, 
+    * m_convTrk2_numTRTHTOutliers, 
+    * m_convTrk1_trtPID, 
+    * m_convTrk2_trtPID, 
+    * m_convTrk1_trtPIDHT, 
+    * m_convTrk2_trtPIDHT, 
+    * m_convTrk1_trtPIDToT, 
+    * m_convTrk2_trtPIDToT, 
+    * m_convTrk1_ToTvar, 
+    * m_convTrk2_ToTvar, 
+    * m_convTrk1_trtRatioHT, 
+    * m_convTrk2_trtRatioHT, 
+    * m_convTrk1_charge, 
+    * m_convTrk2_charge, 
+    * m_convTrk1_DeltaEta_track_calo, 
+    * m_convTrk2_DeltaEta_track_calo, 
+    * m_convTrk1_DeltaPhi_track_calo, 
+    * m_convTrk2_DeltaPhi_track_calo;
+
+  float 
+    * m_XConv,
+    * m_YConv,
+    * m_conv_chi2, 
+    * m_conv_dcottheta, 
+    * m_conv_dphi, 
+    * m_conv_dist, 
+    * m_conv_DR1R2, 
+    * m_conv_p, 
+    * m_conv_phi, 
+    * m_conv_theta,
+    * m_conv_perr,  
+    * m_conv_phierr,  
+    * m_conv_thetaerr,  
+    * m_conv_GSF_p, 
+    * m_conv_GSF_phi, 
+    * m_conv_GSF_theta,
+    * m_conv_GSF_perr,  
+    * m_conv_GSF_phierr,  
+    * m_conv_GSF_thetaerr,  
+    * m_conv_DNA_p, 
+    * m_conv_DNA_phi, 
+    * m_conv_DNA_theta,
+    * m_conv_DNA_perr,  
+    * m_conv_DNA_phierr,  
+    * m_conv_DNA_thetaerr;
+};
+
+
+} // namespace D3PD
+
+
+#endif // not PHOTOND3PDMAKER_PAUPHOTONFILLERTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUDiPhotonAssociationTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUDiPhotonAssociationTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..97eeb066983938be06ba825d88bb721ed8310807
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUDiPhotonAssociationTool.cxx
@@ -0,0 +1,82 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/PAUDiPhotonAssociationTool.cxx
+ * @author Mike Hance <hance@hep.upenn.edu>, based on similar tools by scott snyder <snyder@bnl.gov>
+ * @date August 2010
+ * @brief Associate PAU DiPhoton object to two photons
+ */
+
+
+#include "PAUDiPhotonAssociationTool.h"
+#include "EventKernel/INavigable4Momentum.h"
+#include "AthenaKernel/errorcheck.h"
+
+#include "egammaEvent/Photon.h"
+#include "PhotonAnalysisUtils/PAUDiPhoton.h"
+
+namespace D3PD {
+
+
+/**
+ * @brief Standard Gaudi tool constructor.
+ * @param type The name of the tool type.
+ * @param name The tool name.
+ * @param parent The tool's Gaudi parent.
+ */
+PAUDiPhotonAssociationTool::PAUDiPhotonAssociationTool (const std::string& type,
+							const std::string& name,
+							const IInterface* parent)
+  : Base (type, name, parent),
+    m_photonCounter (0),
+    m_photon_1 (0),
+    m_photon_2 (0)
+{
+}
+
+
+/**
+ * @brief Create any needed tuple variables.
+ */
+StatusCode PAUDiPhotonAssociationTool::reset (const PAU::DiPhoton& dp)
+{
+
+  const std::vector<PAU::egamma*>* photons = dp.getPhotons();
+  if(photons->size() != 2){
+    m_photon_1 = 0;
+    m_photon_2 = 0;
+  }
+  else{
+    m_photon_1 = photons->at(0);
+    m_photon_2 = photons->at(1);
+  }
+  m_photonCounter = 0;
+
+  return StatusCode::SUCCESS;
+}
+
+
+/**
+ * @brief Return the target object.
+ * @param p The source object for the association.
+ *
+ * Return the target of the association, or 0.
+ */
+const Analysis::Photon*
+PAUDiPhotonAssociationTool::next ()
+{
+  if(m_photonCounter > 1)
+    return 0;
+
+  m_photonCounter++;
+  if     (m_photonCounter == 1)   return m_photon_1->photon();
+  else if(m_photonCounter == 2)   return m_photon_2->photon();
+  
+  return 0;
+}
+
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUDiPhotonAssociationTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUDiPhotonAssociationTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..2a8ad2a5d1dfd28f9b8bb7a05223ac36db64c3df
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUDiPhotonAssociationTool.h
@@ -0,0 +1,87 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/PAUDiPhotonAssociationTool.h
+ * @author Mike Hance <hance@hep.upenn.edu>
+ * @date July, 2010
+ * @brief Associate PAU diphoton to photon objects
+ */
+
+
+#ifndef PHOTOND3PDMAKER_PAUDIPHOTONASSOCIATIONTOOL_H
+#define PHOTOND3PDMAKER_PAUDIPHOTONASSOCIATIONTOOL_H
+
+
+#include "D3PDMakerUtils/MultiAssociationTool.h"
+#include "GaudiKernel/ToolHandle.h"
+
+namespace PAU {
+  class egamma;
+  class DiPhoton;
+}
+
+namespace Analysis {
+  class Photon;
+}
+
+namespace D3PD {
+
+
+/**
+ * @brief Associate a PAU::DiPhoton to Analysis::Photons
+ *
+ * This is a multi-association tool.
+ * Given a @c PAU::DiPhoton object,
+ * return the single photon objects
+ *
+ * Parameters:
+ *  none
+ *
+ */
+class PAUDiPhotonAssociationTool
+  : public MultiAssociationTool<PAU::DiPhoton, Analysis::Photon>
+{
+public:
+  typedef MultiAssociationTool<PAU::DiPhoton, Analysis::Photon> Base;
+
+
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  PAUDiPhotonAssociationTool (const std::string& type,
+			      const std::string& name,
+			      const IInterface* parent);
+
+
+  /**
+   * @brief Start the iteration for a new association
+   */
+  virtual StatusCode reset(const PAU::DiPhoton& dp);
+
+
+  /**
+   * @brief Return a pointer to the next associated object
+   *
+   * Return the target of the association, or 0 if exhausted.
+   */
+  virtual const Analysis::Photon* next ();
+
+
+private:
+  unsigned int m_photonCounter;
+  const PAU::egamma* m_photon_1;
+  const PAU::egamma* m_photon_2;
+};
+
+
+} // namespace D3PD
+
+#endif // not PHOTOND3PDMAKER_PAUDIPHOTONASSOCIATIONTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUDiPhotonFillerTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUDiPhotonFillerTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..94f45ba4ab3051506f099da5661594a90ffe30d6
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUDiPhotonFillerTool.cxx
@@ -0,0 +1,317 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/PAUDiPhotonFillerTool.h
+ * @author Mike Hance <hance@hep.upenn.edu>
+ * @date August, 2010
+ * @brief Fill PAU related variables for diphotons
+ */
+
+
+#include "PAUDiPhotonFillerTool.h"
+#include "AthenaKernel/errorcheck.h"
+
+#include "PhotonAnalysisUtils/PAUDiPhoton.h"
+
+#include "VxVertex/VxContainer.h"
+#include "Particle/TrackParticleContainer.h"
+
+//#include "CaloUtils/CaloClusterVertexCorrection.h"
+#include "ParticleEvent/TrackParticleAssocs.h"
+
+namespace D3PD {
+
+
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  PAUDiPhotonFillerTool::PAUDiPhotonFillerTool (const std::string& type,
+						const std::string& name,
+						const IInterface* parent)
+    : BlockFillerTool<PAU::DiPhoton> (type, name, parent)
+      //,m_photonTrackIsolationTool( "TrackIsolationTool/EMTrackIsolationPhotonTrackIsolationTool" )
+  {
+    //declareProperty( "PhotonTrackIsolationTool", m_photonTrackIsolationTool, "the track isolation tool for photons" );
+    declareProperty( "TrackParticleContainerName", m_trackParticleContainerName="TrackParticleCandidate");
+    declareProperty( "VxPrimaryContainerName", m_vxPrimaryContainerName="VxPrimaryCandidate");
+    declareProperty( "TrackMapName", m_trackMapName="GSFTrackAssociation");
+    declareProperty( "UseDefaultPVForTrackIsol", m_useIDPV=false); //will use diphoton vertex if false
+    book().ignore(); // Avoid coverity warnings.
+  }
+  
+  PAUDiPhotonFillerTool::~PAUDiPhotonFillerTool()
+  {
+  }
+  
+  StatusCode PAUDiPhotonFillerTool::initialize()
+  {
+    //CHECK( m_photonTrackIsolationTool.retrieve() );  
+    return StatusCode::SUCCESS;
+  }
+  
+  /**
+   * @brief Book variables for this block.
+   */
+  StatusCode PAUDiPhotonFillerTool::book()
+  {
+    CHECK( addVariable ("fit_etaLead_zcommon"         , m_etaLead                     ) );
+    CHECK( addVariable ("fit_etaSublead_zcommon"      , m_etaSublead                  ) );
+    CHECK( addVariable ("fit_zcommon"                 , m_z                           ) );
+    CHECK( addVariable ("fit_sigma_zcommon"           , m_zres                        ) );
+    CHECK( addVariable ("fit_vtxLikelihood"           , m_vtxLikelihood               ) );
+    
+    CHECK( addVariable ("fit_mgg"                     , m_invmass                     ) );
+    CHECK( addVariable ("fit_mgg_trueDir"             , m_invmassTrueDir              ) );
+    CHECK( addVariable ("fit_mgg_trueE"               , m_invmassTrueE                ) );
+    CHECK( addVariable ("fit_fitFlag"                 , m_invmass_flag                ) );
+    
+    CHECK( addVariable ("fit_ptgg"                    , m_ptgg                        ) );
+    CHECK( addVariable ("fit_detagg"                  , m_detagg                      ) );
+    CHECK( addVariable ("fit_cosThetaStar"            , m_cosTh                       ) );
+    
+    
+    CHECK( addVariable ("onejet_cutStatus"            , m_onejet_cutStatus              ) );
+    CHECK( addVariable ("onejet_ok"                   , m_onejet_ok                     ) );
+    CHECK( addVariable ("onejet_mgg"                  , m_onejet_mgg                    ) );
+    CHECK( addVariable ("onejet_mggj"                 , m_onejet_mggj                   ) );
+    
+    CHECK( addVariable ("twojet_cutStatus"            , m_twojet_cutStatus              ) );
+    CHECK( addVariable ("twojet_ok"                   , m_twojet_ok                     ) );
+    CHECK( addVariable ("twojet_mgg"                  , m_twojet_mgg                    ) );
+    CHECK( addVariable ("twojet_mjj"                  , m_twojet_mjj                    ) );
+    
+    CHECK( addVariable ("HPV_zcommon"                      , m_hgg_HPV_zcommon ) );
+    CHECK( addVariable ("HPV_sigma_zcommon"                , m_hgg_HPV_sigma_zcommon ) );
+    CHECK( addVariable ("HPV_zcommon_primVtxLH"	         , m_hgg_HPV_zcommon_primVtxLH ) );
+    CHECK( addVariable ("HPV_zcommon_primVtxNN"	         , m_hgg_HPV_zcommon_primVtxNN ) );
+    CHECK( addVariable ("HPV_vtxLikelihood"	         , m_hgg_HPV_vtxLikelihood ) );
+    CHECK( addVariable ("HPV_etaLead_zcommon"	         , m_hgg_HPV_etaLead_zcommon ) );
+    CHECK( addVariable ("HPV_etaSublead_zcommon"	         , m_hgg_HPV_etaSublead_zcommon ) );
+    CHECK( addVariable ("HPV_mgg"  		         , m_hgg_HPV_invmass ) );
+    CHECK( addVariable ("HPV_etaLead_zcommon_primVtxLH"    , m_hgg_HPV_etaLead_zcommon_primVtxLH ) );
+    CHECK( addVariable ("HPV_etaSublead_zcommon_primVtxLH" , m_hgg_HPV_etaSublead_zcommon_primVtxLH ) );
+    CHECK( addVariable ("HPV_mgg_primVtxLH"	         , m_hgg_HPV_invmass_primVtxLH ) );
+    CHECK( addVariable ("HPV_mgg_Ztruth"  	         , m_hgg_HPV_invmass_Ztruth ) );
+    CHECK( addVariable ("HPV_ptgg"    		         , m_hgg_HPV_ptgg ) );
+    CHECK( addVariable ("HPV_detagg"  		         , m_hgg_HPV_detagg ) );
+    CHECK( addVariable ("HPV_dphigg"  		         , m_hgg_HPV_dphigg ) );
+    CHECK( addVariable ("HPV_cosTh"   		         , m_hgg_HPV_cosTh ) );
+    CHECK( addVariable ("HPV_cosThCS"                      , m_hgg_HPV_cosThCS ) );
+    
+    CHECK( addVariable ("ptcone20", m_hgg_ptcone20 ) );
+    CHECK( addVariable ("ptcone30", m_hgg_ptcone30 ) );
+    CHECK( addVariable ("ptcone40", m_hgg_ptcone40 ) );
+    
+    return StatusCode::SUCCESS;
+  }
+  
+  
+  /**
+   * @brief Fill one block --- type-safe version.
+   * @param p The input object.
+   *
+   * This is called once per object.  The caller
+   * is responsible for arranging that all the pointers for booked variables
+   * are set appropriately upon entry.
+   */
+  StatusCode PAUDiPhotonFillerTool::fill (const PAU::DiPhoton& p)
+  {
+    
+    *m_etaLead        = p.etaLead        ;
+    *m_etaSublead     = p.etaSublead     ;
+    *m_z              = p.z              ;
+    *m_zres           = p.zres           ;
+    *m_vtxLikelihood  = p.vtxLikelihood  ;
+    
+    *m_invmass        = p.invmass        ;
+    *m_invmassTrueDir = p.invmassTrueDir ;
+    *m_invmassTrueE   = p.invmassTrueE   ;
+    *m_invmass_flag   = p.invmass_flag   ;
+    
+    *m_ptgg           = p.ptgg           ;
+    *m_detagg         = p.detagg         ;
+    *m_cosTh          = p.cosTh          ;
+    
+    
+    *m_onejet_cutStatus    = p.onejet_cutStatus      ;
+    *m_onejet_ok           = p.onejet_ok             ;
+    *m_onejet_mgg          = p.onejet_mgg            ;
+    *m_onejet_mggj         = p.onejet_mggj           ;
+    
+    *m_twojet_cutStatus    = p.twojet_cutStatus      ;
+    *m_twojet_ok           = p.twojet_ok             ;
+    *m_twojet_mgg          = p.twojet_mgg            ;
+    *m_twojet_mjj          = p.twojet_mjj            ;
+    
+    *m_hgg_HPV_zcommon                      = p.hgg_HPV_zcommon;                        
+    *m_hgg_HPV_sigma_zcommon                = p.hgg_HPV_sigma_zcommon;                        
+    *m_hgg_HPV_zcommon_primVtxLH	    = p.hgg_HPV_zcommon_primVtxLH;              
+    *m_hgg_HPV_zcommon_primVtxNN	    = p.hgg_HPV_zcommon_primVtxNN;
+    *m_hgg_HPV_vtxLikelihood		    = p.hgg_HPV_vtxLikelihood;                  
+    *m_hgg_HPV_etaLead_zcommon		    = p.hgg_HPV_etaLead_zcommon;                
+    *m_hgg_HPV_etaSublead_zcommon 	    = p.hgg_HPV_etaSublead_zcommon;             
+    *m_hgg_HPV_invmass			    = p.hgg_HPV_invmass;                        
+    *m_hgg_HPV_etaLead_zcommon_primVtxLH    = p.hgg_HPV_etaLead_zcommon_primVtxLH;      
+    *m_hgg_HPV_etaSublead_zcommon_primVtxLH = p.hgg_HPV_etaSublead_zcommon_primVtxLH;   
+    *m_hgg_HPV_invmass_primVtxLH	    = p.hgg_HPV_invmass_primVtxLH;              
+    *m_hgg_HPV_invmass_Ztruth		    = p.hgg_HPV_invmass_Ztruth;                 
+    *m_hgg_HPV_ptgg    	  		    = p.hgg_HPV_ptgg    ;                       
+    *m_hgg_HPV_detagg  		  	    = p.hgg_HPV_detagg  ;                       
+    *m_hgg_HPV_dphigg  			    = p.hgg_HPV_dphigg  ;                       
+    *m_hgg_HPV_cosTh   			    = p.hgg_HPV_cosTh   ;                       
+    *m_hgg_HPV_cosThCS                      = p.hgg_HPV_cosThCS ;                         
+
+
+    /*
+    const std::vector<PAU::egamma*>* photonList = p.getPhotons();
+    
+    // list of track isolation energies (one for each cone)
+    std::vector<double> energies1;
+    std::vector<double> energies2;
+    std::vector<double> cones;
+    cones.push_back(0.2);
+    cones.push_back(0.3);
+    cones.push_back(0.4);
+
+    // correct for the primary vertex.
+    Amg::Vector3D originPos(0,0,0); 
+    const Rec::TrackParticleContainer* aTrackParticleContainer = 0;
+    CHECK( evtStore()->retrieve( aTrackParticleContainer , m_trackParticleContainerName ));  
+    
+    VxContainer newContainer (SG::OWN_ELEMENTS);
+    const VxContainer* vxTES = 0;
+    const Trk::VxCandidate *vx = 0;
+    if (m_useIDPV) {
+      CHECK( evtStore()->retrieve( vxTES , m_vxPrimaryContainerName ));
+      for (VxContainer::const_iterator it = vxTES->begin(); it != vxTES->end(); ++it) {
+	if ((*it)->vertexType() == Trk::PriVtx) {
+	  vx = *it;
+	  break;
+	}
+      }
+    } else {
+      vx = p.hgg_HPV_vertex;
+      if (vx) {
+	Trk::VxCandidate* vxCand = vx->clone();
+	vxCand->setVertexType(Trk::PriVtx);
+	newContainer.push_back(vxCand);
+	vxTES = &newContainer;
+      } else {
+	ATH_MSG_WARNING("No diphoton vertex found....");
+      }
+    }
+
+    //const Trk::Vertex *vertex = 0;
+    if (!vx) {
+      ATH_MSG_WARNING("Vertex container VxPrimaryCandidate has no vertex.");  
+    } else {
+      originPos = vx->recVertex().position();
+      //vertex = dynamic_cast<const Trk::Vertex *>(&(vx->recVertex()));
+    }
+    const CaloCluster* aCluster1 = photonList->at(0)->cluster();
+    const CaloCluster* aCluster2 = photonList->at(1)->cluster();
+        
+    //const Amg::Vector3D vect1(originPos);
+    //const Amg::Vector3D vect2(originPos);
+    //CaloClusterChangeVertexState mychange1(aCluster1, &vect1);
+    //CaloClusterChangeVertexState mychange2(aCluster2, &vect2);
+        
+    std::vector<Rec::TrackParticle*> aListOfTracks1;
+    const Trk::VxCandidate* vx1 = photonList->at(0)->photon()->conversion();
+    if (vx1) {
+      std::vector<Trk::VxTrackAtVertex*> trks1(*(vx1->vxTrackAtVertex()));
+      int numTracksAtVertex1 = trks1.size();
+      for (int i=0; i<numTracksAtVertex1; i++) {
+	Trk::VxTrackAtVertex* trk1 = trks1[i];
+	const Rec::TrackParticle *trkP1 = getTrackParticle(trk1);
+	const TrackParticleAssocs *trkassocs1 = 0;
+	CHECK( evtStore()->retrieve( trkassocs1 , m_trackMapName ));
+	Rec::TrackParticleContainer associatedElems1(SG::VIEW_ELEMENTS);
+	if (trkassocs1->assocs(trkP1,associatedElems1)) {
+	Rec::TrackParticle* trackP1 = associatedElems1.at(0);
+	if (trackP1) aListOfTracks1.push_back(trackP1);
+      }
+    }
+  }
+    m_photonTrackIsolationTool->trackIsolation( aCluster1, cones, energies1, TrackIsolPtType::summedPt, false,
+						0, 1.0, 0.0, aTrackParticleContainer, vxTES, &aListOfTracks1);
+
+
+  std::vector<Rec::TrackParticle*> aListOfTracks2;
+  const Trk::VxCandidate* vx2 = photonList->at(1)->photon()->conversion();
+  if (vx2) {
+    std::vector<Trk::VxTrackAtVertex*> trks2(*(vx2->vxTrackAtVertex()));
+    int numTracksAtVertex2 = trks2.size();
+    for (int i=0; i<numTracksAtVertex2; i++) {
+      Trk::VxTrackAtVertex* trk2 = trks2[i];
+      const Rec::TrackParticle *trkP2 = getTrackParticle(trk2);
+      const TrackParticleAssocs *trkassocs2 = 0;
+      CHECK( evtStore()->retrieve( trkassocs2 ,  m_trackMapName ));
+      Rec::TrackParticleContainer associatedElems2(SG::VIEW_ELEMENTS);
+      if (trkassocs2->assocs(trkP2,associatedElems2)) {
+	Rec::TrackParticle* trackP2 = associatedElems2.at(0);
+	if (trackP2) aListOfTracks2.push_back(trackP2);
+      }
+    }
+  }
+  m_photonTrackIsolationTool->trackIsolation( aCluster2, cones, energies2, TrackIsolPtType::summedPt, false,
+					      0, 1.0, 0.0, aTrackParticleContainer, vxTES, &aListOfTracks2);
+
+  std::vector<float> ptcone20, ptcone30, ptcone40;
+  ptcone20.push_back(energies1[0]); ptcone20.push_back(energies2[0]);
+  ptcone30.push_back(energies1[1]); ptcone30.push_back(energies2[1]);
+  ptcone40.push_back(energies1[2]); ptcone40.push_back(energies2[2]);
+  *m_hgg_ptcone20 = ptcone20;
+  *m_hgg_ptcone30 = ptcone30;
+  *m_hgg_ptcone40 = ptcone40;
+  ptcone20.clear();  
+  ptcone30.clear();  
+  ptcone40.clear();
+    */
+
+    // isolation tool doesn't exist anymore, fill empty values
+    std::vector<float> ptcone20, ptcone30, ptcone40;
+  ptcone20.push_back(0); ptcone20.push_back(0);
+  ptcone30.push_back(0); ptcone30.push_back(0);
+  ptcone40.push_back(0); ptcone40.push_back(0);
+  *m_hgg_ptcone20 = ptcone20;
+  *m_hgg_ptcone30 = ptcone30;
+  *m_hgg_ptcone40 = ptcone40;
+
+
+  return StatusCode::SUCCESS;
+  }
+  
+  /*
+  const Rec::TrackParticle* PAUDiPhotonFillerTool::getTrackParticle(Trk::VxTrackAtVertex *trkAtVx) 
+  {
+    // protection against bad pointers
+    if (trkAtVx==0) return 0;
+    
+    //find the link to the TrackParticleBase
+    const Trk::ITrackLink* trkLink = trkAtVx->trackOrParticleLink();
+    const Trk::TrackParticleBase* trkPB(0);
+    if (0!= trkLink) {
+      const Trk::LinkToTrackParticleBase* linktrkPB = dynamic_cast<const Trk::LinkToTrackParticleBase *>(trkLink);  
+      if (0!= linktrkPB) {
+	if (linktrkPB->isValid()) trkPB = linktrkPB->cachedElement(); 
+      }//end of dynamic_cast check
+    }//end of ITrackLink existance check
+    
+    //cast to TrackParticle
+    if (trkPB) {
+      const Rec::TrackParticle* trkP = dynamic_cast<const Rec::TrackParticle*>(trkPB);
+      return trkP;
+    } else {
+      return 0;
+    }
+  }
+  */
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUDiPhotonFillerTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUDiPhotonFillerTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..eaccf1bd96bde1ce0977deeba717e711d553e791
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUDiPhotonFillerTool.h
@@ -0,0 +1,137 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/PAUDiPhotonFillerTool.h
+ * @author Mike Hance <hance@hep.upenn.edu>
+ * @date August, 2010
+ * @brief Fill PAU related variables for diphotons
+ */
+
+
+#ifndef PHOTOND3PDMAKER_PAUDIPHOTONFILLERTOOL_H
+#define PHOTOND3PDMAKER_PAUDIPHOTONFILLERTOOL_H
+
+
+#include "D3PDMakerUtils/BlockFillerTool.h"
+#include <vector>
+#include <string>
+//#include "IsolationTool/IIsolationTool.h"
+#include "GaudiKernel/ToolHandle.h"
+
+
+namespace PAU{
+  class DiPhoton;
+}
+
+
+namespace D3PD {
+
+
+/**
+ * @brief Fill author code and related flags.
+ */
+class PAUDiPhotonFillerTool
+  : public BlockFillerTool<PAU::DiPhoton>
+{
+public:
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  PAUDiPhotonFillerTool (const std::string& type,
+			 const std::string& name,
+			 const IInterface* parent);
+
+
+  virtual ~PAUDiPhotonFillerTool();
+
+  StatusCode initialize();
+
+  /// Book variables for this block.
+  virtual StatusCode book();
+
+
+  /**
+   * @brief Fill one block --- type-safe version.
+   * @param p The input object.
+   *
+   * This is called once per object.  The caller
+   * is responsible for arranging that all the pointers for booked variables
+   * are set appropriately upon entry.
+   */
+  virtual StatusCode fill (const PAU::DiPhoton& p);
+
+
+private:
+
+  std::vector<float>   * m_etaLead               ;
+  std::vector<float>   * m_etaSublead            ;
+  std::vector<float>   * m_z                     ;
+  std::vector<float>   * m_zres                  ;
+  std::vector<float>   * m_vtxLikelihood         ;
+  std::vector<float>   * m_invmass               ;
+  std::vector<float>   * m_invmassTrueDir        ;
+  std::vector<float>   * m_invmassTrueE          ;
+  std::vector<int>     * m_invmass_flag          ;
+  std::vector<float>   * m_ptgg                  ;
+  std::vector<float>   * m_detagg                ;
+  std::vector<float>   * m_cosTh                 ;
+
+  int                  * m_onejet_cutStatus      ;
+  int                  * m_onejet_ok             ;
+  float                * m_onejet_mgg            ;
+  float                * m_onejet_mggj           ;
+  	                
+  int                  * m_twojet_cutStatus      ;
+  int                  * m_twojet_ok             ;
+  float                * m_twojet_mgg            ;
+  float                * m_twojet_mjj            ;
+  
+  float                *m_hgg_HPV_zcommon;
+  float                *m_hgg_HPV_sigma_zcommon;
+  float                *m_hgg_HPV_zcommon_primVtxLH;
+  float                *m_hgg_HPV_zcommon_primVtxNN;
+  float                *m_hgg_HPV_vtxLikelihood;
+  float                *m_hgg_HPV_etaLead_zcommon;
+  float                *m_hgg_HPV_etaSublead_zcommon;
+  float                *m_hgg_HPV_invmass;
+  float                *m_hgg_HPV_etaLead_zcommon_primVtxLH;
+  float                *m_hgg_HPV_etaSublead_zcommon_primVtxLH;
+  float                *m_hgg_HPV_invmass_primVtxLH;
+  float                *m_hgg_HPV_invmass_Ztruth;
+  float                *m_hgg_HPV_ptgg    ;
+  float                *m_hgg_HPV_detagg  ;
+  float                *m_hgg_HPV_dphigg  ;
+  float                *m_hgg_HPV_cosTh   ;
+  float                *m_hgg_HPV_cosThCS ;
+
+  std::vector<float>   *m_hgg_ptcone20 ;
+  std::vector<float>   *m_hgg_ptcone30 ;
+  std::vector<float>   *m_hgg_ptcone40 ;
+
+
+  /** @brief the TrackIsolationTool for photons*/
+  //ToolHandle<IIsolationTool> m_photonTrackIsolationTool;
+
+  std::string m_trackParticleContainerName;
+  std::string m_vxPrimaryContainerName;
+  std::string m_trackMapName;
+  bool m_useIDPV;
+  
+
+  //const Rec::TrackParticle* getTrackParticle(Trk::VxTrackAtVertex *trkAtVx);
+
+};
+
+
+} // namespace D3PD
+
+
+#endif // not EGAMMAD3PDMAKER_PAUFILLERTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUElectronFillerTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUElectronFillerTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..4f9ebdd1ae159b23a6052fff8f89a7742a70d5f4
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUElectronFillerTool.cxx
@@ -0,0 +1,64 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file egammaD3PDMaker/src/PAUElectronFillerTool.h
+ * @author Mike Hance <hance@hep.upenn.edu>
+ * @date March, 2010
+ * @brief Fill PAU related variables
+ */
+
+
+#include "PAUElectronFillerTool.h"
+#include "AthenaKernel/errorcheck.h"
+
+#include "PhotonAnalysisUtils/PAUegamma.h"
+
+namespace D3PD {
+
+
+/**
+ * @brief Standard Gaudi tool constructor.
+ * @param type The name of the tool type.
+ * @param name The tool name.
+ * @param parent The tool's Gaudi parent.
+ */
+PAUElectronFillerTool::PAUElectronFillerTool (const std::string& type,
+			      const std::string& name,
+			      const IInterface* parent)
+  : BlockFillerTool<PAU::egamma> (type, name, parent)
+{
+  book().ignore(); // Avoid coverity warnings.
+}
+
+
+/**
+ * @brief Book variables for this block.
+ */
+StatusCode PAUElectronFillerTool::book()
+{
+  CHECK( addVariable("ambiguityResult"				     , m_ambiguityResult			    ) );
+
+  return StatusCode::SUCCESS;
+}
+
+
+/**
+ * @brief Fill one block --- type-safe version.
+ * @param p The input object.
+ *
+ * This is called once per object.  The caller
+ * is responsible for arranging that all the pointers for booked variables
+ * are set appropriately upon entry.
+ */
+StatusCode PAUElectronFillerTool::fill (const PAU::egamma& p)
+{
+  * m_ambiguityResult			        = p.ambiguityResult			       ;
+
+  return StatusCode::SUCCESS;
+}
+
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUElectronFillerTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUElectronFillerTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..e11e4d4ef634d5b655af1af78734b0afd66d35fd
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUElectronFillerTool.h
@@ -0,0 +1,75 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file photonD3PDMaker/src/PAUElectronFillerTool.h
+ * @author Mike Hance <hance@hep.upenn.edu>
+ * @date March, 2010
+ * @brief Fill PAU related variables
+ */
+
+
+#ifndef PHOTOND3PDMAKER_PAUELECTRONFILLERTOOL_H
+#define PHOTOND3PDMAKER_PAUELECTRONFILLERTOOL_H
+
+
+#include "D3PDMakerUtils/BlockFillerTool.h"
+#include <vector>
+#include <string>
+
+namespace PAU{
+  class egamma;
+}
+
+
+namespace D3PD {
+
+
+/**
+ * @brief Fill author code and related flags.
+ */
+class PAUElectronFillerTool
+  : public BlockFillerTool<PAU::egamma>
+{
+public:
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  PAUElectronFillerTool (const std::string& type,
+			 const std::string& name,
+			 const IInterface* parent);
+
+
+  /// Book variables for this block.
+  virtual StatusCode book();
+
+
+  /**
+   * @brief Fill one block --- type-safe version.
+   * @param p The input object.
+   *
+   * This is called once per object.  The caller
+   * is responsible for arranging that all the pointers for booked variables
+   * are set appropriately upon entry.
+   */
+  virtual StatusCode fill (const PAU::egamma& p);
+
+
+private:
+
+  float * m_ambiguityResult;
+  
+};
+
+
+} // namespace D3PD
+
+
+#endif // not PHOTOND3PDMAKER_PAUELECTRONFILLERTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUFillerTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUFillerTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..40bf31fad86d3966d12364e0ab8051e82a662c6e
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUFillerTool.cxx
@@ -0,0 +1,124 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file egammaD3PDMaker/src/PAUFillerTool.h
+ * @author Mike Hance <hance@hep.upenn.edu>
+ * @date March, 2010
+ * @brief Fill PAU related variables
+ */
+
+
+#include "PAUFillerTool.h"
+#include "AthenaKernel/errorcheck.h"
+
+#include "PhotonAnalysisUtils/PAUegamma.h"
+
+namespace D3PD {
+
+
+/**
+ * @brief Standard Gaudi tool constructor.
+ * @param type The name of the tool type.
+ * @param name The tool name.
+ * @param parent The tool's Gaudi parent.
+ */
+PAUFillerTool::PAUFillerTool (const std::string& type,
+			      const std::string& name,
+			      const IInterface* parent)
+  : BlockFillerTool<PAU::egamma> (type, name, parent)
+{
+  m_fillPhotons = true;
+  m_fillPtCorrectedIsolation = 2;
+  book().ignore(); // Avoid coverity warnings.
+
+  declareProperty("FillPhotons"              , m_fillPhotons = true               , "If true, fill photon specific quantities"               );
+  declareProperty("FillPtCorrectedIsolation" , m_fillPtCorrectedIsolation = 1,
+                  "0: Don't fill any pt_corrected variables; "
+                  "1: Fill only Etcone40_pt_corrected; "
+                  "2: Fill all pt_corrected variables.");
+}
+
+
+/**
+ * @brief Book variables for this block.
+ */
+StatusCode PAUFillerTool::book()
+{
+  if(m_fillPhotons){
+
+    CHECK( addVariable ("convIP"                    , m_convIP                     ) );
+    CHECK( addVariable ("convIPRev"                 , m_convIPRev                  ) );
+
+    CHECK( addVariable ("ptIsolationCone"           , m_PtIsolationCone            ) );
+    CHECK( addVariable ("ptIsolationConePhAngle"    , m_PtIsolationConePhAngle     ) );
+  }
+
+  if (m_fillPtCorrectedIsolation) {
+    CHECK( addVariable ("Etcone40_pt_corrected", m_Etcone40_pt_corrected  ) );
+    if (m_fillPtCorrectedIsolation > 1) {
+      CHECK( addVariable ("Etcone35_pt_corrected", m_Etcone35_pt_corrected  ) );
+      CHECK( addVariable ("Etcone30_pt_corrected", m_Etcone30_pt_corrected  ) );
+      CHECK( addVariable ("Etcone25_pt_corrected", m_Etcone25_pt_corrected  ) );
+      CHECK( addVariable ("Etcone20_pt_corrected", m_Etcone20_pt_corrected  ) );
+      CHECK( addVariable ("Etcone15_pt_corrected", m_Etcone15_pt_corrected  ) );
+    }
+  }
+
+  CHECK( addVariable ("Etcone40_ED_corrected"       , m_Etcone40_ED_corrected      ) );
+  CHECK( addVariable ("Etcone40_corrected"          , m_Etcone40_corrected         ) );
+
+  return StatusCode::SUCCESS;
+}
+
+
+/**
+ * @brief Fill one block --- type-safe version.
+ * @param p The input object.
+ *
+ * This is called once per object.  The caller
+ * is responsible for arranging that all the pointers for booked variables
+ * are set appropriately upon entry.
+ */
+StatusCode PAUFillerTool::fill (const PAU::egamma& p)
+{
+
+  if(m_fillPhotons){
+    *m_convIP = p.convIP;
+    *m_convIPRev = p.convIPRev;
+
+    *m_PtIsolationCone = p.PtIsolationCone;
+    *m_PtIsolationConePhAngle = p.PtIsolationConePhAngle;
+  }
+
+  if (m_fillPtCorrectedIsolation) {
+    *m_Etcone40_pt_corrected = p.etcone40_pt_corrected;
+    if (m_fillPtCorrectedIsolation > 1) {
+      *m_Etcone30_pt_corrected = p.etcone30_pt_corrected;
+      *m_Etcone20_pt_corrected = p.etcone20_pt_corrected;
+
+      if (p.isElectron()) {
+        // PAU bug workaround: PAU leaves these fields uninitialized
+        // for electrons.
+        *m_Etcone35_pt_corrected = PAU::UNKNOWN;
+        *m_Etcone25_pt_corrected = PAU::UNKNOWN;
+        *m_Etcone15_pt_corrected = PAU::UNKNOWN;
+      }
+      else {
+        *m_Etcone35_pt_corrected = p.etcone35_pt_corrected;
+        *m_Etcone25_pt_corrected = p.etcone25_pt_corrected;
+        *m_Etcone15_pt_corrected = p.etcone15_pt_corrected;
+      }
+    }
+  }
+
+  *m_Etcone40_ED_corrected = p.etcone40_ED_corrected;
+  *m_Etcone40_corrected    = p.etcone40_corrected   ;
+
+  return StatusCode::SUCCESS;
+}
+
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUFillerTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUFillerTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..d5ac98eed53ec855f80a16a00106c655608d5a51
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUFillerTool.h
@@ -0,0 +1,94 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file egammaD3PDMaker/src/PAUFillerTool.h
+ * @author Mike Hance <hance@hep.upenn.edu>
+ * @date March, 2010
+ * @brief Fill PAU related variables
+ */
+
+
+#ifndef EGAMMAD3PDMAKER_PAUFILLERTOOL_H
+#define EGAMMAD3PDMAKER_PAUFILLERTOOL_H
+
+
+#include "D3PDMakerUtils/BlockFillerTool.h"
+#include <vector>
+#include <string>
+
+namespace PAU{
+  class egamma;
+}
+
+
+namespace D3PD {
+
+
+/**
+ * @brief Fill author code and related flags.
+ */
+class PAUFillerTool
+  : public BlockFillerTool<PAU::egamma>
+{
+public:
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  PAUFillerTool (const std::string& type,
+		 const std::string& name,
+		 const IInterface* parent);
+
+
+  /// Book variables for this block.
+  virtual StatusCode book();
+
+
+  /**
+   * @brief Fill one block --- type-safe version.
+   * @param p The input object.
+   *
+   * This is called once per object.  The caller
+   * is responsible for arranging that all the pointers for booked variables
+   * are set appropriately upon entry.
+   */
+  virtual StatusCode fill (const PAU::egamma& p);
+
+
+private:
+  float* m_convIP;
+  float* m_convIPRev;
+  
+  float* m_PtIsolationCone;
+  float* m_PtIsolationConePhAngle;
+
+  float* m_Etcone40_pt_corrected;
+  float* m_Etcone40_ED_corrected;
+  float* m_Etcone40_corrected   ;
+
+  float* m_Etcone35_pt_corrected;
+  float* m_Etcone30_pt_corrected;
+  float* m_Etcone25_pt_corrected;
+  float* m_Etcone20_pt_corrected;
+  float* m_Etcone15_pt_corrected;
+
+  bool m_fillPhotons;
+
+  /// 0: Don't fill any pt_corrected variables;
+  /// 1: Fill only Etcone40_pt_corrected;
+  /// 2: Fill all pt_corrected variables.
+  int m_fillPtCorrectedIsolation;
+};
+
+
+} // namespace D3PD
+
+
+#endif // not EGAMMAD3PDMAKER_PAUFILLERTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUGammaAssociationTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUGammaAssociationTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..e2851a22f23f71cd849ca5779e7c26295c57051f
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUGammaAssociationTool.cxx
@@ -0,0 +1,149 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file egammaD3PDMaker/src/PAUGammaAssociationTool.cxx
+ * @author Mike Hance <hance@hep.upenn.edu>, based on similar tools by scott snyder <snyder@bnl.gov>
+ * @date March, 2010
+ * @brief Associate photon to PAU egamma object
+ */
+
+
+#include "PAUGammaAssociationTool.h"
+#include "EventKernel/INavigable4Momentum.h"
+#include "AthenaKernel/errorcheck.h"
+#include "FourMomUtils/P4Helpers.h"
+
+#include "PhotonAnalysisUtils/PAUegamma.h"
+
+namespace D3PD {
+
+
+/**
+ * @brief Standard Gaudi tool constructor.
+ * @param type The name of the tool type.
+ * @param name The tool name.
+ * @param parent The tool's Gaudi parent.
+ */
+PAUGammaAssociationTool::PAUGammaAssociationTool (const std::string& type,
+						  const std::string& name,
+						  const IInterface* parent)
+  : Base (type, name, parent),
+    m_getter (this)
+{
+  declareProperty ("Getter", m_getter,
+                   "ICollectionGetterTool instance defining "
+                   "the target collection");
+
+  declareProperty ("DRcut", m_dr_cut=.01,
+		   "If the object can't be matched by pointer values, "
+		   "check to see if there are any objects within DRcut.");
+}
+
+
+/**
+ * @brief Standard Gaudi initialize method.
+ */
+StatusCode PAUGammaAssociationTool::initialize()
+{
+  // Retrieve the getter tool and configure it, saying that we want
+  // to get @c PAU::egamma objects from it.
+  CHECK( m_getter.retrieve() );
+  CHECK( m_getter->configureD3PD<PAU::egamma>() );
+  return Base::initialize();
+}
+
+
+/**
+ * @brief Create any needed tuple variables.
+ */
+StatusCode PAUGammaAssociationTool::book ()
+{
+  return StatusCode::SUCCESS;
+}
+
+
+/**
+ * @brief Return the target object.
+ * @param p The source object for the association.
+ *
+ * Return the target of the association, or 0.
+ */
+const PAU::egamma*
+PAUGammaAssociationTool::get (const INavigable4Momentum& p)
+{
+
+  if (m_getter->reset().isFailure()) {
+    REPORT_MESSAGE (MSG::ERROR) << "Can't reset input getter.";
+    return 0;
+  }
+
+  const Analysis::Photon* p_orig = dynamic_cast<const Analysis::Photon*>(&p);
+  const Analysis::Electron* e_orig = dynamic_cast<const Analysis::Electron*>(&p);
+
+  if(p_orig == 0 && e_orig == 0){
+    REPORT_MESSAGE (MSG::ERROR) << "Can't cast input object to an Analysis::Photon or an Analysis::Electron.";
+    return 0;
+  }
+    
+
+  const PAU::egamma* pout = 0;
+  while ( const PAU::egamma* obj =
+          m_getter->next<PAU::egamma>())
+  {
+    if (p_orig != 0 && p_orig == obj->photon()){
+      pout = obj;
+      break;
+    }
+    else if (e_orig != 0 && e_orig == obj->electron()){
+      pout = obj;
+      break;
+    }
+  }
+
+  // now, we can have cases where the pointers don't match for some reason.
+  // so, use a dR match to figure out which one should be kept.  We'll make
+  // the dR match pretty tight, since the only reason we shouldn't find a match
+  // is if, for instance, the PAU::gamma object is pointing to an object
+  // in PhotonCollection while the Analysis::Photon object is from the
+  // PhotonAODCollection.
+  float 
+    orig_phi=0, 
+    orig_eta=0, 
+    dphi=0, 
+    deta=0, 
+    dR=0;
+  if(pout == 0){
+    if(p_orig){
+      orig_phi = p_orig->phi();
+      orig_eta = p_orig->eta();
+    }
+    else if(e_orig){
+      orig_phi = e_orig->phi();
+      orig_eta = e_orig->eta();
+    }
+
+    if(m_getter->reset() != StatusCode::SUCCESS){
+      REPORT_MESSAGE (MSG::ERROR) << "Could not reset photon getter!";
+      return 0;
+    }
+    while ( const PAU::egamma* obj =
+	    m_getter->next<PAU::egamma>())
+      {
+	dphi = P4Helpers::deltaPhi(obj->phi(),orig_phi);
+	deta = obj->eta() - orig_eta;
+	dR = std::sqrt(dphi*dphi + deta*deta);
+	if(dR < m_dr_cut){
+	  pout = obj;
+	  break;
+	}
+      }
+  }
+
+  return pout;
+}
+
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUGammaAssociationTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUGammaAssociationTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..0525e5b12392de82aa366fe14f3a5558f954a129
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUGammaAssociationTool.h
@@ -0,0 +1,91 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file egammaD3PDMaker/src/PAUGammaAssociationTool.h
+ * @author Mike Hance <hance@hep.upenn.edu>, based on similar tools by scott snyder <snyder@bnl.gov>
+ * @date March, 2010
+ * @brief Associate photon to PAU gamma object
+ */
+
+
+#ifndef EGAMMAD3PDMAKER_PAUGAMMAASSOCIATIONTOOL_H
+#define EGAMMAD3PDMAKER_PAUGAMMAASSOCIATIONTOOL_H
+
+
+#include "D3PDMakerInterfaces/ICollectionGetterTool.h"
+#include "D3PDMakerUtils/SingleAssociationTool.h"
+#include "EventKernel/INavigable4Momentum.h"
+#include "GaudiKernel/ToolHandle.h"
+
+namespace PAU {
+  class egamma;
+}
+
+namespace D3PD {
+
+
+/**
+ * @brief Associate to particle closest in DR.
+ *
+ * This is a single association tool.
+ * Given an @c INavigable4Momentum object and a container of PAU::egamma objects,
+ * return the object in the container that is associated with the original object.
+ *
+ * Parameters:
+ *  Getter - ICollectionGetterTool instance defining the target collection.
+ *
+ */
+class PAUGammaAssociationTool
+  : public SingleAssociationTool<INavigable4Momentum, PAU::egamma>
+{
+public:
+  typedef SingleAssociationTool<INavigable4Momentum, PAU::egamma> Base;
+
+
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  PAUGammaAssociationTool (const std::string& type,
+			   const std::string& name,
+			   const IInterface* parent);
+
+
+  /// Standard Gaudi initialize method.
+  virtual StatusCode initialize();
+
+
+  /**
+   * @brief Create any needed tuple variables.
+   */
+  virtual StatusCode book();
+
+
+  /**
+   * @brief Return the target object.
+   * @param p The source object for the association.
+   *
+   * Return the target of the association, or 0.
+   */
+  virtual const PAU::egamma* get (const INavigable4Momentum& p);
+
+
+private:
+  /// Property: The getter for the target collection.
+  ToolHandle<ICollectionGetterTool> m_getter;
+  float                             m_dr_cut;
+};
+
+
+} // namespace D3PD
+
+
+
+#endif // not EGAMMAD3PDMAKER_PAUGAMMAASSOCIATIONTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUIsolationFillerTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUIsolationFillerTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..0004b854949f305bb5f2f1549c5cc56d50550118
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUIsolationFillerTool.cxx
@@ -0,0 +1,309 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/PAUIsolationFillerTool.h
+ * @author Mike Hance <hance@hep.upenn.edu>
+ * @date January, 2011
+ * @brief Fill PAU related variables
+ */
+
+
+#include "PAUIsolationFillerTool.h"
+#include "AthenaKernel/errorcheck.h"
+
+#include "PhotonAnalysisUtils/PAUegamma.h"
+
+using namespace PAU;
+
+namespace D3PD {
+
+
+/**
+ * @brief Standard Gaudi tool constructor.
+ * @param type The name of the tool type.
+ * @param name The tool name.
+ * @param parent The tool's Gaudi parent.
+ */
+PAUIsolationFillerTool::PAUIsolationFillerTool (const std::string& type,
+						const std::string& name,
+						const IInterface* parent)
+  : BlockFillerTool<PAU::egamma> (type, name, parent)
+{
+  // Avoid coverity warnings.
+  book().ignore();
+  m_ED_median_new = 0;
+  m_ED_sigma_new = 0;
+  m_ED_Njets_new = 0;
+
+  declareProperty("Fill_EtCone_pt_corrected", m_fill_EtCone_pt_corrected);
+  declareProperty("Fill_EtCone_ED_corrected", m_fill_EtCone_ED_corrected);
+  declareProperty("Fill_EtCone_corrected"   , m_fill_EtCone_corrected   );
+  declareProperty("Fill_EtCone_ED_corrected_new", m_fill_EtCone_ED_corrected_new);
+  declareProperty("Fill_EtCone_corrected_new"   , m_fill_EtCone_corrected_new   );
+
+  declareProperty("Fill_EtCone_cells35"     , m_fill_EtCone_cells35     );
+  declareProperty("Fill_EtCone_cells55"     , m_fill_EtCone_cells55     );
+
+  declareProperty("Fill_EtConeIso"          , m_fill_EtConeIso          );
+  declareProperty("Fill_EtConeIso_cells35"  , m_fill_EtConeIso_cells35  );
+  declareProperty("Fill_EtConeIso_cells55"  , m_fill_EtConeIso_cells55  );
+
+  // set up some relationships
+  m_fill_to_value_map[&m_fill_EtCone_pt_corrected] = &m_EtCone_pt_corrected;
+  m_fill_to_value_map[&m_fill_EtCone_ED_corrected] = &m_EtCone_ED_corrected;
+  m_fill_to_value_map[&m_fill_EtCone_corrected]    = &m_EtCone_corrected   ;
+  m_fill_to_value_map[&m_fill_EtCone_ED_corrected_new] = &m_EtCone_ED_corrected_new;
+  m_fill_to_value_map[&m_fill_EtCone_corrected_new]    = &m_EtCone_corrected_new   ;
+
+  m_fill_to_value_map[&m_fill_EtCone_cells35]      = &m_EtCone_cells35     ;
+  m_fill_to_value_map[&m_fill_EtCone_cells55]      = &m_EtCone_cells55     ;
+
+  m_fill_to_value_map[&m_fill_EtConeIso]           = &m_EtConeIso          ;
+  m_fill_to_value_map[&m_fill_EtConeIso_cells35]   = &m_EtConeIso_cells35  ;
+  m_fill_to_value_map[&m_fill_EtConeIso_cells55]   = &m_EtConeIso_cells55  ;
+
+  // initialize some default names
+  m_fill_to_name_map[&m_fill_EtCone_pt_corrected] = "Etcone%d_pt_corrected";
+  m_fill_to_name_map[&m_fill_EtCone_ED_corrected] = "Etcone%d_ED_corrected";
+  m_fill_to_name_map[&m_fill_EtCone_corrected]    = "Etcone%d_corrected"   ;
+  m_fill_to_name_map[&m_fill_EtCone_ED_corrected_new] = "Etcone%d_ED_corrected_new";
+  m_fill_to_name_map[&m_fill_EtCone_corrected_new]    = "Etcone%d_corrected_new"   ;
+		    						    
+  m_fill_to_name_map[&m_fill_EtCone_cells35]      = "cells35_Etcone%d"     ;
+  m_fill_to_name_map[&m_fill_EtCone_cells55]      = "cells55_Etcone%d"     ;
+		    						    
+  m_fill_to_name_map[&m_fill_EtConeIso]           = "Etcone%dIso"          ;
+  m_fill_to_name_map[&m_fill_EtConeIso_cells35]   = "cells35_Etcone%dIso"  ;
+  m_fill_to_name_map[&m_fill_EtConeIso_cells55]   = "cells55_Etcone%dIso"  ;
+
+  // initialize some default acceptable values
+  m_EtCone_pt_corrected[10] = NULL;
+  m_EtCone_pt_corrected[15] = NULL;
+  m_EtCone_pt_corrected[20] = NULL;
+  m_EtCone_pt_corrected[25] = NULL;
+  m_EtCone_pt_corrected[30] = NULL;
+  m_EtCone_pt_corrected[35] = NULL;
+  m_EtCone_pt_corrected[40] = NULL;
+
+  m_EtCone_ED_corrected[10] = NULL;
+  m_EtCone_ED_corrected[15] = NULL;
+  m_EtCone_ED_corrected[20] = NULL;
+  m_EtCone_ED_corrected[25] = NULL;
+  m_EtCone_ED_corrected[30] = NULL;
+  m_EtCone_ED_corrected[35] = NULL;
+  m_EtCone_ED_corrected[40] = NULL;
+
+  m_EtCone_corrected[10] = NULL;
+  m_EtCone_corrected[15] = NULL;
+  m_EtCone_corrected[20] = NULL;
+  m_EtCone_corrected[25] = NULL;
+  m_EtCone_corrected[30] = NULL;
+  m_EtCone_corrected[35] = NULL;
+  m_EtCone_corrected[40] = NULL;
+
+  m_EtCone_ED_corrected_new[10] = NULL;
+  m_EtCone_ED_corrected_new[15] = NULL;
+  m_EtCone_ED_corrected_new[20] = NULL;
+  m_EtCone_ED_corrected_new[25] = NULL;
+  m_EtCone_ED_corrected_new[30] = NULL;
+  m_EtCone_ED_corrected_new[35] = NULL;
+  m_EtCone_ED_corrected_new[40] = NULL;
+
+  m_EtCone_corrected_new[10] = NULL;
+  m_EtCone_corrected_new[15] = NULL;
+  m_EtCone_corrected_new[20] = NULL;
+  m_EtCone_corrected_new[25] = NULL;
+  m_EtCone_corrected_new[30] = NULL;
+  m_EtCone_corrected_new[35] = NULL;
+  m_EtCone_corrected_new[40] = NULL;
+
+  m_EtCone_cells35[20] = NULL;
+  m_EtCone_cells35[30] = NULL;
+  m_EtCone_cells35[40] = NULL;
+
+  m_EtCone_cells55[20] = NULL;
+  m_EtCone_cells55[30] = NULL;
+  m_EtCone_cells55[40] = NULL;
+
+  m_EtConeIso[20] = NULL;
+  m_EtConeIso[30] = NULL;
+  m_EtConeIso[40] = NULL;
+
+  m_EtConeIso_cells35[20] = NULL;
+  m_EtConeIso_cells35[30] = NULL;
+  m_EtConeIso_cells35[40] = NULL;
+
+  m_EtConeIso_cells55[20] = NULL;
+  m_EtConeIso_cells55[30] = NULL;
+  m_EtConeIso_cells55[40] = NULL;
+
+
+  // collect all of the maps for later
+  m_all_vecs.push_back(&m_fill_EtCone_pt_corrected);
+  m_all_vecs.push_back(&m_fill_EtCone_ED_corrected);
+  m_all_vecs.push_back(&m_fill_EtCone_corrected);
+  m_all_vecs.push_back(&m_fill_EtCone_ED_corrected_new);
+  m_all_vecs.push_back(&m_fill_EtCone_corrected_new);
+
+  m_all_vecs.push_back(&m_fill_EtCone_cells35);
+  m_all_vecs.push_back(&m_fill_EtCone_cells55);
+
+  m_all_vecs.push_back(&m_fill_EtConeIso);
+  m_all_vecs.push_back(&m_fill_EtConeIso_cells35);
+  m_all_vecs.push_back(&m_fill_EtConeIso_cells55);
+}
+
+
+/**
+ * @brief Book variables for this block.
+ */
+StatusCode PAUIsolationFillerTool::book()
+{
+  for(unsigned int j=0; j<m_all_vecs.size(); j++){
+    std::vector<float>* fill_vec = m_all_vecs[j];
+    std::map<int, float*>* value_map = m_fill_to_value_map[fill_vec];
+    std::string var_name_template = m_fill_to_name_map[fill_vec];
+
+    for(unsigned int i=0; i<fill_vec->size(); i++){
+      int radius = 0;
+      float float_radius = fill_vec->at(i);
+      if(float_radius < 9) radius = (int)(float_radius*10);
+      else                 radius = (int)(float_radius);
+      
+      if(value_map->find((int)radius) == value_map->end()) continue;
+      
+      char varname[100];
+      snprintf(varname, 100, var_name_template.c_str(), (int)radius);
+      std::string vn(varname);
+      CHECK( addVariable( vn, value_map->at(radius) ) );
+    }
+  }
+
+  CHECK ( addVariable( "ED_median", m_ED_median ) );
+  CHECK ( addVariable( "ED_sigma" , m_ED_sigma  ) );
+  CHECK ( addVariable( "ED_Njets" , m_ED_Njets  ) );
+
+  if(m_fill_EtCone_corrected_new.size()  || m_fill_EtCone_ED_corrected_new.size()){
+    CHECK ( addVariable( "ED_median_new", m_ED_median_new ) );
+    CHECK ( addVariable( "ED_sigma_new" , m_ED_sigma_new  ) );
+    CHECK ( addVariable( "ED_Njets_new" , m_ED_Njets_new  ) );
+  }
+
+  CHECK ( addVariable( "transmin_etcone40" , m_transmin_etcone40  ) );
+  CHECK ( addVariable( "transmax_etcone40" , m_transmax_etcone40  ) );
+  CHECK ( addVariable( "transmin_etcone100", m_transmin_etcone100 ) );
+  CHECK ( addVariable( "transmax_etcone100", m_transmax_etcone100 ) );
+
+  CHECK ( addVariable( "transmin", m_transmin ) );
+  CHECK ( addVariable( "transmax", m_transmax ) );
+
+  CHECK ( addVariable( "transmin_loweta", m_transmin_loweta ) );
+  CHECK ( addVariable( "transmax_loweta", m_transmax_loweta ) );
+  
+  return StatusCode::SUCCESS;
+}
+
+
+void FillIso(float* fillme, float val){
+  if(fillme != NULL) *fillme = val;
+}
+
+/**
+ * @brief Fill one block --- type-safe version.
+ * @param p The input object.
+ *
+ * This is called once per object.  The caller
+ * is responsible for arranging that all the pointers for booked variables
+ * are set appropriately upon entry.
+ */
+StatusCode PAUIsolationFillerTool::fill (const PAU::egamma& p)
+{
+
+  // initialize some default acceptable values
+  FillIso( m_EtCone_pt_corrected[10], p.etcone10_pt_corrected );
+  FillIso( m_EtCone_pt_corrected[15], p.etcone15_pt_corrected );
+  FillIso( m_EtCone_pt_corrected[20], p.etcone20_pt_corrected );
+  FillIso( m_EtCone_pt_corrected[25], p.etcone25_pt_corrected );
+  FillIso( m_EtCone_pt_corrected[30], p.etcone30_pt_corrected );
+  FillIso( m_EtCone_pt_corrected[35], p.etcone35_pt_corrected );
+  FillIso( m_EtCone_pt_corrected[40], p.etcone40_pt_corrected );
+
+  FillIso( m_EtCone_ED_corrected[10], p.etcone10_ED_corrected );
+  FillIso( m_EtCone_ED_corrected[15], p.etcone15_ED_corrected );
+  FillIso( m_EtCone_ED_corrected[20], p.etcone20_ED_corrected );
+  FillIso( m_EtCone_ED_corrected[25], p.etcone25_ED_corrected );
+  FillIso( m_EtCone_ED_corrected[30], p.etcone30_ED_corrected );
+  FillIso( m_EtCone_ED_corrected[35], p.etcone35_ED_corrected );
+  FillIso( m_EtCone_ED_corrected[40], p.etcone40_ED_corrected );
+
+  FillIso( m_EtCone_corrected[10], p.etcone10_corrected );
+  FillIso( m_EtCone_corrected[15], p.etcone15_corrected );
+  FillIso( m_EtCone_corrected[20], p.etcone20_corrected );
+  FillIso( m_EtCone_corrected[25], p.etcone25_corrected );
+  FillIso( m_EtCone_corrected[30], p.etcone30_corrected );
+  FillIso( m_EtCone_corrected[35], p.etcone35_corrected );
+  FillIso( m_EtCone_corrected[40], p.etcone40_corrected );
+
+  FillIso( m_EtCone_ED_corrected_new[10], p.etcone10_ED_corrected_new );
+  FillIso( m_EtCone_ED_corrected_new[15], p.etcone15_ED_corrected_new );
+  FillIso( m_EtCone_ED_corrected_new[20], p.etcone20_ED_corrected_new );
+  FillIso( m_EtCone_ED_corrected_new[25], p.etcone25_ED_corrected_new );
+  FillIso( m_EtCone_ED_corrected_new[30], p.etcone30_ED_corrected_new );
+  FillIso( m_EtCone_ED_corrected_new[35], p.etcone35_ED_corrected_new );
+  FillIso( m_EtCone_ED_corrected_new[40], p.etcone40_ED_corrected_new );
+
+  FillIso( m_EtCone_corrected_new[10], p.etcone10_corrected_new );
+  FillIso( m_EtCone_corrected_new[15], p.etcone15_corrected_new );
+  FillIso( m_EtCone_corrected_new[20], p.etcone20_corrected_new );
+  FillIso( m_EtCone_corrected_new[25], p.etcone25_corrected_new );
+  FillIso( m_EtCone_corrected_new[30], p.etcone30_corrected_new );
+  FillIso( m_EtCone_corrected_new[35], p.etcone35_corrected_new );
+  FillIso( m_EtCone_corrected_new[40], p.etcone40_corrected_new );
+
+  FillIso( m_EtCone_cells35[20], p.cells35etcone20 );
+  FillIso( m_EtCone_cells35[30], p.cells35etcone30 );
+  FillIso( m_EtCone_cells35[40], p.cells35etcone40 );
+			   					     
+  FillIso( m_EtCone_cells55[20], p.cells55etcone20 );
+  FillIso( m_EtCone_cells55[30], p.cells55etcone30 );
+  FillIso( m_EtCone_cells55[40], p.cells55etcone40 );
+
+  FillIso( m_EtConeIso[20], p.etcone20iso );
+  FillIso( m_EtConeIso[30], p.etcone30iso );
+  FillIso( m_EtConeIso[40], p.etcone40iso );
+
+  FillIso( m_EtConeIso_cells35[20], p.cells35etcone20iso );
+  FillIso( m_EtConeIso_cells35[30], p.cells35etcone30iso );
+  FillIso( m_EtConeIso_cells35[40], p.cells35etcone40iso );
+
+  FillIso( m_EtConeIso_cells55[20], p.cells55etcone20iso );
+  FillIso( m_EtConeIso_cells55[30], p.cells55etcone30iso );
+  FillIso( m_EtConeIso_cells55[40], p.cells55etcone40iso );
+
+  * m_ED_median		   = p.ED_median	  ;
+  * m_ED_sigma		   = p.ED_sigma	          ;
+  * m_ED_Njets		   = p.ED_Njets	          ;
+
+  if(m_fill_EtCone_corrected_new.size()  || m_fill_EtCone_ED_corrected_new.size()){
+    * m_ED_median_new		   = p.ED_median_new	  ;
+    * m_ED_sigma_new		   = p.ED_sigma_new	          ;
+    * m_ED_Njets_new		   = p.ED_Njets_new	          ;
+  }
+
+  * m_transmin_etcone40	   = p.transmin_etcone40  ;
+  * m_transmax_etcone40	   = p.transmax_etcone40  ;
+  * m_transmin_etcone100   = p.transmin_etcone100 ;
+  * m_transmax_etcone100   = p.transmax_etcone100 ;
+  * m_transmin		   = p.transmin	          ;
+  * m_transmax		   = p.transmax	          ;
+  * m_transmin_loweta	   = p.transmin_loweta    ;
+  * m_transmax_loweta      = p.transmax_loweta    ;
+
+  return StatusCode::SUCCESS;
+}
+
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUIsolationFillerTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUIsolationFillerTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..9cb96f8382e9bada02b2859fb164a3488ff312a6
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUIsolationFillerTool.h
@@ -0,0 +1,122 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/PAUIsolationFillerTool.h
+ * @author Mike Hance <hance@hep.upenn.edu>
+ * @date March, 2010
+ * @brief Fill PAU related variables
+ */
+
+
+#ifndef PHOTOND3PDMAKER_PAUISOLATIONFILLERTOOL_H
+#define PHOTOND3PDMAKER_PAUISOLATIONFILLERTOOL_H
+
+
+#include "D3PDMakerUtils/BlockFillerTool.h"
+#include <vector>
+#include <string>
+#include <map>
+
+namespace PAU{
+  class egamma;
+}
+
+
+namespace D3PD {
+
+
+/**
+ * @brief Fill author code and related flags.
+ */
+class PAUIsolationFillerTool
+  : public BlockFillerTool<PAU::egamma>
+{
+public:
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  PAUIsolationFillerTool (const std::string& type,
+			  const std::string& name,
+			  const IInterface* parent);
+
+
+  /// Book variables for this block.
+  virtual StatusCode book();
+
+
+  /**
+   * @brief Fill one block --- type-safe version.
+   * @param p The input object.
+   *
+   * This is called once per object.  The caller
+   * is responsible for arranging that all the pointers for booked variables
+   * are set appropriately upon entry.
+   */
+  virtual StatusCode fill (const PAU::egamma& p);
+
+
+private:
+  std::vector<float> m_fill_EtCone_pt_corrected;
+  std::vector<float> m_fill_EtCone_ED_corrected;
+  std::vector<float> m_fill_EtCone_ED_corrected_new;
+  std::vector<float> m_fill_EtCone_corrected;
+  std::vector<float> m_fill_EtCone_corrected_new;
+
+  std::vector<float> m_fill_EtConeIso;
+  std::vector<float> m_fill_EtCone_cells35;
+  std::vector<float> m_fill_EtCone_cells55;
+  std::vector<float> m_fill_EtConeIso_cells35;
+  std::vector<float> m_fill_EtConeIso_cells55;
+
+  std::map<int, float*> m_EtCone_pt_corrected;
+  std::map<int, float*> m_EtCone_ED_corrected;
+  std::map<int, float*> m_EtCone_corrected;
+  std::map<int, float*> m_EtCone_ED_corrected_new;
+  std::map<int, float*> m_EtCone_corrected_new;
+
+  std::map<int, float*> m_EtConeIso;
+  std::map<int, float*> m_EtCone_cells35;
+  std::map<int, float*> m_EtCone_cells55;
+  std::map<int, float*> m_EtConeIso_cells35;
+  std::map<int, float*> m_EtConeIso_cells55;
+
+
+  // mapping the "fill" vectors to the value vectors
+  std::map<std::vector<float>*, std::map<int, float*>*> m_fill_to_value_map;
+
+  // mapping the "fill" vectors to the variable names
+  std::map<std::vector<float>*, std::string> m_fill_to_name_map;
+
+  // collection of all maps
+  std::vector<std::vector<float>*> m_all_vecs;
+
+  // some more isolation stuff
+  float * m_ED_median ;
+  float * m_ED_sigma ;
+  int   * m_ED_Njets ;
+  float * m_ED_median_new ;
+  float * m_ED_sigma_new ;
+  int   * m_ED_Njets_new ;
+  float * m_transmin_etcone40 ;
+  float * m_transmax_etcone40 ;
+  float * m_transmin_etcone100 ;
+  float * m_transmax_etcone100 ;
+  float * m_transmin ;
+  float * m_transmax ;
+  float * m_transmin_loweta ;
+  float * m_transmax_loweta ;
+};
+
+
+} // namespace D3PD
+
+
+#endif // not PHOTOND3PDMAKER_PAUISOLATIONFILLERTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUPhotonFillerTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUPhotonFillerTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..3451e27eda30aae29f32661c2413e648dedd8314
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUPhotonFillerTool.cxx
@@ -0,0 +1,133 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/PAUPhotonFillerTool.h
+ * @author Mike Hance <hance@hep.upenn.edu>
+ * @date January, 2011
+ * @brief Fill PAU related variables
+ */
+
+
+#include "PAUPhotonFillerTool.h"
+#include "AthenaKernel/errorcheck.h"
+
+#include "PhotonAnalysisUtils/PAUegamma.h"
+
+namespace D3PD {
+
+
+/**
+ * @brief Standard Gaudi tool constructor.
+ * @param type The name of the tool type.
+ * @param name The tool name.
+ * @param parent The tool's Gaudi parent.
+ */
+PAUPhotonFillerTool::PAUPhotonFillerTool (const std::string& type,
+			      const std::string& name,
+			      const IInterface* parent)
+  : BlockFillerTool<PAU::egamma> (type, name, parent)
+{
+  m_dumpMC = true;
+  book().ignore(); // Avoid coverity warnings.
+
+  declareProperty("DumpMC", m_dumpMC = false,
+		  "Dump information about truth photon");
+}
+
+
+/**
+ * @brief Book variables for this block.
+ */
+StatusCode PAUPhotonFillerTool::book()
+{
+
+  CHECK( addVariable("ambiguityResult"				     , m_ambiguityResult			    ) );
+
+  if(m_dumpMC){
+    CHECK( addVariable("parton_pt_max_MC"				     , m_parton_pt_max_MC			    ) );
+    CHECK( addVariable("parton_eta_MC"				     , m_parton_eta_MC			            ) );
+    CHECK( addVariable("parton_phi_MC"				     , m_parton_phi_MC			            ) );
+    CHECK( addVariable("parton_barcode_MC"			     , m_parton_barcode_MC			    ) );
+    CHECK( addVariable("parton_pdg_MC"				     , m_parton_pdg_MC			            ) );
+    CHECK( addVariable("etaS2_MC"					     , m_etaS2_MC				    ) );
+    CHECK( addVariable("phiS2_MC"					     , m_phiS2_MC				    ) );
+    CHECK( addVariable("XConv_MC"					     , m_XConv_MC				    ) );
+    CHECK( addVariable("YConv_MC"					     , m_YConv_MC				    ) );
+    CHECK( addVariable("isG4part"					     , m_isG4part				    ) );
+    CHECK( addVariable("partonIsolation15_UE_MC"			     , m_partonIsolation15_UE_MC		    ) );
+    CHECK( addVariable("partonIsolation20_UE_MC"			     , m_partonIsolation20_UE_MC		    ) );
+    CHECK( addVariable("partonIsolation25_UE_MC"			     , m_partonIsolation25_UE_MC		    ) );
+    CHECK( addVariable("partonIsolation30_UE_MC"			     , m_partonIsolation30_UE_MC		    ) );
+    CHECK( addVariable("partonIsolation35_UE_MC"			     , m_partonIsolation35_UE_MC		    ) );
+    CHECK( addVariable("partonIsolation40_UE_MC"			     , m_partonIsolation40_UE_MC		    ) );
+    CHECK( addVariable("partonIsolation45_UE_MC"			     , m_partonIsolation45_UE_MC		    ) );
+    CHECK( addVariable("partonIsolation60_UE_MC"			     , m_partonIsolation60_UE_MC		    ) );
+    CHECK( addVariable("partonIsolation15_MC"			     , m_partonIsolation15_MC		            ) );
+    CHECK( addVariable("partonIsolation20_MC"			     , m_partonIsolation20_MC		            ) );
+    CHECK( addVariable("partonIsolation25_MC"			     , m_partonIsolation25_MC		            ) );
+    CHECK( addVariable("partonIsolation30_MC"			     , m_partonIsolation30_MC		            ) );
+    CHECK( addVariable("partonIsolation35_MC"			     , m_partonIsolation35_MC		            ) );
+    CHECK( addVariable("partonIsolation40_MC"			     , m_partonIsolation40_MC		            ) );
+    CHECK( addVariable("partonIsolation45_MC"			     , m_partonIsolation45_MC		            ) );
+    CHECK( addVariable("partonIsolation60_MC"			     , m_partonIsolation60_MC		            ) );
+    CHECK( addVariable("particleIsolation40_MC"			     , m_particleIsolation40_MC		            ) );
+    CHECK( addVariable("particleIsolation40_ED_corrected_MC"           , m_particleIsolation40_ED_corrected_MC	    ) );
+    CHECK( addVariable("particleIsolation40_ED_corrected_reco_MC"	     , m_particleIsolation40_ED_corrected_reco_MC   ) );
+  }
+  return StatusCode::SUCCESS;
+}
+
+
+/**
+ * @brief Fill one block --- type-safe version.
+ * @param p The input object.
+ *
+ * This is called once per object.  The caller
+ * is responsible for arranging that all the pointers for booked variables
+ * are set appropriately upon entry.
+ */
+StatusCode PAUPhotonFillerTool::fill (const PAU::egamma& p)
+{
+
+  * m_ambiguityResult			        = p.ambiguityResult			       ;
+
+  if(m_dumpMC){
+    * m_parton_pt_max_MC		        = p.parton_pt_max_MC			       ;
+    * m_parton_eta_MC			        = p.parton_eta_MC			       ;
+    * m_parton_phi_MC			        = p.parton_phi_MC			       ;
+    * m_parton_barcode_MC		        = p.parton_barcode_MC			       ;
+    * m_parton_pdg_MC			        = p.parton_pdg_MC			       ;
+    * m_etaS2_MC			        = p.etaCaloMC				       ;
+    * m_phiS2_MC			        = p.phiCaloMC				       ;
+    * m_XConv_MC			        = p.XconvMC				       ;
+    * m_YConv_MC			        = p.YconvMC				       ;
+    * m_isG4part			        = p.isG4part				       ;
+    * m_partonIsolation15_UE_MC		        = p.partonIsolation15_UE		       ;
+    * m_partonIsolation20_UE_MC		        = p.partonIsolation20_UE		       ;
+    * m_partonIsolation25_UE_MC		        = p.partonIsolation25_UE		       ;
+    * m_partonIsolation30_UE_MC		        = p.partonIsolation30_UE		       ;
+    * m_partonIsolation35_UE_MC		        = p.partonIsolation35_UE		       ;
+    * m_partonIsolation40_UE_MC		        = p.partonIsolation40_UE		       ;
+    * m_partonIsolation45_UE_MC		        = p.partonIsolation45_UE		       ;
+    * m_partonIsolation60_UE_MC		        = p.partonIsolation60_UE	               ;
+    * m_partonIsolation15_MC		        = p.partonIsolation15		               ;
+    * m_partonIsolation20_MC		        = p.partonIsolation20		               ;
+    * m_partonIsolation25_MC		        = p.partonIsolation25		               ;
+    * m_partonIsolation30_MC		        = p.partonIsolation30		               ;
+    * m_partonIsolation35_MC		        = p.partonIsolation35		               ;
+    * m_partonIsolation40_MC		        = p.partonIsolation40		               ;
+    * m_partonIsolation45_MC		        = p.partonIsolation45		               ;
+    * m_partonIsolation60_MC		        = p.partonIsolation60		               ;
+    * m_particleIsolation40_MC		        = p.particleIsolation40		               ;
+    * m_particleIsolation40_ED_corrected_MC     = p.particleIsolation40_ED_corrected	       ;
+    * m_particleIsolation40_ED_corrected_reco_MC= p.particleIsolation40_ED_corrected_reco      ;
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUPhotonFillerTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUPhotonFillerTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..0e0698510aa9b324678097b67cf518fc4a6d150e
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUPhotonFillerTool.h
@@ -0,0 +1,106 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/PAUPhotonFillerTool.h
+ * @author Mike Hance <hance@hep.upenn.edu>
+ * @date March, 2010
+ * @brief Fill PAU related variables
+ */
+
+
+#ifndef PHOTOND3PDMAKER_PAUPHOTONFILLERTOOL_H
+#define PHOTOND3PDMAKER_PAUPHOTONFILLERTOOL_H
+
+
+#include "D3PDMakerUtils/BlockFillerTool.h"
+#include <vector>
+#include <string>
+
+namespace PAU{
+  class egamma;
+}
+
+
+namespace D3PD {
+
+
+/**
+ * @brief Fill author code and related flags.
+ */
+class PAUPhotonFillerTool
+  : public BlockFillerTool<PAU::egamma>
+{
+public:
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  PAUPhotonFillerTool (const std::string& type,
+		       const std::string& name,
+		       const IInterface* parent);
+
+
+  /// Book variables for this block.
+  virtual StatusCode book();
+
+
+  /**
+   * @brief Fill one block --- type-safe version.
+   * @param p The input object.
+   *
+   * This is called once per object.  The caller
+   * is responsible for arranging that all the pointers for booked variables
+   * are set appropriately upon entry.
+   */
+  virtual StatusCode fill (const PAU::egamma& p);
+
+
+private:
+
+  bool m_dumpMC;
+
+  float * m_ambiguityResult;
+
+  float * m_parton_pt_max_MC;
+  float * m_parton_eta_MC;
+  float * m_parton_phi_MC;
+  float * m_parton_barcode_MC;
+  float * m_parton_pdg_MC;
+  float * m_etaS2_MC;
+  float * m_phiS2_MC;
+  float * m_XConv_MC;
+  float * m_YConv_MC;
+  int   * m_isG4part;
+  float * m_partonIsolation15_UE_MC;
+  float * m_partonIsolation20_UE_MC;
+  float * m_partonIsolation25_UE_MC;
+  float * m_partonIsolation30_UE_MC;
+  float * m_partonIsolation35_UE_MC;
+  float * m_partonIsolation40_UE_MC;
+  float * m_partonIsolation45_UE_MC;
+  float * m_partonIsolation60_UE_MC;
+  float * m_partonIsolation15_MC;
+  float * m_partonIsolation20_MC;
+  float * m_partonIsolation25_MC;
+  float * m_partonIsolation30_MC;
+  float * m_partonIsolation35_MC;
+  float * m_partonIsolation40_MC;
+  float * m_partonIsolation45_MC;
+  float * m_partonIsolation60_MC;
+  float * m_particleIsolation40_MC;
+  float * m_particleIsolation40_ED_corrected_MC;
+  float * m_particleIsolation40_ED_corrected_reco_MC;
+};
+
+
+} // namespace D3PD
+
+
+#endif // not PHOTOND3PDMAKER_PAUPHOTONFILLERTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUTruthPhotonAssociationTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUTruthPhotonAssociationTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..37c3eda35d459af196a07b2013335058ada89e7a
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUTruthPhotonAssociationTool.cxx
@@ -0,0 +1,103 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file egammaD3PDMaker/src/PAUTruthPhotonAssociationTool.cxx
+ * @author Mike Hance <hance@hep.upenn.edu>, based on similar tools by scott snyder <snyder@bnl.gov>
+ * @date March, 2010
+ * @brief Associate photon to PAU egamma object
+ */
+
+
+#include "PAUTruthPhotonAssociationTool.h"
+#include "McParticleEvent/TruthParticle.h"
+#include "EventKernel/INavigable4Momentum.h"
+#include "AthenaKernel/errorcheck.h"
+#include "FourMomUtils/P4Helpers.h"
+
+#include "PhotonAnalysisUtils/PAUnamespace.h"
+#include "PhotonAnalysisUtils/PAUegammaTruth.h"
+
+namespace D3PD {
+
+
+/**
+ * @brief Standard Gaudi tool constructor.
+ * @param type The name of the tool type.
+ * @param name The tool name.
+ * @param parent The tool's Gaudi parent.
+ */
+PAUTruthPhotonAssociationTool::PAUTruthPhotonAssociationTool (const std::string& type,
+							      const std::string& name,
+							      const IInterface* parent)
+  : Base (type, name, parent),
+    m_getter (this)
+{
+  declareProperty ("Getter", m_getter,
+                   "ICollectionGetterTool instance defining "
+                   "the target collection");
+}
+
+
+/**
+ * @brief Standard Gaudi initialize method.
+ */
+StatusCode PAUTruthPhotonAssociationTool::initialize()
+{
+  // Retrieve the getter tool and configure it, saying that we want
+  // to get @c PAU::egamma objects from it.
+  CHECK( m_getter.retrieve() );
+  CHECK( m_getter->configureD3PD<PAU::egammaTruth>() );
+  return Base::initialize();
+}
+
+
+/**
+ * @brief Create any needed tuple variables.
+ */
+StatusCode PAUTruthPhotonAssociationTool::book ()
+{
+  return StatusCode::SUCCESS;
+}
+
+
+/**
+ * @brief Return the target object.
+ * @param p The source object for the association.
+ *
+ * Return the target of the association, or 0.
+ */
+const PAU::egammaTruth*
+PAUTruthPhotonAssociationTool::get (const INavigable4Momentum& p)
+{
+  if (m_getter->reset().isFailure()) {
+    REPORT_MESSAGE (MSG::ERROR) << "Can't reset input getter.";
+    return 0;
+  }
+
+  const TruthParticle* p_orig = dynamic_cast<const TruthParticle*>(&p);
+  if(p_orig == 0){
+    REPORT_MESSAGE (MSG::ERROR) << "Can't cast input object to a TruthParticle.";
+    return 0;
+  }
+
+  const PAU::egammaTruth* out = 0;
+  while ( const PAU::egammaTruth* obj =
+          m_getter->next<PAU::egammaTruth>())
+  {
+    const TruthParticle* tp = obj->matchedTruthParticle;
+    if(!tp) continue;
+
+    if(p_orig->barcode() == tp->barcode()){  // is this really the best way to compare?
+      out = obj;
+      break;
+    }
+  }
+
+  return out;
+}
+
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUTruthPhotonAssociationTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUTruthPhotonAssociationTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..c0dd45d58f3e65068e516aa2e38a7a6936ef52e3
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUTruthPhotonAssociationTool.h
@@ -0,0 +1,90 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file egammaD3PDMaker/src/PAUGammaAssociationTool.h
+ * @author Mike Hance <hance@hep.upenn.edu>, based on similar tools by scott snyder <snyder@bnl.gov>
+ * @date March, 2010
+ * @brief Associate photon to PAU truth photon object
+ */
+
+
+#ifndef PHOTOND3PDMAKER_PAUTRUTHPHOTONASSOCIATIONTOOL_H
+#define PHOTOND3PDMAKER_PAUTRUTHPHOTONASSOCIATIONTOOL_H
+
+
+#include "D3PDMakerInterfaces/ICollectionGetterTool.h"
+#include "D3PDMakerUtils/SingleAssociationTool.h"
+#include "EventKernel/INavigable4Momentum.h"
+#include "GaudiKernel/ToolHandle.h"
+
+namespace PAU {
+  class egammaTruth;
+}
+
+namespace D3PD {
+
+
+/**
+ * @brief Associate to particle closest in DR.
+ *
+ * This is a single association tool.
+ * Given an @c INavigable4Momentum object and a container of PAU::egamma objects,
+ * return the object in the container that is associated with the original object.
+ *
+ * Parameters:
+ *  Getter - ICollectionGetterTool instance defining the target collection.
+ *
+ */
+class PAUTruthPhotonAssociationTool
+  : public SingleAssociationTool<INavigable4Momentum, PAU::egammaTruth>
+{
+public:
+  typedef SingleAssociationTool<INavigable4Momentum, PAU::egammaTruth> Base;
+
+
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  PAUTruthPhotonAssociationTool (const std::string& type,
+				 const std::string& name,
+				 const IInterface* parent);
+
+
+  /// Standard Gaudi initialize method.
+  virtual StatusCode initialize();
+
+
+  /**
+   * @brief Create any needed tuple variables.
+   */
+  virtual StatusCode book();
+
+
+  /**
+   * @brief Return the target object.
+   * @param p The source object for the association.
+   *
+   * Return the target of the association, or 0.
+   */
+  virtual const PAU::egammaTruth* get (const INavigable4Momentum& p);
+
+
+private:
+  /// Property: The getter for the target collection.
+  ToolHandle<ICollectionGetterTool> m_getter;
+};
+
+
+} // namespace D3PD
+
+
+
+#endif // not PHOTOND3PDMAKER_PAUTRUTHPHOTONASSOCIATIONTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUTruthPhotonFillerTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUTruthPhotonFillerTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..fc101bb1fc453a781ba93c0f05ada1bcc86035d2
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUTruthPhotonFillerTool.cxx
@@ -0,0 +1,125 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/PAUTruthPhotonFillerTool.h
+ * @author Mike Hance <hance@hep.upenn.edu>
+ * @date January, 2011
+ * @brief Fill PAU related variables
+ */
+
+
+#include "PAUTruthPhotonFillerTool.h"
+#include "AthenaKernel/errorcheck.h"
+
+#include "PhotonAnalysisUtils/PAUegammaTruth.h"
+
+namespace D3PD {
+
+
+/**
+ * @brief Standard Gaudi tool constructor.
+ * @param type The name of the tool type.
+ * @param name The tool name.
+ * @param parent The tool's Gaudi parent.
+ */
+PAUTruthPhotonFillerTool::PAUTruthPhotonFillerTool (const std::string& type,
+						    const std::string& name,
+						    const IInterface* parent)
+  : BlockFillerTool<PAU::egammaTruth> (type, name, parent)
+{
+  m_fillNewVars = true;
+  book().ignore(); // Avoid coverity warnings.
+
+  declareProperty( "FillNewVars", m_fillNewVars=false,
+		   "Fill isolation variables with sliding eta window for correction" );
+}
+
+
+/**
+ * @brief Book variables for this block.
+ */
+StatusCode PAUTruthPhotonFillerTool::book()
+{
+  CHECK( addVariable ("PartonIsolation15_UE"        , m_partonIsolation15_UE       ) );
+  CHECK( addVariable ("PartonIsolation20_UE"        , m_partonIsolation20_UE       ) );
+  CHECK( addVariable ("PartonIsolation25_UE"        , m_partonIsolation25_UE       ) );
+  CHECK( addVariable ("PartonIsolation30_UE"        , m_partonIsolation30_UE       ) );
+  CHECK( addVariable ("PartonIsolation35_UE"        , m_partonIsolation35_UE       ) );
+  CHECK( addVariable ("PartonIsolation40_UE"        , m_partonIsolation40_UE       ) );
+  CHECK( addVariable ("PartonIsolation45_UE"        , m_partonIsolation45_UE       ) );
+  CHECK( addVariable ("PartonIsolation60_UE"        , m_partonIsolation60_UE       ) );
+
+  CHECK( addVariable ("PartonIsolation15"           , m_partonIsolation15          ) );
+  CHECK( addVariable ("PartonIsolation20"           , m_partonIsolation20          ) );
+  CHECK( addVariable ("PartonIsolation25"           , m_partonIsolation25          ) );
+  CHECK( addVariable ("PartonIsolation30"           , m_partonIsolation30          ) );
+  CHECK( addVariable ("PartonIsolation35"           , m_partonIsolation35          ) );
+  CHECK( addVariable ("PartonIsolation40"           , m_partonIsolation40          ) );
+  CHECK( addVariable ("PartonIsolation45"           , m_partonIsolation45          ) );
+  CHECK( addVariable ("PartonIsolation60"           , m_partonIsolation60          ) );
+
+  CHECK( addVariable ("ParticleIsolation40"                      , m_particleIsolation40                    ) );
+  CHECK( addVariable ("ParticleIsolation40_ED_corrected"         , m_particleIsolation40_ED_corrected       ) );
+  CHECK( addVariable ("ParticleIsolation40_ED_corrected_reco"    , m_particleIsolation40_ED_corrected_reco  ) );
+
+  if(m_fillNewVars){
+    CHECK( addVariable ("ParticleIsolation40_ED_corrected_new"         , m_particleIsolation40_ED_corrected_new       ) );
+    CHECK( addVariable ("ParticleIsolation40_ED_corrected_reco_new"    , m_particleIsolation40_ED_corrected_reco_new  ) );
+  }
+
+  CHECK( addVariable ("isBremPhoton"                , m_isBremPhoton               ) );
+  CHECK( addVariable ("isHardProcPhoton"            , m_isHardProcPhoton           ) );
+
+  return StatusCode::SUCCESS;
+}
+
+
+/**
+ * @brief Fill one block --- type-safe version.
+ * @param p The input object.
+ *
+ * This is called once per object.  The caller
+ * is responsible for arranging that all the pointers for booked variables
+ * are set appropriately upon entry.
+ */
+StatusCode PAUTruthPhotonFillerTool::fill (const PAU::egammaTruth& p)
+{
+
+  * m_partonIsolation15_UE  = p.partonIsolation15_UE;
+  * m_partonIsolation20_UE  = p.partonIsolation20_UE;
+  * m_partonIsolation25_UE  = p.partonIsolation25_UE;
+  * m_partonIsolation30_UE  = p.partonIsolation30_UE;
+  * m_partonIsolation35_UE  = p.partonIsolation35_UE;
+  * m_partonIsolation40_UE  = p.partonIsolation40_UE;
+  * m_partonIsolation45_UE  = p.partonIsolation45_UE;
+  * m_partonIsolation60_UE  = p.partonIsolation60_UE;
+
+  * m_partonIsolation15     = p.partonIsolation15   ;
+  * m_partonIsolation20     = p.partonIsolation20   ;
+  * m_partonIsolation25     = p.partonIsolation25   ;
+  * m_partonIsolation30     = p.partonIsolation30   ;
+  * m_partonIsolation35     = p.partonIsolation35   ;
+  * m_partonIsolation40     = p.partonIsolation40   ;
+  * m_partonIsolation45     = p.partonIsolation45   ;
+  * m_partonIsolation60     = p.partonIsolation60   ;
+
+  * m_particleIsolation40                     = p.particleIsolation40                   ;
+  * m_particleIsolation40_ED_corrected        = p.particleIsolation40_ED_corrected      ;
+  * m_particleIsolation40_ED_corrected_reco   = p.particleIsolation40_ED_corrected_reco ;
+
+  if(m_fillNewVars){
+    * m_particleIsolation40_ED_corrected_new        = p.particleIsolation40_ED_corrected_new      ;
+    * m_particleIsolation40_ED_corrected_reco_new   = p.particleIsolation40_ED_corrected_new_reco ;
+  }
+
+  * m_isHardProcPhoton      = p.isHardProc          ;
+  * m_isBremPhoton          = p.isBrem              ;
+
+  return StatusCode::SUCCESS;
+}
+
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUTruthPhotonFillerTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUTruthPhotonFillerTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..83669c4565b1e86f842de971de80278d2a2c201c
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PAUTruthPhotonFillerTool.h
@@ -0,0 +1,102 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/PAUTruthPhotonFiller.h
+ * @author Mike Hance <hance@hep.upenn.edu>
+ * @date January, 2011
+ * @brief Fill PAU related variables
+ */
+
+
+#ifndef PHOTOND3PDMAKER_PAUTRUTHPHOTONFILLERTOOL_H
+#define PHOTOND3PDMAKER_PAUTRUTHPHOTONFILLERTOOL_H
+
+
+#include "D3PDMakerUtils/BlockFillerTool.h"
+#include <vector>
+#include <string>
+
+namespace PAU{
+  class egammaTruth;
+}
+
+
+namespace D3PD {
+
+
+/**
+ * @brief Fill author code and related flags.
+ */
+class PAUTruthPhotonFillerTool
+  : public BlockFillerTool<PAU::egammaTruth>
+{
+public:
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  PAUTruthPhotonFillerTool (const std::string& type,
+			    const std::string& name,
+			    const IInterface* parent);
+
+
+  /// Book variables for this block.
+  virtual StatusCode book();
+
+
+  /**
+   * @brief Fill one block --- type-safe version.
+   * @param p The input object.
+   *
+   * This is called once per object.  The caller
+   * is responsible for arranging that all the pointers for booked variables
+   * are set appropriately upon entry.
+   */
+  virtual StatusCode fill (const PAU::egammaTruth& p);
+
+
+private:
+  bool m_fillNewVars;
+
+  float
+    * m_partonIsolation15_UE  ,
+    * m_partonIsolation20_UE  ,
+    * m_partonIsolation25_UE  ,
+    * m_partonIsolation30_UE  ,
+    * m_partonIsolation35_UE  ,
+    * m_partonIsolation40_UE  ,
+    * m_partonIsolation45_UE  ,
+    * m_partonIsolation60_UE  ,
+    * m_partonIsolation15  ,
+    * m_partonIsolation20  ,
+    * m_partonIsolation25  ,
+    * m_partonIsolation30  ,
+    * m_partonIsolation35  ,
+    * m_partonIsolation40  ,
+    * m_partonIsolation45  ,
+    * m_partonIsolation60  ;
+
+  float 
+    * m_particleIsolation40,
+    * m_particleIsolation40_ED_corrected,
+    * m_particleIsolation40_ED_corrected_reco,
+    * m_particleIsolation40_ED_corrected_new,
+    * m_particleIsolation40_ED_corrected_reco_new;
+
+  bool
+    * m_isHardProcPhoton,
+    * m_isBremPhoton;
+};
+
+
+} // namespace D3PD
+
+
+#endif
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonFilter.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonFilter.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..a06f9b9deb4a2eaa89520b5d4c53823bfe8d089a
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonFilter.cxx
@@ -0,0 +1,142 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include <algorithm>
+
+#include "PhotonFilter.h"
+#include "Particle/TrackParticle.h"
+#include "TrkTrackSummary/TrackSummary.h"
+#include "Particle/TrackParticleContainer.h"
+#include "egammaEvent/PhotonContainer.h"
+#include "egammaEvent/ElectronContainer.h"
+#include "egammaEvent/egammaPIDdefs.h"
+#include "muonEvent/MuonContainer.h"
+
+#include "TrkTrack/LinkToTrack.h"
+#include "TrkParticleBase/TrackParticleBaseCollection.h"
+#include "TrkParticleBase/TrackParticleBase.h"
+#include "TrkParticleBase/LinkToTrackParticleBase.h"
+#include "VxVertex/VxTrackAtVertex.h"
+
+#include "GaudiKernel/ISvcLocator.h"
+#include "GaudiKernel/StatusCode.h"
+ 
+#include "GaudiKernel/MsgStream.h"
+
+#include "AthenaKernel/errorcheck.h"
+
+#include "StoreGate/StoreGateSvc.h" 
+
+#define PI 2.*asin(1.)
+
+namespace D3PD{
+PhotonFilter::PhotonFilter(const std::string& name, 
+			   ISvcLocator* pSvcLocator) : 
+  Algorithm(name, pSvcLocator), 
+  m_storeGate(0),
+  m_ph_getter(),
+  m_PhotonNNTool("PhotonNeuralNetworkTool")
+{ 
+  declareProperty("OutputCollectionName"     , m_outputCollName   = "SelectedPhotons"      );
+  declareProperty("photonGetter"             , m_ph_getter                                 );
+  declareProperty("ptCut"                    , m_ptCut            = 20000.                 );
+  declareProperty("etaCut"                   , m_etaCut           = 2.5                    );
+  declareProperty("IsEM"                     , m_IsEM             = egammaPID::PhotonLoose );
+  declareProperty("Indices"                  , m_indices                                   );
+  declareProperty("NNCut"                    , m_NNCut            = true                   );
+
+  declareProperty ("PhotonNNTool"            , m_PhotonNNTool,
+		   "Photon neural-network helper tool.");
+}
+
+PhotonFilter::~PhotonFilter()
+{ }
+
+StatusCode PhotonFilter::initialize()
+{
+
+  MsgStream log(msgSvc(), name());
+
+
+  StatusCode sc;
+   
+   // get StoreGate 
+  sc = service("StoreGateSvc", m_storeGate);
+  if ( sc == StatusCode::FAILURE ) {
+    log<<MSG::ERROR << "   could not access StoreGate " << endreq;
+    return StatusCode::FAILURE;
+  }
+ 
+  // Retrieve the getter tool and configure it, saying that we want
+  // to get @c PAU::egamma objects from it.
+  CHECK( m_ph_getter.retrieve() );
+  CHECK( m_ph_getter->configureD3PD<Analysis::Photon>() );
+  CHECK( m_PhotonNNTool.retrieve() );
+
+  return StatusCode::SUCCESS;
+    
+}
+
+
+StatusCode PhotonFilter::finalize()
+{
+
+ return StatusCode::SUCCESS;
+}
+
+///////////////
+StatusCode PhotonFilter::execute()
+{
+  MsgStream log( messageService(), name() );
+  log << MSG::DEBUG << " in execute" << endreq;
+
+  // Record the output tracks container
+  egammaContainer* outputCont = new egammaContainer(SG::VIEW_ELEMENTS) ;
+  StatusCode sc = m_storeGate->record(outputCont, m_outputCollName) ; 
+  if(StatusCode::SUCCESS != sc ) {
+    log<<MSG::ERROR<<" unable to record output container: "<< m_outputCollName <<endreq; 
+    return sc;
+  }
+
+
+  // Get the photons
+  if (m_ph_getter->reset().isFailure()) {
+    REPORT_MESSAGE (MSG::ERROR) << "Can't reset input getter.";
+    return 0;
+  }
+
+  // now, loop over all the photons, store the eta and phi positions of qualifying photons
+  int numAcceptedObjects=0;
+  while ( const Analysis::Photon* obj = m_ph_getter->next<Analysis::Photon>()) {
+    if(accept(obj)){
+      if(m_indices.size()==0 || 
+	 std::find(m_indices.begin(),m_indices.end(),numAcceptedObjects)!=m_indices.end()){
+	outputCont->push_back(const_cast<Analysis::Photon*> (obj)); 
+      }
+      ++numAcceptedObjects;
+    }
+  }
+
+  return sc;
+}
+
+
+// Keep photons that satisfy all of the requirements.
+bool PhotonFilter::accept(const Analysis::Photon* photon){
+  if(!photon->cluster()) 
+    return false;
+  if(photon->cluster()->pt() < m_ptCut) 
+    return false;
+  if(fabs(photon->cluster()->etaBE(2)) > m_etaCut) 
+    return false;
+  
+  if(m_IsEM != 0 && !photon->passID((egammaPID::egammaIDQuality)m_IsEM)) 
+    return false;
+  if(m_NNCut  && !m_PhotonNNTool->Passes(photon)) 
+    return false;
+
+  return true;
+}
+
+}
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonFilter.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonFilter.h
new file mode 100644
index 0000000000000000000000000000000000000000..5baee8ba6824c16974610ae777b135e9ef846fc4
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonFilter.h
@@ -0,0 +1,59 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef PHOTONFILTER_H
+#define PHOTONFILTER_H
+
+#include "GaudiKernel/Algorithm.h"
+
+#include "Identifier/Identifier.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "D3PDMakerInterfaces/ICollectionGetterTool.h"
+
+#include "PhotonAnalysisUtils/IPhotonNeuralNetworkTool.h"
+
+#include "egammaEvent/egamma.h"
+#include "egammaEvent/Photon.h"
+
+#include "muonEvent/Muon.h"
+
+class StoreGateSvc; 
+
+namespace D3PD{
+class PhotonFilter: public Algorithm
+{
+public:    
+
+    PhotonFilter(const std::string& name, ISvcLocator* pSvcLocator);
+    virtual ~PhotonFilter();
+    StatusCode initialize();
+    StatusCode execute();
+    StatusCode finalize();
+
+private: 
+
+    std::string     m_outputCollName;      //output container
+
+    float           m_ptCut;               //min photon/electron pt
+    float           m_etaCut;              //max photon/electron eta
+
+    long            m_IsEM;                //isEM cut to be applied on photons
+    bool            m_NNCut;               //neural net requirement
+
+    std::vector<int> m_indices;            //only keep a few photons that pass all other requirements, by index
+
+    StoreGateSvc* m_storeGate; 
+
+    ToolHandle<D3PD::ICollectionGetterTool> m_ph_getter;
+
+    bool           accept(const Analysis::Photon* ph);
+
+    /// Property: NN tool
+    ToolHandle<IPhotonNeuralNetworkTool> m_PhotonNNTool;
+
+};
+
+}
+
+#endif
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonPVFillerTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonPVFillerTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..ecded936232d97617800b92be07b2696578e0631
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonPVFillerTool.cxx
@@ -0,0 +1,147 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/PhotonPVFillerTool.cxx
+ * @author Jean-Francois Marchand <jean-francois.marchand@cern.ch>
+ * @date April 2011
+ * @brief Block filler tool for primary vertex kinematics, from attached tracks. Adapted from TrackD3PDMaker/src/VertexKineFillerTool.cxx
+ */
+
+
+#include "PhotonPVFillerTool.h"
+#include "Particle/TrackParticle.h"
+#include "AthenaKernel/errorcheck.h"
+
+
+using HepGeom::Vector3D;
+
+
+namespace D3PD {
+
+
+/**
+ * @brief Standard Gaudi tool constructor.
+ * @param type The name of the tool type.
+ * @param name The tool name.
+ * @param parent The tool's Gaudi parent.
+ */
+PhotonPVFillerTool::PhotonPVFillerTool
+    (const std::string& type,
+     const std::string& name,
+     const IInterface* parent)
+  : BlockFillerTool<Trk::VxCandidate> (type, name, parent)
+{
+  book().ignore(); // Avoid coverity warnings.
+}
+
+
+/**
+ * @brief Book variables for this block.
+ */
+StatusCode PhotonPVFillerTool::book()
+{
+  CHECK( addVariable ("px",            m_px          ) );
+  CHECK( addVariable ("py",            m_py          ) );
+  CHECK( addVariable ("pz",            m_pz          ) );
+  CHECK( addVariable ("E",             m_E           ) );
+  CHECK( addVariable ("m",             m_m           ) );
+  CHECK( addVariable ("nTracks",       m_nTracks     ) );
+  CHECK( addVariable ("sumPt",         m_sumPt       ) );
+  CHECK( addVariable ("sumPt2",        m_sumPt2      ) );
+  CHECK( addVariable ("type",          m_type        ) );
+  CHECK( addVariable ("missPt",        m_ptmiss      ) );
+  CHECK( addVariable ("meanPt",        m_meanpt      ) );
+  CHECK( addVariable ("nTracks_05GeV", m_nTracks05GeV) );
+  CHECK( addVariable ("nTracks_07GeV", m_nTracks07GeV) );
+  CHECK( addVariable ("nTracks_1GeV",  m_nTracks1GeV ) );
+  CHECK( addVariable ("nTracks_2GeV",  m_nTracks2GeV ) );
+
+  return StatusCode::SUCCESS;
+}
+
+
+/**
+ * @brief Fill one block --- type-safe version.
+ * @param p The input object.
+ *
+ * This is called once per object.  The caller
+ * is responsible for arranging that all the pointers for booked variables
+ * are set appropriately upon entry.
+ */
+StatusCode PhotonPVFillerTool::fill (const Trk::VxCandidate& p)
+{
+  const std::vector<Trk::VxTrackAtVertex*>* tracks = p.vxTrackAtVertex();
+  std::vector<Trk::VxTrackAtVertex*>::const_iterator begintracks = tracks->begin();
+  std::vector<Trk::VxTrackAtVertex*>::const_iterator endtracks = tracks->end();
+
+  float sumpx = 0.0; 
+  float sumpy = 0.0; 
+  float sumpz = 0.0; 
+  float sumpp = 0.0; 
+  float sumpt = 0.0;
+  float sumpt2 = 0.0;
+
+  Amg::Vector3D vecSumMom(0,0,0);
+  int Ntracks = 0;
+  int Ntracks_05GeV = 0;
+  int Ntracks_07GeV = 0;
+  int Ntracks_1GeV = 0;
+  int Ntracks_2GeV = 0;
+
+  for (std::vector<Trk::VxTrackAtVertex*>::const_iterator i = begintracks; i!=endtracks; i++) {
+
+    const Trk::Perigee* perigee = 0;
+    if ( (*i)->perigeeAtVertex() )
+      perigee = (const Trk::Perigee*) (*i)->perigeeAtVertex();
+    else
+      perigee = (const Trk::Perigee*) (*i)->initialPerigee();
+
+    sumpx += perigee->momentum().x();
+    sumpy += perigee->momentum().y();
+    sumpz += perigee->momentum().z();
+    sumpp += perigee->momentum().mag();
+    sumpt += sqrt(perigee->momentum().x()*perigee->momentum().x()+perigee->momentum().y()*perigee->momentum().y()); 
+    sumpt2 += perigee->momentum().x()*perigee->momentum().x()+perigee->momentum().y()*perigee->momentum().y();
+
+    vecSumMom += perigee->momentum();
+    if (perigee->momentum().perp()>500)  Ntracks_05GeV += 1;
+    if (perigee->momentum().perp()>700)  Ntracks_07GeV += 1;
+    if (perigee->momentum().perp()>1000) Ntracks_1GeV += 1;
+    if (perigee->momentum().perp()>2000) Ntracks_2GeV += 1;
+
+ }
+  
+  float vtxmass = sumpp*sumpp-sumpx*sumpx-sumpy*sumpy-sumpz*sumpz;
+  if (vtxmass>0.0)
+    vtxmass = std::sqrt(vtxmass);
+  else
+    vtxmass = 0.0;
+
+  Ntracks = p.vxTrackAtVertex()->size();
+  float meanPt = (Ntracks > 0 ? sumpt*1./Ntracks:0);
+  float ptmiss = vecSumMom.perp();
+
+  *m_px           = sumpx;
+  *m_py           = sumpy;
+  *m_pz           = sumpz;
+  *m_E            = sumpp;
+  *m_m            = vtxmass;
+  *m_nTracks      = p.vxTrackAtVertex()->size();
+  *m_sumPt        = sumpt;
+  *m_sumPt2       = sumpt2;
+  *m_type         = (int)p.vertexType();
+  *m_ptmiss       = ptmiss;
+  *m_meanpt       = meanPt;
+  *m_nTracks05GeV = Ntracks_05GeV;
+  *m_nTracks07GeV = Ntracks_05GeV;
+  *m_nTracks1GeV  = Ntracks_1GeV;
+  *m_nTracks2GeV  = Ntracks_2GeV;
+
+  return StatusCode::SUCCESS;
+}
+
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonPVFillerTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonPVFillerTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..d1dda9663bafd081ff760a68e116e5a39da35c53
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonPVFillerTool.h
@@ -0,0 +1,84 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/PhotonPVFillerTool.h
+ * @author Jean-Francois Marchand <jean-francois.marchand@cern.ch>
+ * @date April 2011
+ * @brief Block filler tool for primary vertex kinematics, from attached tracks. Adapted from TrackD3PDMaker/src/VertexKineFillerTool.h
+ */
+
+#ifndef PHOTOND3PDMAKER_PRIMARYVERTEXFILLERTOOL_H
+#define PHOTOND3PDMAKER_PRIMARYVERTEXFILLERTOOL_H
+
+
+#include "D3PDMakerUtils/BlockFillerTool.h"
+
+#include "VxVertex/VxCandidate.h"
+#include "VxVertex/VxTrackAtVertex.h"
+
+namespace D3PD {
+
+/**
+ * @brief Block filler tool for vertex kinematics, from attached tracks.
+ */
+class PhotonPVFillerTool
+  : public BlockFillerTool<Trk::VxCandidate>
+{
+public:
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  PhotonPVFillerTool (const std::string& type,
+                        const std::string& name,
+                        const IInterface* parent);
+  
+
+  /// Book variables for this block.
+  virtual StatusCode book();
+  
+
+  /**
+   * @brief Fill one block --- type-safe version.
+   * @param p The input object.
+   *
+   * This is called once per object.  The caller
+   * is responsible for arranging that all the pointers for booked variables
+   * are set appropriately upon entry.
+   */
+  virtual StatusCode fill (const Trk::VxCandidate& p);
+
+
+private:
+
+  /// Variables: Vertex position.
+  float* m_px;
+  float* m_py;
+  float* m_pz;
+  float* m_E;
+  float* m_m;
+  int*   m_nTracks;
+  float* m_sumPt;
+  float* m_sumPt2;
+  int*   m_type;
+  float* m_ptmiss;
+  float* m_meanpt;
+  int* m_nTracks05GeV;
+  int* m_nTracks07GeV;
+  int* m_nTracks1GeV;
+  int* m_nTracks2GeV;
+
+};
+
+
+} // namespace D3PD
+
+
+#endif // not PHOTOND3PDMAKER_PRIMARYVERTEXFILLERTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonSorterAlg.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonSorterAlg.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..553c326380a8e33b540b4e64a4b9fac19e283496
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonSorterAlg.cxx
@@ -0,0 +1,47 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/PhotonSorterAlg.cxx
+ * @author Mike Hance
+ * @date Feb, 2010
+ * @brief sorting by pt
+ */
+
+
+#include "PhotonSorterAlg.h"
+
+
+namespace D3PD {
+
+
+/**
+ * @brief Standard Gaudi algorithm constructor.
+ * @param name The algorithm name.
+ * @param svcloc The service locator.
+ */
+PhotonSorterAlg::PhotonSorterAlg (const std::string& name,
+                                      ISvcLocator* svcloc)
+  : IN4MSorterAlg<PhotonContainer> (name, svcloc)
+{
+  declareProperty("RemoveTopoClusterCandidates",   m_remove_TopoCluster_candidates);
+}
+
+/**
+ * @brief Store the element in the output list
+ */
+StatusCode PhotonSorterAlg::addElement (const INavigable4Momentum* ptr)
+{
+
+  // apply any filters
+  if(m_remove_TopoCluster_candidates){
+    const Analysis::Photon* phot = dynamic_cast<const Analysis::Photon*>(ptr);
+    if(phot && phot->author() == 128) return StatusCode::SUCCESS;
+  }
+
+  return IN4MSorterAlg<PhotonContainer>::addElement(ptr);
+}
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonSorterAlg.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonSorterAlg.h
new file mode 100644
index 0000000000000000000000000000000000000000..013663853b89e89e3a782aba327e00449887741d
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonSorterAlg.h
@@ -0,0 +1,53 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/PhotonSorterAlg.h
+ * @author Mike Hance
+ * @date Feb, 2011
+ * @brief sort by pt
+ */
+
+
+#ifndef PHOTOND3PDMAKER_PHOTONSORTERALG_H
+#define PHOTOND3PDMAKER_PHOTONSORTERALG_H
+
+
+#include "IN4MSorterAlg.h"
+#include "egammaEvent/PhotonContainer.h"
+
+
+namespace D3PD {
+
+
+/**
+ * @brief Recalculate OQ flags for Photon objects.
+ */
+class PhotonSorterAlg
+  : public IN4MSorterAlg<PhotonContainer>
+{
+public:
+  /**
+   * @brief Standard Gaudi algorithm constructor.
+   * @param name The algorithm name.
+   * @param svcloc The service locator.
+   */
+  PhotonSorterAlg (const std::string& name,
+                     ISvcLocator* svcloc);
+
+  virtual StatusCode addElement(const INavigable4Momentum* ptr);
+
+private:
+  
+  bool m_remove_TopoCluster_candidates;
+};
+
+
+} // namespace D3PD
+
+
+#endif // not PHOTOND3PDMAKER_PHOTONSORTERALG_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonTruthParticleFilterTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonTruthParticleFilterTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..76ee678e2fef2dc634e1104be18633df6184122e
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonTruthParticleFilterTool.cxx
@@ -0,0 +1,374 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/PhotonTruthParticleFilterTool.cxx
+ * @author Mike Hance <mike.hance@cern.ch>
+ * @date August 2010
+ * @brief Filter truth particles for writing to D3PD.
+ */
+
+
+#include "PhotonTruthParticleFilterTool.h"
+#include "GeneratorObjects/McEventCollection.h"
+#include "AthenaKernel/errorcheck.h"
+#include "HepMC/GenEvent.h"
+#include "HepMC/GenVertex.h"
+#include "HepMC/GenParticle.h"
+#include "boost/foreach.hpp"
+#include <utility>
+
+
+namespace {
+
+
+const int PARTONPDGMAX = 43;
+const int NPPDGMIN = 1000000;
+const int NPPDGMAX = 8999999;
+const int PHOTOSMIN = 10000;
+const int GEANTMIN = 200000;
+
+
+} // anonymous namespace
+
+
+namespace D3PD {
+
+
+/**
+ * @brief Standard Gaudi tool constructor.
+ * @param type The name of the tool type.
+ * @param name The tool name.
+ * @param parent The tool's Gaudi parent.
+ */
+PhotonTruthParticleFilterTool::PhotonTruthParticleFilterTool
+  (const std::string& type,
+   const std::string& name,
+   const IInterface* parent)
+    : AthAlgTool (type, name, parent),
+      m_resolver (name, evtStore(), m_mcEventsName),
+      m_firstHadronBarcode(0)
+{
+  declareProperty( "McEvents",       
+		   m_mcEventsName = "GEN_AOD",
+		   "Name of the input McEventCollection we want to filter" );
+
+  declareProperty( "McEventsOutput", 
+		   m_mcEventsOutputName = "GEN_D3PD",
+		   "Name of the output McEventCollection which has been filtered" );
+
+  declareProperty( "DoPileup",
+                   m_doPileup = false,
+                   "If true, include particles from pileup/cavern.");
+
+  declareProperty ("RemoveEmpty",
+                   m_removeEmpty = true,
+                   "If true, remove empty GenEvent structures.");
+
+  declareProperty ("DoEtIsolations",
+                   m_doEtIsolations = false,
+                   "Unused, but required by configuration script.");
+
+  declareProperty ("WritePartons",
+                   m_writePartons = true,
+                   "Keep partons?");
+
+  declareProperty ("WriteHadrons",
+                   m_writeHadrons = false,
+                   "Keep hadrons?");
+
+  declareProperty ("WriteGeant",
+                   m_writeGeant = false,
+                   "Keep geant particles?");
+
+  declareProperty ("ParticleFilters",
+		   m_particleFilters,
+		   "Filters to keep certain types of particles");
+
+  m_haveSeenAHadron = false;
+}
+
+
+/**
+ * @brief Standard Gaudi @c queryInterface method.
+ */
+StatusCode
+PhotonTruthParticleFilterTool::queryInterface( const InterfaceID& riid, void** ppvIf )
+{
+  if ( riid == ITruthParticleFilterTool::interfaceID() )  {
+    *ppvIf = static_cast<ITruthParticleFilterTool*> (this);
+    addRef();
+    return StatusCode::SUCCESS;
+  }
+
+  return AlgTool::queryInterface( riid, ppvIf );
+}
+
+
+/**
+ * @brief Standard Gaudi initialize method.
+ */
+StatusCode PhotonTruthParticleFilterTool::initialize()
+{
+  CHECK( m_resolver.initialize<McEventCollection>() );
+  return AthAlgTool::initialize();
+}
+
+
+/**
+ * @brief Standard Gaudi finalize method.
+ */
+StatusCode PhotonTruthParticleFilterTool::finalize()
+{
+  return AthAlgTool::finalize();
+}
+
+
+/**
+ * @brief Standard Gaudi execute method.
+ */
+StatusCode PhotonTruthParticleFilterTool::execute()
+{
+  m_haveSeenAHadron = false;
+  m_firstHadronBarcode = 0;
+
+  // Fetch input collection.
+  const McEventCollection* mc_in;
+  CHECK( evtStore()->retrieve (mc_in, m_resolver.key()) );
+
+  // Create output collection.
+  McEventCollection* mc_out = new McEventCollection;
+  CHECK( evtStore()->record (mc_out, m_mcEventsOutputName) );
+  CHECK( evtStore()->setConst (mc_out) );
+
+  // Copy and filter.
+  CHECK( buildMcAod (mc_in, mc_out) );
+  return StatusCode::SUCCESS;
+}
+
+
+/**
+ *  This method will check the validity of the input McEventCollection 
+ *  and build a filtered one from the strategy implemented by the 
+ *  concrete tool.
+ *  It is not const to allow derived tools to build statistics during
+ *  the filtering process.
+ */
+StatusCode
+PhotonTruthParticleFilterTool::buildMcAod (const McEventCollection* mc_in,
+                                     McEventCollection* mc_out)
+{
+  // Loop over GenEvent's.
+  mc_out->reserve (mc_in->size());
+  BOOST_FOREACH (const HepMC::GenEvent* ev_in, *mc_in) {
+    if (!ev_in) continue;
+
+    // Copy the GenEvent.
+    HepMC::GenEvent* ev_out = new HepMC::GenEvent (ev_in->signal_process_id(),
+                                                   ev_in->event_number());
+    ev_out->set_event_scale (ev_in->event_scale());
+    ev_out->set_alphaQCD (ev_in->alphaQCD());
+    ev_out->set_alphaQED (ev_in->alphaQED());
+    ev_out->weights() = ev_in->weights();
+    ev_out->set_random_states (ev_in->random_states());
+    if (ev_in->heavy_ion())
+      ev_out->set_heavy_ion (*ev_in->heavy_ion());
+    if (ev_in->pdf_info())
+      ev_out->set_pdf_info (*ev_in->pdf_info());
+
+    // Copy and filter the contents.
+    CHECK( filterEvent (ev_in, ev_out) );
+
+    // Maybe throw out empty GenEvent's.
+    if (m_removeEmpty && ev_out->particles_empty())
+      delete ev_out;
+    else
+      mc_out->push_back (ev_out);
+
+    // If we don't want pileup, only do the first GenEvent.
+    if (!m_doPileup)
+      break;
+  }
+  return StatusCode::SUCCESS;
+}
+
+
+/**
+ * @brief Filter a single @c GenEvent.
+ */
+StatusCode
+PhotonTruthParticleFilterTool::filterEvent (const HepMC::GenEvent* ev_in,
+                                      HepMC::GenEvent* ev_out)
+{
+  // Loop over particles.
+  // (FOREACH doesn't work here because particle_const_iterator
+  // isn't consistent in the use of const...)
+  for (HepMC::GenEvent::particle_const_iterator ip = ev_in->particles_begin();
+       ip != ev_in->particles_end();
+       ++ip)
+  {
+    // Copy the particle if we want to keep it.
+    if (acceptParticle (*ip))
+      CHECK( addParticle (*ip, ev_out) );
+  }
+  return StatusCode::SUCCESS;
+}
+
+
+/**
+ * @brief Add a @c GenParticle (and its production vertex) to a @c GenEvent.
+ */
+StatusCode
+PhotonTruthParticleFilterTool::addParticle (const HepMC::GenParticle* p,
+                                      HepMC::GenEvent* ev)
+{
+  // Add parent vertex if it exists.  Otherwise, add decay vertex.
+  if (p->production_vertex())
+    CHECK( addVertex (p->production_vertex(), ev) );
+  else if (p->end_vertex())
+    CHECK( addVertex (p->end_vertex(), ev) );
+  else {
+    REPORT_MESSAGE (MSG::ERROR) << "Encountered GenParticle with no vertices!";
+    return StatusCode::FAILURE;
+  }
+
+  // Find the particle in the event.
+  // If it doesn't exist yet, copy it.
+  HepMC::GenParticle* pnew = ev->barcode_to_particle (p->barcode());
+  if (!pnew)
+    pnew = new HepMC::GenParticle (*p);
+
+  // Add ourself to our vertices.
+  if (p->production_vertex()) {
+    HepMC::GenVertex* v =
+      ev->barcode_to_vertex (p->production_vertex()->barcode());
+    if (v)
+      v->add_particle_out (pnew);
+  }
+
+  if (p->end_vertex()) {
+    HepMC::GenVertex* v =
+      ev->barcode_to_vertex (p->end_vertex()->barcode());
+    if (v)
+      v->add_particle_in (pnew);
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+
+/**
+ * @brief Add a @c GenVertex to a @c GenEvent.
+ */
+StatusCode
+PhotonTruthParticleFilterTool::addVertex (const HepMC::GenVertex* v,
+                                    HepMC::GenEvent* ev)
+{
+  // See if this vertex has already been copied.
+  HepMC::GenVertex* vnew = ev->barcode_to_vertex (v->barcode());
+  if (!vnew) {
+    // No ... make a new one.
+    vnew = new HepMC::GenVertex;
+    vnew->set_position (v->position());
+    vnew->set_id (v->id());
+    vnew->suggest_barcode (v->barcode());
+    vnew->weights() = v->weights();
+    ev->add_vertex (vnew);
+
+    // Fill in the existing relations of the new vertex.
+    BOOST_FOREACH(const HepMC::GenParticle* p,
+                  std::make_pair (v->particles_in_const_begin(),
+                                  v->particles_in_const_end()))
+    {
+      HepMC::GenParticle* pnew = ev->barcode_to_particle (p->barcode());
+      if (pnew)
+        vnew->add_particle_in (pnew);
+    }
+
+    BOOST_FOREACH(const HepMC::GenParticle* p,
+                  std::make_pair (v->particles_out_const_begin(),
+                                  v->particles_out_const_end()))
+    {
+      HepMC::GenParticle* pnew = ev->barcode_to_particle (p->barcode());
+      if (pnew)
+        vnew->add_particle_out (pnew);
+    }
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+
+/**
+ * @brief Test to see if we want to keep a particle.
+ */
+bool
+PhotonTruthParticleFilterTool::acceptParticle (const HepMC::GenParticle* p)
+{
+  bool ok = false;
+
+  int pdg_id = std::abs (p->pdg_id());
+  int status = p->status();
+  int barcode = p->barcode();
+
+  if (p->barcode() > GEANTMIN && !m_writeGeant)
+    return false;
+  
+  // are we at parton/hadron level?
+  if ( status!=3 && pdg_id > PARTONPDGMAX && !m_haveSeenAHadron ) {
+    m_haveSeenAHadron = true;
+    m_firstHadronBarcode = barcode;
+  }
+
+  // OK if we select partons and are at beginning of event record
+  if( m_writePartons /*&& !m_haveSeenAHadron */ &&
+      (pdg_id <= PARTONPDGMAX || (pdg_id >= NPPDGMIN && pdg_id <= NPPDGMAX) ))
+    ok = true;
+
+  //  OK if we should select hadrons and are in hadron range 
+  if( m_writeHadrons && m_haveSeenAHadron && barcode < PHOTOSMIN )
+    ok = true;
+ 
+  // PHOTOS range: check whether photons come from parton range or 
+  // hadron range
+  int motherBarcode = 999999999;
+  if( barcode > PHOTOSMIN && barcode < GEANTMIN &&
+      p->production_vertex() ) {
+    const HepMC::GenVertex* vprod = p->production_vertex();
+    if (vprod->particles_in_size() > 0) {
+      const HepMC::GenParticle* mother = *vprod->particles_in_const_begin();
+      if (mother) 
+        motherBarcode = mother->barcode();
+    }
+    if( m_writePartons && motherBarcode < m_firstHadronBarcode )
+      ok = true;
+    if( m_writeHadrons && motherBarcode >= m_firstHadronBarcode )
+      ok = true;
+  }
+
+  // OK if we should select G4 particles and are in G4 range
+  if( m_writeGeant && barcode > GEANTMIN )
+    ok = true;
+
+  using namespace std;
+
+  if(ok) return ok;
+
+
+  // now, if we're still not sure if we should keep this particle, go through some checks
+  ToolHandleArray<ITruthParticleFilterCutTool>::iterator cut_iter   ;
+  ToolHandleArray<ITruthParticleFilterCutTool>::iterator cut_iter_E = m_particleFilters.end();
+  for(cut_iter = m_particleFilters.begin(); cut_iter != cut_iter_E; ++cut_iter){
+    if((*cut_iter)->passesCut(p)){
+      ok = true;
+      break;
+    }
+  }
+  
+  return ok;
+}
+
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonTruthParticleFilterTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonTruthParticleFilterTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..5f5cd3c55ef827bbed964b548ab4dbdf88ef7a17
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/PhotonTruthParticleFilterTool.h
@@ -0,0 +1,146 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/PhotonTruthParticleFilterTool.h
+ * @author Mike Hance <michael.hance@cern.ch>
+ * @date August 2010
+ * @brief Filter truth particles for writing to D3PD.  Based on TruthParticleFilterTool in EventCommonD3PDMaker
+ */
+
+
+#ifndef PHOTOND3PDMAKER_PHOTONTRUTHPARTICLEFILTERTOOL_H
+#define PHOTOND3PDMAKER_PHOTONTRUTHPARTICLEFILTERTOOL_H
+
+#include "D3PDMakerUtils/SGKeyResolver.h"
+#include "McParticleKernel/ITruthParticleFilterTool.h"
+#include "PhotonD3PDMaker/ITruthParticleFilterCutTool.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+
+#include <string>
+class McEventCollection;
+namespace HepMC {
+  class GenEvent;
+  class GenVertex;
+  class GenParticle;
+}
+
+
+namespace D3PD {
+
+/**
+ * @brief Filter truth particles for writing to D3PD.
+ *
+ * This is used as part of @c TruthParticleBuilder.
+ *
+ * This tool retrieves a @c McEventCollection, filters it, and
+ * writes a new one.
+ *
+ * The @c TruthParticleBuilder will then turn the filtered
+ * @c McEventCollection into a @c TruthParticleContainer.
+ *
+ * Most of the code here is just copying the @c McEventCollection ---
+ * that should be factored out somehow.
+ */
+class PhotonTruthParticleFilterTool
+  : public ITruthParticleFilterTool, public AthAlgTool
+{
+public:
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  PhotonTruthParticleFilterTool (const std::string& type,
+				 const std::string& name,
+				 const IInterface* parent);
+
+
+  /// Standard Gaudi @c queryInterface method.
+  virtual StatusCode queryInterface( const InterfaceID& riid,
+                                     void** ppvIf );
+
+  /// Standard Gaudi initialize method.
+  virtual StatusCode initialize();
+
+  /// Standard Gaudi finalize  method.
+  virtual StatusCode finalize();
+
+  /// Run the tool.
+  virtual StatusCode execute();
+
+
+  /** This method will check the validity of the input McEventCollection 
+   *  and build a filtered one from the strategy implemented by the 
+   *  concrete tool.
+   *  It is not const to allow derived tools to build statistics during
+   *  the filtering process.
+   */
+  virtual StatusCode buildMcAod( const McEventCollection* in,
+				 McEventCollection* filtered );
+
+
+private:
+  /// Filter a single @c GenEvent.
+  StatusCode filterEvent (const HepMC::GenEvent* ev_in,
+                          HepMC::GenEvent* ev_out);
+
+  /// Add a @c GenParticle (and its production vertex) to a @c GenEvent.
+  StatusCode addParticle (const HepMC::GenParticle* p,
+                          HepMC::GenEvent* ev);
+
+  /// Add a @c GenVertex to a @c GenEvent.
+  StatusCode addVertex (const HepMC::GenVertex* p,
+                        HepMC::GenEvent* ev);
+
+  /// Test to see if we want to keep a particle.
+  bool acceptParticle (const HepMC::GenParticle* p);
+
+  /// Parameter: SG key for input @c McEventCollection.
+  std::string m_mcEventsName;
+
+  /// Helper to resolve SG key for input collection.
+  SGKeyResolver m_resolver;
+
+  /// Parameter: SG key for output @c McEventCollection.
+  std::string m_mcEventsOutputName;
+
+  /// Parameter: Keep pileup @c GenEvent's?
+  bool m_doPileup;
+
+  /// Parameter: Remove @c GenEvent's with no particles?
+  bool m_removeEmpty;
+
+  /// Unused parameter (but required by configuration code).
+  bool m_doEtIsolations;
+
+  /// Parameter: Keep partons?
+  bool m_writePartons;
+
+  /// Parameter: Keep hadrons?
+  bool m_writeHadrons;
+
+  /// Parameter: Keep geant particles?
+  bool m_writeGeant;
+
+  /// Set when we see the first hadron.
+  bool m_haveSeenAHadron;
+
+  /// Set when we see the first hadron.
+  int m_firstHadronBarcode;
+
+  /// Particle filters
+  ToolHandleArray<ITruthParticleFilterCutTool> m_particleFilters;
+};
+
+
+} // namespace D3PD
+
+
+#endif // not PHOTONTRUTHPARTICLEFILTERTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ShowerRadiusFillerTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ShowerRadiusFillerTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..d876c32a6666551a9bc334443f6f4fc1af8b5074
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ShowerRadiusFillerTool.cxx
@@ -0,0 +1,118 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/ShowerRadiusFillerTool.cxx
+ * @author Jean-Francois Marchadn <jean-francois.marchand@cern.ch>
+ * @date May, 2013
+ * @brief Block filler tool for shower radius in layer 2
+ */
+
+
+#include "ShowerRadiusFillerTool.h"
+#include "CaloEvent/CaloCluster.h"
+#include "AthenaKernel/errorcheck.h"
+#include <typeinfo>
+#include "CaloDetDescr/CaloDetDescrManager.h"
+
+
+namespace D3PD {
+
+
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  ShowerRadiusFillerTool::ShowerRadiusFillerTool (const std::string& type,
+					const std::string& name,
+					const IInterface* parent)
+    : BlockFillerTool<CaloCluster> (type, name, parent)
+  {
+    book().ignore(); // Avoid coverity warnings
+  }
+
+
+  /**
+   * @brief Book variables for this block.
+   */
+  StatusCode ShowerRadiusFillerTool::book()
+  {
+    CHECK( addVariable ("radius_s1",     m_radius_s1)  );
+    CHECK( addVariable ("radius_s2",     m_radius_s2)  );
+
+    return StatusCode::SUCCESS;
+  }
+
+
+  /**
+   * @brief Fill one block --- type-safe version.
+   * @param p The input object.
+   *
+   * This is called once per object.  The caller
+   * is responsible for arranging that all the pointers for booked variables
+   * are set appropriately upon entry.
+   */
+  StatusCode ShowerRadiusFillerTool::fill (const CaloCluster& p)
+  {
+    const CaloDetDescrManager* calodet = CaloDetDescrManager::instance();
+    CaloCell_ID::CaloSample layer1, layer2;
+    if (p.inBarrel() && ! p.inEndcap()) {
+      layer1 = CaloCell_ID::EMB1;
+      layer2 = CaloCell_ID::EMB2;
+    } else if (p.inEndcap() && !p.inBarrel()) {
+      layer1 = CaloCell_ID::EME1;
+      layer2 = CaloCell_ID::EME2;
+    } else {
+      double eBarrel = p.getVariable(CaloVariableType::ENERGY, CaloSampling::EMB2,true);
+      double eEndCap = p.getVariable(CaloVariableType::ENERGY, CaloSampling::EME2,true);
+      if (eEndCap>= eBarrel) {
+	layer1 = CaloCell_ID::EME1;
+	layer2 = CaloCell_ID::EME2;
+      } else {
+	layer1 = CaloCell_ID::EMB1;
+	layer2 = CaloCell_ID::EMB2;
+      }
+    }
+
+    double radius_s2 = 0;
+    const CaloDetDescrElement* element2 = calodet->get_element(layer2,p.eta(),p.phi());
+    if (element2) {
+      if (layer2==CaloCell_ID::EMB2) radius_s2 = element2->r()-element2->dr();
+      else
+	if (std::fabs(p.eta())>0.)
+	  radius_s2 = (std::fabs(element2->z())-std::fabs(element2->dz()))/std::fabs(sinh(p.eta()));
+    }
+    *m_radius_s2 = radius_s2;
+
+    double radiusEntrance_s1 = 0;
+    const CaloDetDescrElement* element1 = calodet->get_element(layer1,p.etaBE(1),p.phiBE(2));
+    if (element1) {
+      if ( layer2 == CaloCell_ID::EME2 )
+	radiusEntrance_s1 = element1->z() - (element1->z()<0 ? -element1->dz() : element1->dz());
+      else
+	radiusEntrance_s1 = (element1->r()-element1->dr());
+    }
+    if ( std::abs (radiusEntrance_s1) < 10.) {
+      float aeta = static_cast<float> (std::abs(p.etaBE(1)));
+      if ( layer1 == CaloCell_ID::EMB1 ) {
+	if (aeta < 0.8)
+	  radiusEntrance_s1 = (1567.8 - 18.975*aeta - 17.668*aeta*aeta);
+	else
+	  radiusEntrance_s1 = (1503.2 + 71.716*aeta - 41.008*aeta*aeta);
+      } else {
+	radiusEntrance_s1 = 3760.;
+	if (p.etaBE(1) < 0.) radiusEntrance_s1 = -radiusEntrance_s1;
+      }
+    }
+    *m_radius_s1 = radiusEntrance_s1;
+
+
+    return StatusCode::SUCCESS;
+  }
+
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ShowerRadiusFillerTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ShowerRadiusFillerTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..ed3510cda5499f4875ae389b2698e4ab05c05ca1
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/ShowerRadiusFillerTool.h
@@ -0,0 +1,64 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/ShowerRadiusFillerTool.h
+ * @brief Block filler tool for shower radius in layer 2
+ */
+
+#ifndef PHOTOND3PDMAKER_SHOWERRADIUSFILLERTOOL_H
+#define PHOTOND3PDMAKER_SHOWERRADIUSFILLERTOOL_H
+
+#include <vector>
+#include "D3PDMakerUtils/BlockFillerTool.h"
+
+class CaloCluster;
+
+namespace D3PD {
+
+  /**
+   * @brief Block filler tool for a cluster
+   *
+   */
+class ShowerRadiusFillerTool
+  : public BlockFillerTool<CaloCluster>
+  {
+  public:
+    /**
+     * @brief Standard Gaudi tool constructor.
+     * @param type The name of the tool type.
+     * @param name The tool name.
+     * @param parent The tool's Gaudi parent.
+     */
+    ShowerRadiusFillerTool (const std::string& type,
+			    const std::string& name,
+			    const IInterface* parent);
+
+    /// Book variables for this block.
+    virtual StatusCode book();
+
+    /**
+     * @brief Fill one block --- type-safe version.
+     * @param p The input object.
+     *
+     * This is called once per object.  The caller
+     * is responsible for arranging that all the pointers for booked variables
+     * are set appropriately upon entry.
+     */
+    virtual StatusCode fill (const CaloCluster& c);
+
+  private:
+    /// Variable: radius 2nd layer.
+    float* m_radius_s1;
+    float* m_radius_s2;
+
+  };
+
+} // namespace D3PD
+
+
+#endif // not PHOTOND3PDMAKER_SHOWERRADIUSFILLERTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TrackFilter.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TrackFilter.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..007fc3bd32f6b384e8bffb0897924c60861f1cd9
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TrackFilter.cxx
@@ -0,0 +1,411 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include <algorithm>
+
+#include "TrackFilter.h"
+#include "Particle/TrackParticle.h"
+#include "TrkTrackSummary/TrackSummary.h"
+#include "Particle/TrackParticleContainer.h"
+#include "egammaEvent/PhotonContainer.h"
+#include "egammaEvent/ElectronContainer.h"
+#include "egammaEvent/egammaPIDdefs.h"
+#include "DataModel/ConstDataVector.h"
+#include "muonEvent/MuonContainer.h"
+
+#include "TrkTrack/LinkToTrack.h"
+#include "TrkParticleBase/TrackParticleBaseCollection.h"
+#include "TrkParticleBase/TrackParticleBase.h"
+#include "TrkParticleBase/LinkToTrackParticleBase.h"
+#include "VxVertex/VxTrackAtVertex.h"
+#include "D3PDMakerInterfaces/IObjGetterTool.h"
+
+#include "ParticleEvent/TrackParticleAssocs.h"
+
+#include "GaudiKernel/ISvcLocator.h"
+#include "GaudiKernel/StatusCode.h"
+ 
+#include "GaudiKernel/MsgStream.h"
+
+#include "AthenaKernel/errorcheck.h"
+
+#include "StoreGate/StoreGateSvc.h" 
+
+#define PI 2.*asin(1.)
+
+namespace D3PD{
+TrackFilter::TrackFilter(const std::string& name, 
+			 ISvcLocator* pSvcLocator) : 
+  Algorithm(name, pSvcLocator), 
+  m_inputTracksName("TrackParticleCandidate"),
+  m_outputTracksName("SelectedTracks"),
+  m_ptCut(10000),
+  m_etaCut(2.5),
+  m_deltaRCut(.6),
+  m_photonIsEM(egammaPID::PhotonLoose),
+  m_electronIsEM(egammaPID::ElectronTight),
+  m_storePerpTrk(true),
+  m_storeGate(0)
+{ 
+  declareProperty("InputTrackCollectionName" ,m_inputTracksName);
+  declareProperty("OutputTrackCollectionName",m_outputTracksName);
+  declareProperty("photonGetter"             ,m_ph_getter);
+  declareProperty("electronGetter"           ,m_el_getter);
+  declareProperty("muonGetter"               ,m_mu_getter);
+  declareProperty("CheckGSFTracks"           ,m_check_gsf=false);
+  declareProperty("GSFTrackParticleGetter"   ,m_gsf_getter);
+  declareProperty("GSFAssocGetter"           ,m_gsf_assoc_getter);
+  declareProperty("ptCut"                    ,m_ptCut);
+  declareProperty("etaCut"                   ,m_etaCut);
+  declareProperty("deltaRCut"                ,m_deltaRCut);
+  declareProperty("photonIsEM"               ,m_photonIsEM);
+  declareProperty("electronIsEM"             ,m_electronIsEM);
+  declareProperty("storePerpendicularTracks" ,m_storePerpTrk);
+  declareProperty("FilterTracksForMET"       ,m_filterTracksForMET=false);
+}
+
+TrackFilter::~TrackFilter()
+{ }
+
+StatusCode TrackFilter::initialize()
+{
+
+  MsgStream log(msgSvc(), name());
+
+
+  StatusCode sc;
+   
+   // get StoreGate 
+  sc = service("StoreGateSvc", m_storeGate);
+  if ( sc == StatusCode::FAILURE ) {
+    log<<MSG::ERROR << "   could not access StoreGate " << endreq;
+    return StatusCode::FAILURE;
+  }
+ 
+  // Retrieve the getter tool and configure it, saying that we want
+  // to get @c PAU::egamma objects from it.
+  CHECK( m_ph_getter.retrieve() );
+  CHECK( m_ph_getter->configureD3PD<Analysis::Photon>() );
+
+  // Retrieve the getter tool and configure it, saying that we want
+  // to get @c PAU::egamma objects from it.
+  CHECK( m_el_getter.retrieve() );
+  CHECK( m_el_getter->configureD3PD<Analysis::Electron>() );
+
+  // Retrieve the getter tool and configure it, saying that we want
+  // to get @c Analysis::Muon objects from it.
+  CHECK( m_mu_getter.retrieve() );
+  CHECK( m_mu_getter->configureD3PD<Analysis::Muon>() );
+
+  if(m_check_gsf){
+    CHECK( m_gsf_getter.retrieve() );
+    CHECK( m_gsf_getter->configureD3PD<Rec::TrackParticle>() );
+    
+    CHECK( m_gsf_assoc_getter.retrieve() );
+    CHECK( m_gsf_assoc_getter->configureD3PD<TrackParticleAssocs> () );
+  }
+
+  return StatusCode::SUCCESS;
+    
+}
+
+
+StatusCode TrackFilter::finalize()
+{
+
+ return StatusCode::SUCCESS;
+}
+
+///////////////
+StatusCode TrackFilter::execute()
+{
+  MsgStream log( messageService(), name() );
+  log << MSG::DEBUG << " in execute" << endreq;
+
+  // Get the input tracks container
+  const Rec::TrackParticleContainer* trkcoll ;
+  StatusCode sc = m_storeGate->retrieve(trkcoll, m_inputTracksName) ; 
+  if(StatusCode::SUCCESS != sc ){
+    log<<MSG::ERROR<<" unable to retrieve TrackParticle container: "<< m_inputTracksName <<endreq; 
+    return sc;
+  }
+
+  // Record the output tracks container
+  ConstDataVector<Rec::TrackParticleContainer>* outputCont =
+    new ConstDataVector<Rec::TrackParticleContainer>(SG::VIEW_ELEMENTS) ;
+  sc = m_storeGate->record(outputCont, m_outputTracksName) ; 
+  if(StatusCode::SUCCESS != sc ) 
+    {
+      log<<MSG::ERROR<<" unable to record Tracks container: "<< m_outputTracksName <<endreq; 
+      return sc;
+    }
+
+  // clean vectors
+  etas.clear();
+  phis.clear();
+
+  // a vector to keep track of the tracks from electrons, muons and photons that pass our basic selection
+  std::vector<const Rec::TrackParticle*> electron_muon_photon_tracks;
+
+  // Get the photons
+  if (m_ph_getter->reset().isFailure()) {
+    REPORT_MESSAGE (MSG::ERROR) << "Can't reset input getter.";
+    return 0;
+  }
+
+  // now, loop over all the photons, store the eta and phi positions of qualifying photons
+  //const Analysis::Photon* eout = 0;
+  while ( const Analysis::Photon* obj = m_ph_getter->next<Analysis::Photon>()) {
+
+    // keep all tracks corresponding to conversions.
+    int nConversions = obj->nConversions();
+    for(int conv_iter=0; conv_iter<nConversions; conv_iter++){
+      const Trk::VxCandidate* vtx = obj->conversion(conv_iter);
+      if(vtx){
+	const std::vector<Trk::VxTrackAtVertex*>* trklist = vtx->vxTrackAtVertex();
+	for(unsigned int trkiter = 0; trkiter < trklist->size(); trkiter++){
+	  Trk::VxTrackAtVertex* trk = (*trklist)[trkiter];
+	  Trk::ITrackLink* link = trk->trackOrParticleLink();
+	  const Trk::LinkToTrackParticleBase* tr_part = dynamic_cast<const Trk::LinkToTrackParticleBase*>(link);
+	  if(!tr_part || !(*tr_part)) continue;
+	  const Rec::TrackParticle* tp = dynamic_cast<const Rec::TrackParticle*>(**tr_part);
+	  if(tp) electron_muon_photon_tracks.push_back(tp);
+	}
+      }
+    }
+
+    // only keep the rest of the tracks if they're nearby an interesting photon
+    if(fabs(obj->cluster()->etaBE(2))>m_etaCut) continue;
+    if(obj->cluster()->pt() < m_ptCut) continue;
+    if(obj->isem(m_photonIsEM)!=0) continue;
+
+    fillDirection((egamma*)obj);
+  }
+
+  // Get the electrons
+  if (m_el_getter->reset().isFailure()) {
+    REPORT_MESSAGE (MSG::ERROR) << "Can't reset input getter.";
+    return 0;
+  }
+
+  // now, loop over all the electrons, store the eta and phi positions of qualifying electrons
+  //const Analysis::Electron* eout = 0;
+  while ( const Analysis::Electron* obj = m_el_getter->next<Analysis::Electron>()) {
+
+    // keep all tracks corresponding to electrons.
+    if(obj->trackParticle()){
+      electron_muon_photon_tracks.push_back(obj->trackParticle());
+    }
+
+    // only keep the rest of the tracks if they're nearby an interesting electron
+    if(fabs(obj->cluster()->etaBE(2))>m_etaCut) continue;
+    if(obj->cluster()->pt() < m_ptCut) continue;
+    if(obj->isem(m_electronIsEM)!=0) continue;
+
+    fillDirection((egamma*)obj);
+  }
+
+  // Get the muons
+  if (m_mu_getter->reset().isFailure()) {
+    REPORT_MESSAGE (MSG::ERROR) << "Can't reset input getter.";
+    return 0;
+  }
+
+  // now, loop over all the muons, store the eta and phi positions of qualifying muons
+  //const Analysis::Muon* eout = 0;
+  while ( const Analysis::Muon* obj = m_mu_getter->next<Analysis::Muon>()) {
+
+    // keep all tracks corresponding to muons.
+    if(obj->track()){
+      electron_muon_photon_tracks.push_back(obj->track());
+    }
+
+    // only keep the rest of the tracks if they're nearby an interesting muons
+    if(obj->pt() < m_ptCut) continue;
+
+    fillDirection((Analysis::Muon*)obj);
+  }
+
+  if(m_check_gsf){
+    // Get the tracks
+    if (m_gsf_getter->reset().isFailure()) {
+      REPORT_MESSAGE (MSG::ERROR) << "Can't reset input getter.";
+      return 0;
+    }
+
+    // finally, check the GSF-refitted particles, so we can keep the original tracks
+    // from the refits
+    const TrackParticleAssocs* assocs = m_gsf_assoc_getter->get<TrackParticleAssocs>();
+    if (assocs) {
+      while ( const Rec::TrackParticle* track = m_gsf_getter->next<Rec::TrackParticle>()){
+
+	if (track->info().trackFitter() != Trk::TrackInfo::GaussianSumFilter){
+	  REPORT_MESSAGE (MSG::VERBOSE) << "Not a GSF track.  Skipping.";
+	  break;
+	}
+      
+	TrackParticleAssocs::asso_iterator beg = assocs->beginAssociation (track);
+	TrackParticleAssocs::asso_iterator end = assocs->endAssociation (track);
+	const Rec::TrackParticle* ret = 0;
+	if (beg != end && beg.isValid())
+	  ret = dynamic_cast<const Rec::TrackParticle*> (*beg);
+	if (ret){
+	  electron_muon_photon_tracks.push_back(ret);
+	}
+	else{
+	  REPORT_MESSAGE (MSG::INFO) << "No original track.";
+	}
+      }
+
+      m_gsf_assoc_getter->releaseObject (assocs);
+    }
+    else{
+      REPORT_MESSAGE (MSG::INFO) << "No GSF track assocs.";
+    }
+  }
+  else{
+    REPORT_MESSAGE (MSG::INFO) << "No GSF tracks.";
+  }
+
+  // if there are no qualifying photons/electrons/muons, no need to look any further
+  if(etas.size() == 0 && electron_muon_photon_tracks.size() == 0) return sc;
+
+  // now loop over all the tracks, and keep the ones that are within m_deltaRCut of at least one of the qualifying photons
+  Rec::TrackParticleContainer::const_iterator f_trk = trkcoll->begin();
+  Rec::TrackParticleContainer::const_iterator l_trk = trkcoll->end();
+  
+  for ( ; f_trk!=l_trk; ++f_trk) {
+    const Rec::TrackParticle* track = (*f_trk);
+
+    if (m_filterTracksForMET) {
+
+      // Following harcoded cuts from Claire and Rachid, to get tracks to be used for TrackMET
+      double trk_theta = track->measuredPerigee()->parameters()[Trk::theta];
+      double trk_qOverP = track->measuredPerigee()->parameters()[Trk::qOverP];
+      double trk_pt = fabs(1.0/trk_qOverP) * sin(trk_theta) ;
+      double trk_eta = track->eta();
+      int trk_nPixHits = track->trackSummary()->get(Trk::numberOfPixelHits);
+      int trk_nSCTHits = track->trackSummary()->get(Trk::numberOfSCTHits);
+
+      if ( trk_pt>500 && fabs(trk_eta)<2.5 && trk_nPixHits>=1 && trk_nSCTHits>=6 ) {
+	outputCont->push_back(const_cast<Rec::TrackParticle*>(track));	
+      } else {
+	// let's make sure we store the tracks that correspond to the electron, muon or the converted photon
+	bool foundtrack=false;
+	for(unsigned int epiter = 0; epiter < electron_muon_photon_tracks.size(); epiter++){
+	  const Rec::TrackParticle* eptrack = electron_muon_photon_tracks[epiter];
+	  
+	  if(track->hasSameAthenaBarCodeExceptVersion(*eptrack) || track==eptrack){
+	    outputCont->push_back(const_cast<Rec::TrackParticle*>(track));
+	    foundtrack=true;
+	    break;
+	  }
+	}
+	if(foundtrack) continue;
+	
+	for(unsigned int i=0; i<etas.size(); i++){
+	  float deltaR = sqrt( pow(etas[i]-track->eta()            ,2.) +
+			       pow(acos(cos(phis[i]-track->phi() )),2.) );
+	  if( deltaR < m_deltaRCut ){
+	    // FIXME: cast needed for copying between containers
+	    outputCont->push_back(const_cast<Rec::TrackParticle*> (track)); 
+	    break;
+	  }
+	}     
+      }
+      
+    } else {
+      // let's make sure we store the tracks that correspond to the electron, muon or the converted photon
+      bool foundtrack=false;
+      for(unsigned int epiter = 0; epiter < electron_muon_photon_tracks.size(); epiter++){
+	const Rec::TrackParticle* eptrack = electron_muon_photon_tracks[epiter];
+	
+	if(track->hasSameAthenaBarCodeExceptVersion(*eptrack) || track==eptrack){
+          outputCont->push_back(track); 
+	  foundtrack=true;
+	  break;
+	}
+      }
+      if(foundtrack){
+	continue;
+      }
+      
+      for(unsigned int i=0; i<etas.size(); i++){
+	float deltaR = sqrt( pow(etas[i]-track->eta()            ,2.) +
+			     pow(acos(cos(phis[i]-track->phi() )),2.) );
+	if( deltaR < m_deltaRCut ){
+	  // FIXME: cast needed for copying between containers
+	  outputCont->push_back(const_cast<Rec::TrackParticle*> (track)); 
+	  break;
+	}
+      }     
+    }
+
+  }
+
+  return sc;
+}
+
+void TrackFilter::fillDirection(egamma* obj)
+{  
+  float eta = obj->eta();
+  float phi = obj->phi();
+  float phi_perp1 = correct_phi(phi+PI/2.);
+  float phi_perp2 = correct_phi(phi-PI/2.);
+  
+  etas.push_back(eta);
+  phis.push_back(phi);
+  
+  if (m_storePerpTrk) { //store tracks close to the egamma's perpendicular region (perp. in phi)
+    etas.push_back(eta);
+    phis.push_back(phi_perp1);
+    etas.push_back(eta);
+    phis.push_back(phi_perp2);
+  }
+  
+  // consider both eta and phi directions, the egamma's object and the cluster ones
+  float eta_clus = obj->cluster()->eta();
+  float phi_clus = obj->cluster()->phi();
+  float phi_clus_perp1 = correct_phi(phi_clus+PI/2.);
+  float phi_clus_perp2 = correct_phi(phi_clus-PI/2.);
+  
+  etas.push_back(eta_clus);
+  phis.push_back(phi_clus);
+  
+  if (m_storePerpTrk) { //store tracks close to the egamma's perpendicular region (perp. in phi)
+    etas.push_back(eta_clus);
+    phis.push_back(phi_clus_perp1);
+    etas.push_back(eta_clus);
+    phis.push_back(phi_clus_perp2);
+  }
+
+}
+
+void TrackFilter::fillDirection(Analysis::Muon* obj)
+{  
+  float eta = obj->eta();
+  float phi = obj->phi();
+  float phi_perp1 = correct_phi(phi+PI/2.);
+  float phi_perp2 = correct_phi(phi-PI/2.);
+  
+  etas.push_back(eta);
+  phis.push_back(phi);
+  
+  if (m_storePerpTrk) { //store tracks close to the muons' perpendicular region (perp. in phi)
+    etas.push_back(eta);
+    phis.push_back(phi_perp1);
+    etas.push_back(eta);
+    phis.push_back(phi_perp2);
+  }
+  
+}
+
+float TrackFilter::correct_phi(float phi)
+{
+  if (phi>    PI) return phi-2.*PI;
+  if (phi<-1.*PI) return phi+2.*PI;
+  return phi;
+}
+
+}
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TrackFilter.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TrackFilter.h
new file mode 100644
index 0000000000000000000000000000000000000000..04554fd41b6d3f29d210f829c7244d0fcbb8e1ca
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TrackFilter.h
@@ -0,0 +1,68 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRACKFILTER_H
+#define TRACKFILTER_H
+
+#include "GaudiKernel/Algorithm.h"
+
+#include "Identifier/Identifier.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "D3PDMakerInterfaces/ICollectionGetterTool.h"
+
+#include "egammaEvent/egamma.h"
+#include "muonEvent/Muon.h"
+
+class StoreGateSvc; 
+
+namespace D3PD{
+class IObjGetterTool;
+
+class TrackFilter: public Algorithm
+{
+public:    
+
+    TrackFilter(const std::string& name, ISvcLocator* pSvcLocator);
+    virtual ~TrackFilter();
+    StatusCode initialize();
+    StatusCode execute();
+    StatusCode finalize();
+
+private: 
+
+    std::string     m_inputTracksName;     //track container
+    std::string     m_outputTracksName;    //output Track container
+
+    float           m_ptCut;               //min photon/electron pt
+    float           m_etaCut;              //max photon/electron eta
+    float           m_deltaRCut;           //max difference in dR between photon/electron and track
+
+    long            m_photonIsEM;          //isEM cut to be applied on photons
+    long            m_electronIsEM;        //isEM cut to be applied on electrons
+
+    bool            m_storePerpTrk;        //store tracks close to the photon/electron perpendicular region (perp. in phi)
+
+    bool            m_check_gsf;
+
+    bool            m_filterTracksForMET;
+
+    std::vector<float> etas;
+    std::vector<float> phis;
+
+    StoreGateSvc* m_storeGate; 
+
+    ToolHandle<D3PD::ICollectionGetterTool> m_ph_getter;
+    ToolHandle<D3PD::ICollectionGetterTool> m_el_getter;
+    ToolHandle<D3PD::ICollectionGetterTool> m_mu_getter;
+    ToolHandle<D3PD::ICollectionGetterTool> m_gsf_getter;
+    ToolHandle<D3PD::IObjGetterTool>        m_gsf_assoc_getter;
+
+    float correct_phi(float phi);
+    void fillDirection(egamma* obj);
+    void fillDirection(Analysis::Muon* obj);
+
+};
+}
+
+#endif
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TrackParticleParametersAtDiPhotonVertex.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TrackParticleParametersAtDiPhotonVertex.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..4564c397d20d8789ea152cab9f42eca57930aa79
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TrackParticleParametersAtDiPhotonVertex.cxx
@@ -0,0 +1,82 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TrackParticleParametersAtDiPhotonVertex.h"
+
+#include "AthenaKernel/errorcheck.h"
+#include "Particle/TrackParticle.h"
+
+namespace D3PD {
+
+
+TrackParticleParametersAtDiPhotonVertex::TrackParticleParametersAtDiPhotonVertex (const std::string& type,
+                      const std::string& name,
+                      const IInterface* parent)
+  : D3PD::BlockFillerTool<Rec::TrackParticle> (type, name, parent),
+    m_trackToVertexTool("Reco::TrackToVertex")
+{
+  // Avoid coverity warnings.
+  book().ignore();
+
+  declareProperty ("DefaultValue", m_defaultValue=0,
+                   "Default value to which to set unfilled variables.");
+  declareProperty ("TrackToVertexTool", m_trackToVertexTool);
+}
+
+StatusCode TrackParticleParametersAtDiPhotonVertex::initialize(){
+
+  CHECK( D3PD::BlockFillerTool<Rec::TrackParticle>::initialize() );
+
+  StatusCode sc = m_trackToVertexTool.retrieve();
+  if(sc.isFailure()){
+    REPORT_MESSAGE (MSG::ERROR) << "Could not retrieve TrackToVertexTool";
+    return StatusCode::FAILURE;
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode TrackParticleParametersAtDiPhotonVertex::book()
+{
+  // track parameters at perigee
+  CHECK( addVariable ("d0_wrtDiPhotonPV", m_d0, "", m_defaultValue) );
+  CHECK( addVariable ("z0_wrtDiPhotonPV", m_z0, "", m_defaultValue) );
+  CHECK( addVariable ("phi_wrtDiPhotonPV", m_phi, "", m_defaultValue) );
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode TrackParticleParametersAtDiPhotonVertex::fill (const Rec::TrackParticle& track)
+{  
+  const VxContainer* vxTES = 0;
+  CHECK( evtStore()->retrieve( vxTES , "PAUDiphotonVertexCollection" ));  
+  const Trk::VxCandidate* vxcand = vxTES->at(0);
+  if (!vxcand) {
+    REPORT_MESSAGE (MSG::DEBUG) << "Diphoton vertex is NULL";
+    return StatusCode::SUCCESS;
+  }
+  const Trk::RecVertex* theVertex = &(vxcand->recVertex());
+
+  if(theVertex) {
+    const Trk::Perigee *testPerigee = 0;
+    testPerigee = m_trackToVertexTool->perigeeAtVertex(track,theVertex->position());
+    if ( testPerigee ) {
+      *m_z0 = testPerigee->parameters()[Trk::z0];
+      *m_d0 = testPerigee->parameters()[Trk::d0];
+      *m_phi = testPerigee->parameters()[Trk::phi0];
+      delete testPerigee;
+      testPerigee = 0;
+    } else {
+      REPORT_MESSAGE (MSG::DEBUG) << "Failed to get parameters wrt primary vertex";
+      return StatusCode::SUCCESS;
+    }
+  } else {
+    REPORT_MESSAGE (MSG::DEBUG) << "Failed to retrieve the primary vertex";
+    return StatusCode::SUCCESS;
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TrackParticleParametersAtDiPhotonVertex.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TrackParticleParametersAtDiPhotonVertex.h
new file mode 100644
index 0000000000000000000000000000000000000000..5e9497e848356b0c74bec13e37d5b5df65a4bb7b
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TrackParticleParametersAtDiPhotonVertex.h
@@ -0,0 +1,49 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef PHOTOND3PDMAKER_TRACKPARTICLEPARAMETERSATDIPHOTONVERTEX_H
+#define PHOTOND3PDMAKER_TRACKPARTICLEPARAMETERSATDIPHOTONVERTEX_H
+
+#include "D3PDMakerUtils/BlockFillerTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "ITrackToVertex/ITrackToVertex.h"
+
+namespace Rec{
+  class TrackParticle;
+}
+
+namespace D3PD {
+  
+  class TrackParticleParametersAtDiPhotonVertex
+    : public D3PD::BlockFillerTool<Rec::TrackParticle>
+  {
+  public:
+    TrackParticleParametersAtDiPhotonVertex (const std::string& type,
+					     const std::string& name,
+					     const IInterface* parent);
+    virtual StatusCode initialize();
+    
+    virtual StatusCode book();
+    
+    virtual StatusCode fill (const Rec::TrackParticle &p);
+    
+  private:
+    
+    /// Parameter: Value to which to set variables if they don't get filled.
+    float m_defaultValue;
+    
+    /* NTuple variables: **/
+    // track parameters at perigee
+    float *m_d0;
+    float *m_z0;
+    float *m_phi;
+
+    /* Track to vertex extrapolator **/
+    ToolHandle<Reco::ITrackToVertex> m_trackToVertexTool;
+    
+  }; // class TrackParticleParametersAtDiPhotonVertex
+  
+} // namespace D3PD
+
+#endif // not PHOTOND3PDMAKER_TRKTRACKPARAMETERSATDIPHOTONVERTEX_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TruthExplorerAlg.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TruthExplorerAlg.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..9b0332e0df36eb676ba72ad56cdffa997ba737d0
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TruthExplorerAlg.cxx
@@ -0,0 +1,295 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: TruthExplorerAlg.cxx 502492 2012-05-25 13:19:11Z jmarchan $
+/**
+ * @file PhotonD3PDMaker/src/TruthExplorerAlg.cxx
+ * @author Mike Hance <mike.hance@cern.ch>
+ * @date June 2011
+ * @brief Calculate some different isolation values
+ */
+
+
+#include "TruthExplorerAlg.h"
+#include "D3PDMakerInterfaces/ICollectionGetterTool.h"
+#include "egammaEvent/Photon.h"
+#include "egammaEvent/Electron.h"
+#include "FourMomUtils/P4Helpers.h"
+#include "AthenaKernel/errorcheck.h"
+#include "boost/foreach.hpp"
+#include <vector>
+#include <map>
+#include <iostream>
+#include <iomanip>
+
+#include "TMath.h"
+
+#include "HepMC/GenParticle.h"
+
+namespace D3PD {
+
+TruthExplorerAlg::TruthExplorerAlg (const std::string& name,
+						ISvcLocator* svcloc)
+  : UDAlgBase (name, svcloc),
+    m_photonGetter(this),
+    m_electronGetter(this),
+    m_truthParticleGetter(this)
+{
+  declareProperty ("PAUtruthTool", m_PAUtruthTool,
+                   "PAU truth tool.");
+
+  declareProperty ("PAUCaloIsolationTool", m_PAUTruthCaloIsolationTool,
+		   "PAU calorimeter isolation correction tool.");
+
+  declareProperty ("CalculateTruthCaloIsolation", m_CalculateTruthCaloIsolation=true,
+		   "Compute the jet-area corrections for the particle-level isolation variables");
+
+  declareProperty ("RemoveNHardestJets", m_RemoveNHardestJets=0,
+		   "Ignore the N hardest jets when computing the jet-area corrections.");
+  
+  declareProperty ("PhotonGetter", m_photonGetter,
+                   "Getter instance for the photons.");
+
+  declareProperty ("ElectronGetter", m_electronGetter,
+                   "Getter instance for the electrons.");
+
+  declareProperty ("TruthParticleGetter", m_truthParticleGetter,
+                   "Getter instance for the truth particles.");
+}
+
+
+/**
+ * @brief Standard Gaudi @c initialize method.
+ */
+StatusCode TruthExplorerAlg::initialize()
+{
+  CHECK( UDAlgBase::initialize() );
+  CHECK( m_PAUtruthTool.retrieve() );
+  CHECK( m_PAUTruthCaloIsolationTool.retrieve() );
+  CHECK( m_photonGetter.retrieve() );
+  CHECK( m_electronGetter.retrieve() );
+  CHECK( m_truthParticleGetter.retrieve() );
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode TruthExplorerAlg::DecorateTruthParticle(const TruthParticle* truePart){
+
+  if(m_DecoratedTruthParticles.find(truePart) != m_DecoratedTruthParticles.end()) return StatusCode::SUCCESS;
+  
+  // conversion info 
+  m_isTruthConv = (int)m_PAUtruthTool->isConvMC( truePart, 
+						   m_XTruthConv, 
+						   m_YTruthConv, 
+						   m_RTruthConv, 
+						   m_ZTruthConv );
+
+  CHECK( deco( *truePart, "TruthConv",  m_isTruthConv) );
+  CHECK( deco( *truePart, "XTruthConv", m_XTruthConv ) );
+  CHECK( deco( *truePart, "YTruthConv", m_YTruthConv ) );
+  CHECK( deco( *truePart, "ZTruthConv", m_ZTruthConv ) );
+  CHECK( deco( *truePart, "RTruthConv", m_RTruthConv ) );
+
+  m_isHardProc     = (int)m_PAUtruthTool->isDirectPhotonMC(truePart) ;
+  m_isBrem         = (int)(!(m_isHardProc) && m_PAUtruthTool->isQuarkBremMC(truePart)) ;
+  m_isPromptPhoton = (int)m_PAUtruthTool->isPromptPhotonMC(truePart);
+
+  CHECK( deco( *truePart, "isHardProcPhoton", m_isHardProc     ) ); 
+  CHECK( deco( *truePart, "isBremPhoton"    , m_isBrem         ) );
+  CHECK( deco( *truePart, "isPromptPhoton"  , m_isPromptPhoton ) );
+  
+  //all partons in cone
+  m_partonIsolation15_UE =  m_PAUtruthTool->getPartonIsolation(truePart, 0.15, false )  ; 
+  m_partonIsolation20_UE =  m_PAUtruthTool->getPartonIsolation(truePart, 0.20, false )  ; 
+  m_partonIsolation25_UE =  m_PAUtruthTool->getPartonIsolation(truePart, 0.25, false )  ;
+  m_partonIsolation30_UE =  m_PAUtruthTool->getPartonIsolation(truePart, 0.30, false )  ;
+  m_partonIsolation35_UE =  m_PAUtruthTool->getPartonIsolation(truePart, 0.35, false )  ; 
+  m_partonIsolation40_UE =  m_PAUtruthTool->getPartonIsolation(truePart, 0.40, false )  ; 
+  m_partonIsolation45_UE =  m_PAUtruthTool->getPartonIsolation(truePart, 0.45, false )  ; 
+  m_partonIsolation60_UE =  m_PAUtruthTool->getPartonIsolation(truePart, 0.60, false )  ;
+
+  CHECK( deco( *truePart, "PartonIsolation15_UE",  m_partonIsolation15_UE ) );
+  CHECK( deco( *truePart, "PartonIsolation20_UE",  m_partonIsolation20_UE ) );
+  CHECK( deco( *truePart, "PartonIsolation25_UE",  m_partonIsolation25_UE ) );
+  CHECK( deco( *truePart, "PartonIsolation30_UE",  m_partonIsolation30_UE ) );
+  CHECK( deco( *truePart, "PartonIsolation35_UE",  m_partonIsolation35_UE ) );
+  CHECK( deco( *truePart, "PartonIsolation40_UE",  m_partonIsolation40_UE ) );
+  CHECK( deco( *truePart, "PartonIsolation45_UE",  m_partonIsolation45_UE ) );
+  CHECK( deco( *truePart, "PartonIsolation60_UE",  m_partonIsolation60_UE ) );
+
+  //just partons from the same mother in cone      
+  m_partonIsolation15    =  m_PAUtruthTool->getPartonIsolation(truePart, 0.15, true )  ; 
+  m_partonIsolation20    =  m_PAUtruthTool->getPartonIsolation(truePart, 0.20, true )  ; 
+  m_partonIsolation30    =  m_PAUtruthTool->getPartonIsolation(truePart, 0.30, true )  ;
+  m_partonIsolation25    =  m_PAUtruthTool->getPartonIsolation(truePart, 0.25, true )  ;
+  m_partonIsolation35    =  m_PAUtruthTool->getPartonIsolation(truePart, 0.35, true )  ; 
+  m_partonIsolation40    =  m_PAUtruthTool->getPartonIsolation(truePart, 0.40, true )  ; 
+  m_partonIsolation45    =  m_PAUtruthTool->getPartonIsolation(truePart, 0.45, true )  ; 
+  m_partonIsolation60    =  m_PAUtruthTool->getPartonIsolation(truePart, 0.60, true )  ;
+
+  CHECK( deco( *truePart, "PartonIsolation15", m_partonIsolation15 ) );
+  CHECK( deco( *truePart, "PartonIsolation20", m_partonIsolation20 ) );
+  CHECK( deco( *truePart, "PartonIsolation30", m_partonIsolation30 ) );
+  CHECK( deco( *truePart, "PartonIsolation25", m_partonIsolation25 ) );
+  CHECK( deco( *truePart, "PartonIsolation35", m_partonIsolation35 ) );
+  CHECK( deco( *truePart, "PartonIsolation40", m_partonIsolation40 ) );
+  CHECK( deco( *truePart, "PartonIsolation45", m_partonIsolation45 ) );
+  CHECK( deco( *truePart, "PartonIsolation60", m_partonIsolation60 ) );
+
+  //compute particle level isolation          
+  m_particleIsolation40  = m_PAUtruthTool->getParticleIsolation(truePart, 0.40, false)  ;
+  m_particleIsolation30  = m_PAUtruthTool->getParticleIsolation(truePart, 0.30, false)  ;
+  m_particleIsolation20  = m_PAUtruthTool->getParticleIsolation(truePart, 0.20, false)  ;
+
+  CHECK( deco( *truePart, "ParticleIsolation40",  m_particleIsolation40 ) );
+  CHECK( deco( *truePart, "ParticleIsolation30",  m_particleIsolation30 ) );
+  CHECK( deco( *truePart, "ParticleIsolation20",  m_particleIsolation20 ) );
+
+  //to get ED corrections right for particle isolation
+  float area_cone40 = TMath::Pi()*0.4*0.4;
+  float area_cone30 = TMath::Pi()*0.3*0.3;
+  float area_cone20 = TMath::Pi()*0.2*0.2;
+  int neta = 5, nphi = 7;
+  float deta = 0.0125*neta*2;
+  float dphi = M_PI/256.*nphi*2;
+  float area_5x7 = deta*dphi;
+
+  float fPutWBack40  = area_cone40 / (area_cone40 - area_5x7);
+  float fPutWBack30  = area_cone30 / (area_cone30 - area_5x7);
+  float fPutWBack20  = area_cone20 / (area_cone20 - area_5x7);
+
+  if(m_CalculateTruthCaloIsolation){
+    m_particleIsolation40_ED_corrected      = m_particleIsolation40 - m_PAUTruthCaloIsolationTool->EtConeCorrectionJetAreas(truePart, .40, m_RemoveNHardestJets) * fPutWBack40 ;
+    m_particleIsolation30_ED_corrected      = m_particleIsolation30 - m_PAUTruthCaloIsolationTool->EtConeCorrectionJetAreas(truePart, .30, m_RemoveNHardestJets) * fPutWBack30 ;
+    m_particleIsolation20_ED_corrected      = m_particleIsolation20 - m_PAUTruthCaloIsolationTool->EtConeCorrectionJetAreas(truePart, .20, m_RemoveNHardestJets) * fPutWBack20 ;
+  }
+  else{
+    m_particleIsolation40_ED_corrected      = PAU::UNKNOWN;
+    m_particleIsolation30_ED_corrected      = PAU::UNKNOWN;
+    m_particleIsolation20_ED_corrected      = PAU::UNKNOWN;
+  }
+
+  CHECK( deco( *truePart, "ParticleIsolation40_ED_corrected", m_particleIsolation40_ED_corrected ) );
+  CHECK( deco( *truePart, "ParticleIsolation30_ED_corrected", m_particleIsolation30_ED_corrected ) );
+  CHECK( deco( *truePart, "ParticleIsolation20_ED_corrected", m_particleIsolation20_ED_corrected ) );
+
+  if ( truePart->nParents()>0 && truePart->mother(0) ) 
+    m_mother_pdgId = truePart->mother(0)->pdgId();
+  else 
+    m_mother_pdgId = int(PAU::UNKNOWN);
+  CHECK( deco( *truePart, "mother_pdgId", m_mother_pdgId ) );
+
+  m_DecoratedTruthParticles.insert(truePart);
+
+  return StatusCode::SUCCESS;
+}
+
+
+StatusCode TruthExplorerAlg::DecorateTruthParticleWithZeroes(const TruthParticle* truePart){
+
+  if(m_DecoratedTruthParticles.find(truePart) != m_DecoratedTruthParticles.end()) return StatusCode::SUCCESS;
+  
+  int unknownint = PAU::UNKNOWN;
+  float unknownfloat = PAU::UNKNOWN;
+
+  CHECK( deco( *truePart, "TruthConv" , unknownint   ) );
+  CHECK( deco( *truePart, "XTruthConv", unknownfloat ) );
+  CHECK( deco( *truePart, "YTruthConv", unknownfloat ) );
+  CHECK( deco( *truePart, "ZTruthConv", unknownfloat ) );
+  CHECK( deco( *truePart, "RTruthConv", unknownfloat ) );
+
+  CHECK( deco( *truePart, "isHardProcPhoton", unknownint ) );
+  CHECK( deco( *truePart, "isBremPhoton"    , unknownint ) );
+  CHECK( deco( *truePart, "isPromptPhoton"  , unknownint ) );
+  
+  CHECK( deco( *truePart, "PartonIsolation15_UE", unknownfloat ) );
+  CHECK( deco( *truePart, "PartonIsolation20_UE", unknownfloat ) );
+  CHECK( deco( *truePart, "PartonIsolation25_UE", unknownfloat ) );
+  CHECK( deco( *truePart, "PartonIsolation30_UE", unknownfloat ) );
+  CHECK( deco( *truePart, "PartonIsolation35_UE", unknownfloat ) );
+  CHECK( deco( *truePart, "PartonIsolation40_UE", unknownfloat ) );
+  CHECK( deco( *truePart, "PartonIsolation45_UE", unknownfloat ) );
+  CHECK( deco( *truePart, "PartonIsolation60_UE", unknownfloat ) );
+
+  CHECK( deco( *truePart, "PartonIsolation15", unknownfloat ) );
+  CHECK( deco( *truePart, "PartonIsolation20", unknownfloat ) );
+  CHECK( deco( *truePart, "PartonIsolation30", unknownfloat ) );
+  CHECK( deco( *truePart, "PartonIsolation25", unknownfloat ) );
+  CHECK( deco( *truePart, "PartonIsolation35", unknownfloat ) );
+  CHECK( deco( *truePart, "PartonIsolation40", unknownfloat ) );
+  CHECK( deco( *truePart, "PartonIsolation45", unknownfloat ) );
+  CHECK( deco( *truePart, "PartonIsolation60", unknownfloat ) );
+
+  CHECK( deco( *truePart, "ParticleIsolation40", unknownfloat ) );
+  CHECK( deco( *truePart, "ParticleIsolation30", unknownfloat ) );
+  CHECK( deco( *truePart, "ParticleIsolation20", unknownfloat ) );
+
+  CHECK( deco( *truePart, "ParticleIsolation40_ED_corrected", unknownfloat ) );
+  CHECK( deco( *truePart, "ParticleIsolation30_ED_corrected", unknownfloat ) );
+  CHECK( deco( *truePart, "ParticleIsolation20_ED_corrected", unknownfloat ) );
+
+  CHECK( deco( *truePart, "mother_pdgId", unknownint ) );
+
+  m_DecoratedTruthParticles.insert(truePart);
+
+  return StatusCode::SUCCESS;
+}
+
+
+/**
+ * @brief Standard Gaudi @c execute method.
+ */
+StatusCode TruthExplorerAlg::execute()
+{
+
+  m_DecoratedTruthParticles.clear();
+
+  for ( unsigned u=0 ; u<m_PAUtruthTool->getFinalStateMC().size() ; ++u ) {
+    
+    const TruthParticle* truePart = m_PAUtruthTool->getFinalStateMC()[u] ;
+    
+    // I think this filter needs to be changed, so we keep a wider range
+    // of potential photon candidates
+    if ( truePart == 0 || 
+	 truePart->genParticle() == 0 ||
+	 truePart->pdgId() != 22 || 
+	 !(m_PAUtruthTool->isFinalStatePhotonMC(truePart)))  
+      continue;
+
+    CHECK( DecorateTruthParticle(truePart) );
+  }
+
+  
+  // okay, this part is ugly.  we need to make sure that we have MC particles corresponding
+  // to all of the reconstructed electrons and photons.  Furthermore, they all need to be
+  // decorated.  So, go through all of the electrons and photons, find their truth matches,
+  // and decorate those too.
+  CHECK( m_photonGetter->reset() );
+  while (const Analysis::Photon* g = m_photonGetter->next<Analysis::Photon>()){
+    const TruthParticle* tp = m_PAUtruthTool->getTruthMatch(g);
+    if(tp){
+      CHECK( DecorateTruthParticle(tp) );
+    }
+  }
+
+  CHECK( m_electronGetter->reset() );
+  while (const Analysis::Electron* e = m_electronGetter->next<Analysis::Electron>()){
+    const TruthParticle* tp = m_PAUtruthTool->getTruthMatch(e);
+    if(tp) {
+      CHECK( DecorateTruthParticle(tp) );
+    }
+  }
+
+  // now, for the rest of the truth particles, fill with dummy values
+  CHECK( m_truthParticleGetter->reset() );
+  while (const TruthParticle* tp = m_truthParticleGetter->next<TruthParticle>()){
+    CHECK( DecorateTruthParticleWithZeroes(tp) );
+  }
+
+
+  return StatusCode::SUCCESS;
+}
+
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TruthExplorerAlg.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TruthExplorerAlg.h
new file mode 100644
index 0000000000000000000000000000000000000000..0d630fe7d9b8bb76a50f5c0a82ece4ae6fb0c7d0
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TruthExplorerAlg.h
@@ -0,0 +1,120 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: TruthExplorerAlg.h 502492 2012-05-25 13:19:11Z jmarchan $
+/**
+ * @file PhotonD3PDMaker/src/TruthExplorerAlg.h
+ * @author Mike Hance <mike.hance@cern.ch>
+ * @date March, 2011
+ * @brief Calculate some truth quantities
+ */
+
+
+#ifndef PHOTOND3PDMAKER_TRUTHEXPLORERALG_H
+#define PHOTOND3PDMAKER_TRUTHEXPLORERALG_H
+
+
+#include "D3PDMakerUtils/UDAlgBase.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "PhotonAnalysisUtils/IPAUtruthTool.h"
+#include "PhotonAnalysisUtils/IPAUcaloIsolationTool.h"
+#include <vector>
+#include <string>
+#include <map>
+#include <set>
+
+namespace D3PD {
+
+
+class ICollectionGetterTool;
+
+
+/**
+ * @brief Calculate isolation cones of topo clusters for photons.  Save as UD.
+ */
+class TruthExplorerAlg
+  : public UDAlgBase
+{
+public:
+  /**
+   * @brief Standard Gaudi algorithm constructor.
+   * @param name The algorithm name.
+   * @param svcloc The service locator.
+   */
+  TruthExplorerAlg (const std::string& name,
+		    ISvcLocator* svcloc);
+
+
+  /// Standard Gaudi @c initialize method.
+  virtual StatusCode initialize();
+
+
+  /// Standard Gaudi @c execute method.
+  virtual StatusCode execute();
+
+
+private:
+  /// Property: Getter for input photons.
+  ToolHandle<ICollectionGetterTool> m_photonGetter;
+
+  /// Property: Getter for input electrons.
+  ToolHandle<ICollectionGetterTool> m_electronGetter;
+
+  /// Property: Getter for truth particles
+  ToolHandle<ICollectionGetterTool> m_truthParticleGetter;
+
+  /// Property: truth tool
+  ToolHandle<IPAUtruthTool> m_PAUtruthTool;
+
+  float
+    m_partonIsolation15,
+    m_partonIsolation20,
+    m_partonIsolation25,
+    m_partonIsolation30,
+    m_partonIsolation35,
+    m_partonIsolation40,
+    m_partonIsolation45,
+    m_partonIsolation60,
+    m_partonIsolation15_UE,
+    m_partonIsolation20_UE,
+    m_partonIsolation25_UE,
+    m_partonIsolation30_UE,
+    m_partonIsolation35_UE,
+    m_partonIsolation40_UE,
+    m_partonIsolation45_UE,
+    m_partonIsolation60_UE,
+    m_particleIsolation20,
+    m_particleIsolation30,
+    m_particleIsolation40,
+    m_particleIsolation20_ED_corrected,
+    m_particleIsolation30_ED_corrected,
+    m_particleIsolation40_ED_corrected;
+
+  int m_isHardProc, m_isBrem, m_isPromptPhoton;
+
+  int m_isTruthConv;
+
+  float m_XTruthConv,m_YTruthConv,m_ZTruthConv,m_RTruthConv;
+
+  bool m_CalculateTruthCaloIsolation;
+  ToolHandle<IPAUcaloIsolationTool> m_PAUTruthCaloIsolationTool;
+
+  int m_RemoveNHardestJets;
+
+  int m_mother_pdgId;
+
+  StatusCode DecorateTruthParticle(const TruthParticle* tp);
+  StatusCode DecorateTruthParticleWithZeroes(const TruthParticle* tp);
+
+  std::set<const TruthParticle*> m_DecoratedTruthParticles;
+
+};
+  
+
+} // namespace D3PD
+
+
+#endif
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TruthParticleAssociationTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TruthParticleAssociationTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..4d8837c4ee79a5fac25cd3872c36ef20952a8bcf
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TruthParticleAssociationTool.cxx
@@ -0,0 +1,77 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id $
+/**
+ * @file egammaD3PDMaker/src/TruthParticleAssociationTool.cxx
+ * @author Mike Hance <hance@hep.upenn.edu>, based on similar tools by scott snyder <snyder@bnl.gov>
+ * @date December, 2011
+ * @brief Associate an object to PAU egamma object
+ */
+
+
+#include "TruthParticleAssociationTool.h"
+#include "EventKernel/INavigable4Momentum.h"
+#include "AthenaKernel/errorcheck.h"
+#include "FourMomUtils/P4Helpers.h"
+
+namespace D3PD {
+
+
+/**
+ * @brief Standard Gaudi tool constructor.
+ * @param type The name of the tool type.
+ * @param name The tool name.
+ * @param parent The tool's Gaudi parent.
+ */
+TruthParticleAssociationTool::TruthParticleAssociationTool (const std::string& type,
+							const std::string& name,
+							const IInterface* parent)
+  : Base (type, name, parent)
+{
+  declareProperty ("PAUtruthTool", m_PAUtruthTool,
+		   "PAU truth tool instance");
+
+}
+
+
+/**
+ * @brief Standard Gaudi initialize method.
+ */
+StatusCode TruthParticleAssociationTool::initialize()
+{
+  // Retrieve the getter tool and configure it, saying that we want
+  // to get @c PAU::egamma objects from it.
+  CHECK( m_PAUtruthTool.retrieve() );
+  return Base::initialize();
+}
+
+
+/**
+ * @brief Create any needed tuple variables.
+ */
+StatusCode TruthParticleAssociationTool::book ()
+{
+  return StatusCode::SUCCESS;
+}
+
+
+/**
+ * @brief Return the target object.
+ * @param p The source object for the association.
+ *
+ * Return the target of the association, or 0.
+ */
+const TruthParticle*
+TruthParticleAssociationTool::get (const INavigable4Momentum& p)
+{
+  // added a disambiguation function in PAU, so I can just pass in an IN4M.
+  // the trick is the second argument set to "true".
+  //
+  const TruthParticle* tp = m_PAUtruthTool->getTruthMatch(&p, true);
+  return tp;
+}
+
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TruthParticleAssociationTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TruthParticleAssociationTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..4e3e7bd3561a1c423fd76050d4b2e85c859b54d0
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TruthParticleAssociationTool.h
@@ -0,0 +1,89 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id $
+/**
+ * @file PhotonD3PDMaker/src/TruthParticleAssociationTool.h
+ * @author Mike Hance <hance@hep.upenn.edu>, based on similar tools by scott snyder <snyder@bnl.gov>
+ * @date December, 2011
+ * @brief Associate an object to a TruthParticle using PAU tools
+ */
+
+
+#ifndef D3PDMAKER_GENPARTICLEASSOCIATIONTOOL_H
+#define D3PDMAKER_GENPARTICLEASSOCIATIONTOOL_H
+
+
+#include "D3PDMakerInterfaces/ICollectionGetterTool.h"
+#include "D3PDMakerUtils/SingleAssociationTool.h"
+#include "EventKernel/INavigable4Momentum.h"
+#include "GaudiKernel/ToolHandle.h"
+
+#include "PhotonAnalysisUtils/IPAUtruthTool.h"
+
+#include "McParticleEvent/TruthParticle.h"
+
+namespace D3PD {
+
+
+/**
+ * @brief Associate to particle closest in DR.
+ *
+ * This is a single association tool.
+ * Given an @c INavigable4Momentum object and a container of objects,
+ * return the object in the container that is associated with the original object.
+ *
+ * Parameters:
+ *  Getter - ICollectionGetterTool instance defining the target collection.
+ *
+ */
+class TruthParticleAssociationTool
+  : public SingleAssociationTool<INavigable4Momentum, TruthParticle>
+{
+public:
+  typedef SingleAssociationTool<INavigable4Momentum, TruthParticle> Base;
+
+
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  TruthParticleAssociationTool (const std::string& type,
+				const std::string& name,
+				const IInterface* parent);
+
+
+  /// Standard Gaudi initialize method.
+  virtual StatusCode initialize();
+
+
+  /**
+   * @brief Create any needed tuple variables.
+   */
+  virtual StatusCode book();
+
+
+  /**
+   * @brief Return the target object.
+   * @param p The source object for the association.
+   *
+   * Return the target of the association, or 0.
+   */
+  virtual const TruthParticle* get (const INavigable4Momentum& p);
+
+
+private:
+  ToolHandle<IPAUtruthTool>         m_PAUtruthTool;
+};
+
+
+} // namespace D3PD
+
+
+
+#endif
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TruthParticleFilterCutTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TruthParticleFilterCutTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..cd3e1cad627815230b9ae397e184a3ccacdbdcf8
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TruthParticleFilterCutTool.cxx
@@ -0,0 +1,147 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/TruthParticleFilterTool.cxx
+ * @author Mike Hance <mike.hance@cern.ch>
+ * @date August 2010
+ * @brief Filter truth particles for writing to D3PD.
+ */
+
+
+#include "TruthParticleFilterCutTool.h"
+#include "GeneratorObjects/McEventCollection.h"
+#include "AthenaKernel/errorcheck.h"
+#include "HepMC/GenEvent.h"
+#include "HepMC/GenVertex.h"
+#include "HepMC/GenParticle.h"
+#include "CLHEP/Units/SystemOfUnits.h"
+#include "boost/foreach.hpp"
+#include <utility>
+
+
+using CLHEP::GeV;
+
+
+namespace D3PD {
+
+
+/**
+ * @brief Standard Gaudi tool constructor.
+ * @param type The name of the tool type.
+ * @param name The tool name.
+ * @param parent The tool's Gaudi parent.
+ */
+TruthParticleFilterCutTool::TruthParticleFilterCutTool
+  (const std::string& type,
+   const std::string& name,
+   const IInterface* parent)
+    : AthAlgTool (type, name, parent)
+{
+  declareProperty ("PDG_IDs",
+		   m_pdgIDs,
+		   "Types of particles to keep");
+
+  declareProperty ("pT_low",
+		   m_cut_lower_pT = -1,
+		   "Lower pT cut");
+  
+  declareProperty ("pT_high",
+		   m_cut_upper_pT = -1,
+		   "Upper pT cut");
+
+  declareProperty ("eta_low",
+		   m_cut_lower_eta = 0,
+		   "Lower eta cut");
+
+  declareProperty ("eta_high",
+		   m_cut_upper_eta = -1,
+		   "Upper eta cut");
+}
+
+
+/**
+ * @brief Standard Gaudi @c queryInterface method.
+ */
+StatusCode
+TruthParticleFilterCutTool::queryInterface( const InterfaceID& riid, void** ppvIf )
+{
+  if ( riid == ITruthParticleFilterCutTool::interfaceID() )  {
+    *ppvIf = static_cast<ITruthParticleFilterCutTool*> (this);
+    addRef();
+    return StatusCode::SUCCESS;
+  }
+  
+  return AlgTool::queryInterface( riid, ppvIf );
+}
+
+
+/**
+ * @brief Check the input PDG against the list of PDG IDs passed into the constructor
+ */
+bool TruthParticleFilterCutTool::check_PDG(unsigned int pdg_id){
+  if(m_pdgIDs.size()==0) 
+    return true;
+
+  for(unsigned int i=0; i<m_pdgIDs.size(); i++){
+    if(abs(m_pdgIDs[i]) == abs(pdg_id)) return true;
+  }
+  return false;
+}
+
+  
+/**
+ * @brief Test to see if we want to keep a particle.
+ */
+bool
+TruthParticleFilterCutTool::passesCut (const HepMC::GenParticle* p)
+{
+  int pdg_id = std::abs (p->pdg_id());
+  // Avoid problems evaluating eta().
+  if (p->momentum().perp() < 1e-3*GeV) return false;
+  float eta  = fabs(p->momentum().eta());
+  float pT   = p->momentum().e()/cosh(eta);
+
+  bool local_cut_results = true;
+  {
+    local_cut_results &= (check_PDG(pdg_id));
+    local_cut_results &= (pT > m_cut_lower_pT || m_cut_lower_pT < 0);
+    local_cut_results &= (pT < m_cut_upper_pT || m_cut_upper_pT < 0);
+    local_cut_results &= (eta > m_cut_lower_eta || m_cut_lower_eta < 0);
+    local_cut_results &= (eta < m_cut_upper_eta || m_cut_upper_eta < 0);
+  }
+
+  return local_cut_results;
+}
+
+/**
+ * @brief Standard Gaudi initialize method.
+ */
+StatusCode TruthParticleFilterCutTool::initialize()
+{
+  return AthAlgTool::initialize();
+}
+
+
+/**
+ * @brief Standard Gaudi finalize method.
+ */
+StatusCode TruthParticleFilterCutTool::finalize()
+{
+  return AthAlgTool::finalize();
+}
+
+/**
+ * @brief Standard Gaudi execute method.
+ */
+StatusCode TruthParticleFilterCutTool::execute()
+{
+  return StatusCode::SUCCESS;
+}
+
+
+
+
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TruthParticleFilterCutTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TruthParticleFilterCutTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..1705054bcce86e79cc86b3778cb7bf81a2d3429b
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/TruthParticleFilterCutTool.h
@@ -0,0 +1,96 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/TruthParticleFilterTool.h
+ * @author Mike Hance <mike.hance@cern.ch>
+ * @date August, 2010
+ * @brief Filter truth particles for writing to D3PD.
+ */
+
+
+#ifndef PHOTOND3PDMAKER_TRUTHPARTICLEFILTERCUTTOOL_H
+#define PHOTOND3PDMAKER_TRUTHPARTICLEFILTERCUTTOOL_H
+
+
+#include "D3PDMakerUtils/SGKeyResolver.h"
+#include "PhotonD3PDMaker/ITruthParticleFilterCutTool.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include <string>
+class McEventCollection;
+namespace HepMC {
+  class GenEvent;
+  class GenVertex;
+  class GenParticle;
+}
+
+
+namespace D3PD {
+
+
+/**
+ * @brief Filter truth particles based on a variety of attributes
+ *
+ */
+class TruthParticleFilterCutTool
+  : public ITruthParticleFilterCutTool, public AthAlgTool
+{
+public:
+  /**
+   * @brief Standard Gaudi tool constructor.
+   * @param type The name of the tool type.
+   * @param name The tool name.
+   * @param parent The tool's Gaudi parent.
+   */
+  TruthParticleFilterCutTool (const std::string& type,
+			      const std::string& name,
+			      const IInterface* parent);
+
+
+  /// Standard Gaudi @c queryInterface method.
+  virtual StatusCode queryInterface( const InterfaceID& riid,
+                                     void** ppvIf );
+
+  /// Standard Gaudi initialize method.
+  virtual StatusCode initialize();
+
+  /// Standard Gaudi finalize  method.
+  virtual StatusCode finalize();
+
+  /// Run the tool.
+  virtual StatusCode execute();
+
+  /// Here's the meat
+  virtual bool passesCut( const HepMC::GenParticle* tp );
+
+private:
+
+  /// compare input PDG with m_pdgIDs, below
+  bool check_PDG(unsigned int);
+
+  /// PDG ID to keep
+  std::vector<int> m_pdgIDs;
+  
+  /// lower pT cut
+  float m_cut_lower_pT;
+  
+  /// upper pT cut
+  float m_cut_upper_pT;
+  
+  /// lower eta cut
+  float m_cut_lower_eta;
+  
+  /// upper eta cut
+  float m_cut_upper_eta;
+};
+
+
+} // namespace D3PD
+
+
+#endif // not TRUTHPARTICLEFILTERTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/VxTrackAtVertexAssociationTool.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/VxTrackAtVertexAssociationTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..6017fc69ece7726fc51c7f3f0700827d1c7d73b5
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/VxTrackAtVertexAssociationTool.cxx
@@ -0,0 +1,58 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: VxTrackAtVertexAssociationTool.cxx
+/**
+ * @file PhotonD3PDMaker/src/VxTrackAtVertexAssociationTool.cxx
+ * @author Jean-Francois Marchand <jean-francois.marchand@cern.ch>
+ * @date November 2012
+ * @brief Associate VxTrackAtVertex to conversions vertex
+ */
+
+#include "VxTrackAtVertexAssociationTool.h"
+#include "EventKernel/INavigable4Momentum.h"
+#include "AthenaKernel/errorcheck.h"
+
+#include "VxVertex/VxCandidate.h"
+#include "VxVertex/VxTrackAtVertex.h"
+
+
+namespace D3PD {
+
+  
+  VxTrackAtVertexAssociationTool::VxTrackAtVertexAssociationTool
+  (const std::string& type,
+   const std::string& name,
+   const IInterface* parent)
+    : Base (type, name, parent)
+  {
+  }
+
+  /**
+   * @brief Start the iteration for a new association.
+   * @param p The object from which to associate.
+   */
+  StatusCode VxTrackAtVertexAssociationTool::reset (const Trk::VxCandidate& vx)
+  {    
+    const std::vector<Trk::VxTrackAtVertex*>* tracks = vx.vxTrackAtVertex();   
+    m_trkItr = tracks->begin();
+    m_trkEnd = tracks->end();    
+    return StatusCode::SUCCESS;
+  }
+  
+  /**
+   * @brief Return a pointer to the next element in the association.
+   *
+   * Return 0 when the association has been exhausted.
+   */
+  const Trk::VxTrackAtVertex* VxTrackAtVertexAssociationTool::next()
+  {
+    // reached the end
+    if(m_trkItr == m_trkEnd) return 0;    
+    const Trk::VxTrackAtVertex *track = *m_trkItr;
+    m_trkItr++;
+    return track;
+  }
+    
+} // namespace D3PD
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/VxTrackAtVertexAssociationTool.h b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/VxTrackAtVertexAssociationTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..0288f255e5094ebd1e3384d750f3b882d424edd6
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/VxTrackAtVertexAssociationTool.h
@@ -0,0 +1,51 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef PHOTOND3PDMAKER_VXTRACKATVERTEXASSOCIATIONTOOL_H
+#define PHOTOND3PDMAKER_VXTRACKATVERTEXASSOCIATIONTOOL_H
+
+#include "D3PDMakerUtils/MultiAssociationTool.h"
+#include <vector>
+
+namespace Trk{
+  class VxCandidate;
+  class VxTrackAtVertex;
+}
+
+namespace D3PD {
+
+  class VxTrackAtVertexAssociationTool
+    : public MultiAssociationTool<Trk::VxCandidate, Trk::VxTrackAtVertex> 
+    {
+    public:
+      typedef MultiAssociationTool<Trk::VxCandidate, Trk::VxTrackAtVertex> Base;
+      
+      VxTrackAtVertexAssociationTool (const std::string& type,
+				  const std::string& name,
+				  const IInterface* parent);
+      
+      /**
+       * @brief Start the iteration for a new association.
+       * @param p The object from which to associate.
+       */
+      virtual StatusCode reset (const Trk::VxCandidate& p);
+      
+      /**
+       * @brief Return a pointer to the next element in the association.
+       *
+       * Return 0 when the association has been exhausted.
+       */
+      virtual const Trk::VxTrackAtVertex* next();
+      
+    private:
+            
+      std::vector<Trk::VxTrackAtVertex*>::const_iterator m_trkItr;
+      std::vector<Trk::VxTrackAtVertex*>::const_iterator m_trkEnd;
+            
+    };
+
+} // namespace D3PD
+
+
+#endif // not PHOTOND3PDMAKER_VXTRACKATVERTEXASSOCIATIONTOOL_H
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/components/PhotonD3PDMaker_entries.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/components/PhotonD3PDMaker_entries.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..3ba2f18e7ea1c138393fc3bce848ef9c0dd9a682
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/components/PhotonD3PDMaker_entries.cxx
@@ -0,0 +1,117 @@
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/components/PhotonD3PDMaker_entries.cxx
+ * @author Mike Hance <hance@hep.upenn.edu>
+ * @date July 2010
+ * @brief List Gaudi components.
+ */
+
+
+#include "../PAUDiPhotonAssociationTool.h"
+#include "../PAUDiPhotonFillerTool.h"
+#include "../PhotonTruthParticleFilterTool.h"
+#include "../TruthParticleFilterCutTool.h"
+#include "../EgammaFilter.h"
+#include "../PhotonFilter.h"
+#include "../ElectronFilter.h"
+#include "../TrackFilter.h"
+#include "../CellFilter.h"
+#include "../PAUTruthPhotonAssociationTool.h"
+#include "../PAUTruthPhotonFillerTool.h"
+#include "../PAUPhotonFillerTool.h"
+#include "../PAUElectronFillerTool.h"
+#include "../PAUConversionFillerTool.h"
+#include "../PAUIsolationFillerTool.h"
+#include "../ElectronSorterAlg.h"
+#include "../PhotonSorterAlg.h"
+#include "../DREtAssociationTool.h"
+#include "../PhotonPVFillerTool.h"
+#include "../ClusterFillerTool.h"
+#include "../PAUGammaAssociationTool.h"
+#include "../PAUFillerTool.h"
+#include "../TruthParticleAssociationTool.h"
+#include "../TruthExplorerAlg.h"
+#include "../EgammaTruthParticleFilter.h"
+#include "../GSFOriginalTrackParticleAssociationTool.h"
+#include "../TrackParticleParametersAtDiPhotonVertex.h"
+#include "../VxTrackAtVertexAssociationTool.h"
+#include "../ConversionPerigeeAssociationTool.h"
+#include "../ConversionNeutralPerigeeAssociationTool.h"
+#include "../NeutralPerigeeFillerTool.h"
+#include "../NeutralPerigeeCovarianceAssociationTool.h"
+#include "../ShowerRadiusFillerTool.h"
+
+#include "GaudiKernel/DeclareFactoryEntries.h"
+
+
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, PAUDiPhotonAssociationTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, PAUDiPhotonFillerTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, PhotonTruthParticleFilterTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, TruthParticleFilterCutTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, PAUTruthPhotonAssociationTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, PAUTruthPhotonFillerTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, PAUPhotonFillerTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, PAUElectronFillerTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, PAUConversionFillerTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, PAUIsolationFillerTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, DREtAssociationTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, PhotonPVFillerTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, ClusterFillerTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, PAUGammaAssociationTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, PAUFillerTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, TruthParticleAssociationTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, GSFOriginalTrackParticleAssociationTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, TrackParticleParametersAtDiPhotonVertex)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, VxTrackAtVertexAssociationTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, ConversionPerigeeAssociationTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, ConversionNeutralPerigeeAssociationTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, NeutralPerigeeFillerTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, NeutralPerigeeCovarianceAssociationTool)
+DECLARE_NAMESPACE_TOOL_FACTORY      (D3PD, ShowerRadiusFillerTool)
+
+DECLARE_NAMESPACE_ALGORITHM_FACTORY (D3PD, EgammaFilter)
+DECLARE_NAMESPACE_ALGORITHM_FACTORY (D3PD, PhotonFilter)
+DECLARE_NAMESPACE_ALGORITHM_FACTORY (D3PD, ElectronFilter)
+DECLARE_NAMESPACE_ALGORITHM_FACTORY (D3PD, TrackFilter)
+DECLARE_NAMESPACE_ALGORITHM_FACTORY (D3PD, CellFilter)
+DECLARE_NAMESPACE_ALGORITHM_FACTORY (D3PD, ElectronSorterAlg)
+DECLARE_NAMESPACE_ALGORITHM_FACTORY (D3PD, PhotonSorterAlg)
+DECLARE_NAMESPACE_ALGORITHM_FACTORY (D3PD, TruthExplorerAlg)
+DECLARE_NAMESPACE_ALGORITHM_FACTORY (D3PD, EgammaTruthParticleFilter)
+
+DECLARE_FACTORY_ENTRIES(PhotonD3PDMaker) {
+  DECLARE_NAMESPACE_TOOL      (D3PD, PAUDiPhotonAssociationTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, PAUDiPhotonFillerTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, PhotonTruthParticleFilterTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, TruthParticleFilterCutTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, PAUTruthPhotonAssociationTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, PAUTruthPhotonFillerTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, PAUPhotonFillerTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, PAUElectronFillerTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, PAUConversionFillerTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, PAUIsolationFillerTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, DREtAssociationTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, PhotonPVFillerTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, ClusterFillerTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, PAUGammaAssociationTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, PAUFillerTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, TruthParticleAssociationTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, GSFOriginalTrackParticleAssociationTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, VxTrackAtVertexAssociationTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, ConversionPerigeeAssociationTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, ConversionNeutralPerigeeAssociationTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, NeutralPerigeeFillerTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, NeutralPerigeeCovarianceAssociationTool)
+  DECLARE_NAMESPACE_TOOL      (D3PD, ShowerRadiusFillerTool)
+
+  DECLARE_NAMESPACE_ALGORITHM (D3PD, EgammaFilter)
+  DECLARE_NAMESPACE_ALGORITHM (D3PD, PhotonFilter)
+  DECLARE_NAMESPACE_ALGORITHM (D3PD, ElectronFilter)
+  DECLARE_NAMESPACE_ALGORITHM (D3PD, TrackFilter)
+  DECLARE_NAMESPACE_ALGORITHM (D3PD, CellFilter)
+  DECLARE_NAMESPACE_ALGORITHM (D3PD, ElectronSorterAlg)
+  DECLARE_NAMESPACE_ALGORITHM (D3PD, PhotonSorterAlg)
+  DECLARE_NAMESPACE_ALGORITHM (D3PD, TruthExplorerAlg)
+
+  DECLARE_NAMESPACE_ALGORITHM (D3PD, EgammaTruthParticleFilter)
+}
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/components/PhotonD3PDMaker_load.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/components/PhotonD3PDMaker_load.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..dbd7b6c3bd002bf0015d23942d2989870cbe0ee5
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/components/PhotonD3PDMaker_load.cxx
@@ -0,0 +1,13 @@
+// $Id$
+/**
+ * @file PhotonD3PDMaker/src/components/PhotonD3PDMaker_entries.cxx
+ * @author Mike Hance <hance@hep.upenn.edu>
+ * @date July 2010
+ * @brief Gaudi boilerplate.
+ */
+
+
+#include "GaudiKernel/LoadFactoryEntries.h"
+
+LOAD_FACTORY_ENTRIES(PhotonD3PDMaker)
+
diff --git a/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/trackParticleInheritance.cxx b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/trackParticleInheritance.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..f74ebefe2f53d492e6d174940ab45e4238d91112
--- /dev/null
+++ b/PhysicsAnalysis/D3PDMaker/PhotonD3PDMaker/src/trackParticleInheritance.cxx
@@ -0,0 +1,13 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// this is somewhat ridiculous.
+
+#include "SGTools/BaseInfo.h"
+#include "Navigation/IAthenaBarCode.h"
+#include "Particle/TrackParticle.h"
+#include "EventKernel/INavigable4Momentum.h"
+
+SG_ADD_BASE( Rec::TrackParticle, SG_VIRTUAL (IAthenaBarCode) ); 
+SG_ADD_BASE( Rec::TrackParticle, SG_VIRTUAL (INavigable4Momentum) );