diff --git a/Generators/TruthUtils/CMakeLists.txt b/Generators/TruthUtils/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7e05a94e31ae6754d3961b6cfbb55a992a9aa264
--- /dev/null
+++ b/Generators/TruthUtils/CMakeLists.txt
@@ -0,0 +1,22 @@
+################################################################################
+# Package: TruthUtils
+################################################################################
+
+# Declare the package name:
+atlas_subdir( TruthUtils )
+
+# External dependencies:
+find_package( Boost COMPONENTS filesystem thread system )
+find_package( FastJet )
+find_package( HEPUtils )
+find_package( HepMC )
+find_package( MCUtils )
+find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread )
+
+# Component(s) in the package:
+atlas_add_library( TruthUtils
+                   Root/*.cxx
+                   PUBLIC_HEADERS TruthUtils
+                   INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${HEPUTILS_INCLUDE_DIRS} ${MCUTILS_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS} ${FASTJET_INCLUDE_DIRS}
+                   LINK_LIBRARIES ${Boost_LIBRARIES} ${ROOT_LIBRARIES} ${HEPUTILS_LIBRARIES} ${MCUTILS_LIBRARIES} ${HEPMC_LIBRARIES} ${FASTJET_LIBRARIES} )
+
diff --git a/Generators/TruthUtils/Root/GeneratorName.cxx b/Generators/TruthUtils/Root/GeneratorName.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..f7fb8b65401600c30bf90670a8339075bcad2a22
--- /dev/null
+++ b/Generators/TruthUtils/Root/GeneratorName.cxx
@@ -0,0 +1,206 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TruthUtils/GeneratorName.h"
+#include <iostream>
+#include <algorithm>
+
+/// @todo This scheme doesn't work anymore...
+
+GeneratorName generator_name (const int& index) {
+  switch (index) {
+    //new scheme for first generators
+  case  110000000 : return PYTHIA;
+  case   20000000 : return HERWIG;
+  case   30000000 : return ISAJET;
+  case   40000000 : return SINGLE;
+  case   50000000 : return HIJING;
+  case   60000000 : return PHOJET;
+  case   70000000 : return Sherpa;
+  case   80000000 : return CASCADE;
+  case   90000000 : return JIMMY;
+  case  100000000 : return HYDJET;
+    // note 110000000 used for PYTHIA
+  case  120000000 : return EPOS;
+  case 100000   : return COMPHEP;
+    //  case 150000   : return CHARYBDIS;
+  case 200000   : return USER;
+  case 300000   : return ACERMC;
+  case 400000   : return ALPGEN;
+  case 500000   : return MADGRAPH;
+  case 600000   : return MADCUP;
+  case 700000   : return TOPREX;
+  case 800000   : return LHAEXT;
+  case 900000   : return MCATNLO;
+    // new second generators in a new scheme
+  case 1001000000 : return CHARYBDIS;
+  case 1001100000 : return HORACE;
+  case 1001200000 : return LHEF;
+  case 1001300000 : return MATCHIG;
+  case 1001400000 : return HVGEN;
+  case 1001500000 : return EXOGRAVITON;
+  case 1001600000 : return PYTHIABC;
+  case 1001700000 : return PROTOS;
+  case 1001800000 : return GRAVADD;
+  case 1001900000 : return HELAC;
+  case 1002000000 : return PYTHIASGLUON;
+    // third generators
+  case 10000    : return TAUOLA;
+  case 20000    : return PHOTOS;
+  case 30000    : return TAUOLA_PHOTOS;
+  }
+  return UNKNOWN;
+}
+
+
+GeneratorName first_generator(const int& index) {
+  int gen1;
+  if (isNewGenCoding(index)) {
+    gen1 = 10000000*(index/10000000);
+    if (gen1 >= 1000000000) gen1=gen1-1000000000;
+  } else{
+    // Extract the first generator int representation (/1000000 *1000000)
+    // and convert to a new scheme (*10)
+    gen1 = 10000000*(index/1000000);
+    //special treatment for PYTHIA, as the coding is not standard
+    if (gen1 == 10000000) gen1=110000000;
+  }
+  return generator_name(gen1);
+}
+
+GeneratorName second_generator(const int& index) {
+  int gen1,gen2;
+  if (isNewGenCoding(index)){
+    gen1 = first_generator(index);
+    gen2 = index - gen1;
+    gen2 = 100000*(gen2/100000);
+    //  if (gen2==100000 && (gen1==2000000 || gen1==9000000)) gen2 += 50000;
+  } else{
+    gen1 = 1000000*(index/1000000);
+    gen2 = index - gen1;
+    gen2 = 100000*(gen2/100000);
+  }
+  return generator_name(gen2);
+}
+
+
+GeneratorName third_generator(const int& index) {
+  int gen1,gen2,gen3;
+  if (isNewGenCoding(index)){
+    gen1 = first_generator(index);
+    gen2 = second_generator(index);
+    gen3 = index - gen1 - gen2;
+    gen3 = 10000*(gen3/10000);
+  } else{
+    gen1 = 1000000*(index/1000000);
+    gen2 = index - gen1;
+    gen2 = 100000*(gen2/100000);
+    gen3 = index - gen1 - gen2;
+    gen3 = 10000*(gen3/10000);
+  }
+  return generator_name(gen3);
+}
+
+
+int generator_process(int& index) { return index % 10000; }
+
+void GeneratorName_print(int& id) {
+  std::cout << first_generator(id) << " "
+            << second_generator(id) << " "
+            << third_generator(id) << " + "
+            << generator_process(id);
+}
+
+std::string generator_string(const int& index) {
+  switch (index) {
+  case 110000000  : return "PYTHIA";
+  case 20000000  : return "HERWIG";
+  case 30000000  : return "ISAJET";
+  case 40000000  : return "SINGLE";
+  case 50000000  : return "HIJING";
+  case 60000000  : return "PHOJET";
+  case 70000000  : return "Sherpa";
+  case 80000000  : return "CASCADE";
+  case 90000000  : return "JIMMY";
+  case 100000000 : return "HYDJET";
+  case 120000000 : return "EPOS";
+  case 100000   : return "COMPHEP";
+    //  case 150000   : return "CHARYBDIS";
+  case 200000   : return "USER";
+  case 300000   : return "ACERMC";
+  case 400000   : return "ALPGEN";
+  case 500000   : return "MADGRAPH";
+  case 600000   : return "MADCUP";
+  case 700000   : return "TOPREX";
+  case 800000   : return "LHAEXT";
+  case 900000   : return "MCATNLO";
+  case 1001000000   : return "CHARYBDIS";
+  case 1001100000   : return "HORACE";
+  case 1001200000   : return "LHEF";
+  case 1001300000   : return "MATCHIG";
+  case 1001400000   : return "HVGEN";
+  case 1001500000   : return "EXOGRAVITON";
+  case 1001600000   : return "PYTHIABC";
+  case 1001700000   : return "PROTOS";
+  case 1001800000   : return "GRAVADD";
+  case 1001900000   : return "HELAC";
+  case 1002000000   : return "PYTHIASGLUON";
+  case 10000    : return "TAUOLA";
+  case 20000    : return "PHOTOS";
+  case 30000    : return "TAUOLA_PHOTOS";
+  }
+  return "";
+}
+
+int generator_int (std::string& name) {
+  /// @note Sherpa cannot be written with capital letters as it interferes with the namespace name from external Sherpa package.  EML 11.12.2008
+  if (name == "sherpa") name = "Sherpa";
+  else transform(name.begin(), name.end(), name.begin(), toupper);
+  if ( name == "PYTHIA" )        return 110000000;
+  if ( name == "HERWIG" )        return 20000000;
+  if ( name == "ISAJET" )        return 30000000;
+  if ( name == "SINGLE" )        return 40000000;
+  if ( name == "HIJING" )        return 50000000;
+  if ( name == "PHOJET" )        return 60000000;
+  if ( name == "Sherpa" )        return 70000000;
+  if ( name == "CASCADE" )       return 80000000;
+  if ( name == "JIMMY" )         return 90000000;
+  if ( name == "HYDJET" )        return 100000000;
+  if ( name == "EPOS" )          return 120000000;
+  if ( name == "COMPHEP" )       return 100000;
+  //  if ( name == "CHARYBDIS" )     return 150000;
+  if ( name == "USER" )          return 200000;
+  if ( name == "ACERMC" )        return 300000;
+  if ( name == "ALPGEN" )        return 400000;
+  if ( name == "MADGRAPH" )      return 500000;
+  if ( name == "MADCUP" )        return 600000;
+  if ( name == "TOPREX" )        return 700000;
+  if ( name == "LHAEXT" )        return 800000;
+  if ( name == "MCATNLO" )       return 900000;
+  if ( name == "CHARYBDIS" )     return 1001000000;
+  if (name == "HORACE" )        return 1001100000;
+  if (name == "LHEF")           return 1001200000;
+  if (name == "MATCHIG")        return 1001300000;
+  if (name == "HVGEN")          return 1001400000;
+  if (name == "EXOGRAVITON")    return 1001500000;
+  if (name == "PYTHIABC")       return 1001600000;
+  if (name == "PROTOS")         return 1001700000;
+  if (name == "GRAVADD")        return 1001800000;
+  if (name == "HELAC")          return 1001900000;
+  if (name == "PYTHIASGLUON")   return 1002000000;
+  if ( name == "TAUOLA" )        return 10000;
+  if ( name == "PHOTOS" )        return 20000;
+  if ( name == "TAUOLA_PHOTOS" ) return 30000;
+  return -999;
+}
+
+std::ostream& operator<<(std::ostream& lhs, GeneratorName rhs) {
+  lhs << generator_string(rhs);
+  return lhs;
+}
+
+bool isNewGenCoding(const int& index) {
+  if (index < 20000000) return false;
+  else return true;
+}
diff --git a/Generators/TruthUtils/TruthUtils/GeneratorName.h b/Generators/TruthUtils/TruthUtils/GeneratorName.h
new file mode 100644
index 0000000000000000000000000000000000000000..9f702d852c3009f3322c4ae190261fe96b7d500a
--- /dev/null
+++ b/Generators/TruthUtils/TruthUtils/GeneratorName.h
@@ -0,0 +1,93 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRUTHUTILS_GENERATORNAME_H
+#define TRUTHUTILS_GENERATORNAME_H
+
+#include <iosfwd>
+#include <string>
+
+/// @file GeneratorName.h
+/// @brief Enum and tools for decoding generator information from the process code -- yuck!
+/// @todo This thing is a mess that completely breaks down with LHE files and new gens. REMOVE!
+
+
+/// @note Sherpa cannot be used with capital letters as it interferes with the namespace name from external Sherpa package.
+/// @note New generators need to be added in genames.inc too EML 12.12.2008
+/// @note PYTHIA instead of a special number 1010000000 is now 110000000 (the special number may be used when we run out of other numbers) EML 19.01.2009
+enum GeneratorName {
+  /*
+  PYTHIA          = 1000000,
+  HERWIG          = 2000000,
+  ISAJET          = 3000000,
+  SINGLE          = 4000000,
+  HIJING          = 5000000,
+  PHOJET          = 6000000,
+  Sherpa          = 7000000,
+  CASCADE         = 8000000,
+  JIMMY           = 9000000,
+  HYDJET          = 10000000,
+  */
+  // first generators - new scheme
+  PYTHIA          = 110000000,
+  HERWIG          = 20000000,
+  ISAJET          = 30000000,
+  SINGLE          = 40000000,
+  HIJING          = 50000000,
+  PHOJET          = 60000000,
+  Sherpa          = 70000000,
+  CASCADE         = 80000000,
+  JIMMY           = 90000000,
+  HYDJET          = 100000000,
+  // note 110000000 used for PYTHIA
+  EPOS            = 120000000,
+
+  // second generators
+  COMPHEP         = 100000,
+  //  CHARYBDIS   = 150000,
+  USER            = 200000,
+  ACERMC          = 300000,
+  ALPGEN          = 400000,
+  MADGRAPH        = 500000,
+  MADCUP          = 600000,
+  TOPREX          = 700000,
+  LHAEXT          = 800000,
+  MCATNLO         = 900000,
+  // new second generators - new scheme
+  CHARYBDIS       = 1001000000,
+  HORACE          = 1001100000,
+  LHEF            = 1001200000,
+  MATCHIG         = 1001300000,
+  HVGEN           = 1001400000,
+  EXOGRAVITON     = 1001500000,
+  PYTHIABC        = 1001600000,
+  PROTOS          = 1001700000,
+  GRAVADD         = 1001800000,
+  HELAC           = 1001900000,
+  PYTHIASGLUON    = 1002000000,
+
+  // third generators
+  TAUOLA          = 10000,
+  PHOTOS          = 20000,
+  TAUOLA_PHOTOS   = 30000,
+  UNKNOWN         = -999
+};
+
+
+GeneratorName  generator_name(const int& index);
+GeneratorName  first_generator(const int& index);
+GeneratorName  second_generator(const int& index);
+GeneratorName  third_generator(const int& index);
+
+int            generator_process(int& index);
+
+void           GeneratorName_print(int& id);
+std::string    generator_string(const int& index);
+int            generator_int(std::string& name);
+
+std::ostream &operator<< (std::ostream& lhs, GeneratorName rhs);
+bool isNewGenCoding(const int& index);
+
+
+#endif // GENERATORMODULES_GENERATORNAME_H
diff --git a/Generators/TruthUtils/TruthUtils/HepMCHelpers.h b/Generators/TruthUtils/TruthUtils/HepMCHelpers.h
new file mode 100644
index 0000000000000000000000000000000000000000..27964dc5a2f374c9ebc157a3a4b99f1627602ec3
--- /dev/null
+++ b/Generators/TruthUtils/TruthUtils/HepMCHelpers.h
@@ -0,0 +1,96 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#pragma once
+
+/// @file
+///
+/// Provides the HepMC tools from the external MCUtils header package,
+/// ATLAS-specific HepMC functions not suitable for MCUtils.
+
+#include "TruthUtils/PIDHelpers.h"
+#include "TruthUtils/TruthParticleHelpers.h"
+#include "MCUtils/HepMCUtils.h"
+// #include "MCUtils/Clustering.h"
+
+// Common imports from external namespaces
+using HepMC::GenEvent;
+using HepMC::GenParticle;
+using HepMC::GenVertex;
+//using fastjet::PseudoJet;
+//using fastjet::ClusterSequence;
+
+// Alias BOOST_FOREACH as foreach in this semi-safe way
+#include <boost/foreach.hpp>
+#ifndef foreach
+namespace boost { namespace BOOST_FOREACH = foreach; }
+#define foreach BOOST_FOREACH
+#endif
+
+
+namespace MC {
+
+  // Use the MCUtils and HEPUtils functions as if they were defined in the ATLAS MC and MC::PID namespaces
+  using namespace MCUtils;
+  using namespace HEPUtils;
+
+
+  /// @name Extra ATLAS-specific particle classifier functions
+  //@{
+
+  /// @brief Determine if the particle is stable at the generator (not det-sim) level,
+  ///
+  /// The receipe for this is barcode < 200k and status = 1. Gen-stable particles decayed by
+  /// G4 are not set to have status = 2 in ATLAS, but simply have more status = 1 children,
+  /// with barcodes > 200k.
+  inline bool isGenStable(const HepMC::GenParticle* p) {
+    return isGenStable(p->status(), p->barcode());
+  }
+
+
+  /// @todo There are many kinds of stable: stable from generator, stable at intermediate stage of det sim transport, or stable after all det sim. Need fns for each?
+
+
+  /// @brief Identify if the particle is considered stable at the post-detector-sim stage
+  inline bool isSimStable(const HepMC::GenParticle* p) {
+    if (p->status() != 1) return false;
+    if (isGenStable(p)) return p->end_vertex() == NULL;
+    return true;
+  }
+
+  /// @brief Identify if the particle is considered stable at the post-detector-sim stage
+  /// @todo I'm sure this shouldn't be exactly the same as isGenStable, but it is...
+  /// @deprecated Use isSimulStable: this function _will_ be removed!
+  inline bool isGenSimulStable(const HepMC::GenParticle* p) {
+    return isSimStable(p);
+  }
+
+
+  /// @brief Identify if the particle would not interact with the detector, i.e. not a neutrino or WIMP
+  inline bool isNonInteracting(const HepMC::GenParticle* p) {
+    return MC::isNonInteracting(p->pdg_id()); //< From TruthUtils/PIDHelpers.h
+  }
+
+  /// @brief Identify if the particle could interact with the detector during the simulation, e.g. not a neutrino or WIMP
+  /// @todo This one can't be made to only take a PDG ID argument since it needs to check gen-stability via status & decay links
+  // inline bool isSimInteracting(int pid) {
+  //   if (! MC::isGenStable(pid)) return false; //skip particles which the simulation would not see
+  //   return !MC::isNonInteracting(pid);
+  // }
+  /// @brief Identify if the particle could interact with the detector during the simulation, e.g. not a neutrino or WIMP
+  inline bool isSimInteracting(const HepMC::GenParticle* p) {
+    if (! MC::isGenStable(p)) return false; //skip particles which the simulation would not see
+    return !MC::isNonInteracting(p);
+  }
+
+  /// @brief Oddly-named alias for isSimInteracting
+  /// @deprecated Use isSimInteracting: this function _will_ be removed!
+  inline bool isGenInteracting(const HepMC::GenParticle* p) {
+    return isSimInteracting(p);
+  }
+
+  //@}
+
+
+}
diff --git a/Generators/TruthUtils/TruthUtils/PIDHelpers.h b/Generators/TruthUtils/TruthUtils/PIDHelpers.h
new file mode 100644
index 0000000000000000000000000000000000000000..b10272803c4e193b0cbbc888ae09ace530319a89
--- /dev/null
+++ b/Generators/TruthUtils/TruthUtils/PIDHelpers.h
@@ -0,0 +1,33 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#pragma once
+
+/// @file
+///
+/// PID-only functions with no HepMC dependence, both from MCUtils and ATLAS-specific.
+
+#include "MCUtils/PIDUtils.h"
+
+namespace MC {
+
+  // Use the MCUtils and HEPUtils functions as if they were defined in the ATLAS MC and MC::PID namespaces
+  using namespace MCUtils;
+  using namespace HEPUtils;
+
+
+  /// @brief Identify if the particle with given PDG ID would not interact with the detector, i.e. not a neutrino or WIMP
+  inline bool isNonInteracting(int pid) {
+    return !(PID::isStrongInteracting(pid) || PID::isEMInteracting(pid));
+  }
+
+
+  /// @brief Identify if the particle with given PDG ID would produce ID tracks but not shower in the detector if stable
+  inline bool isChargedNonShowering(int pid) {
+    if (PID::isMuon(pid)) return true;
+    if (PID::isSUSY(pid)) return true; //(meta)stable charginos, R-hadrons etc
+     return false;
+   }
+
+}
diff --git a/Generators/TruthUtils/TruthUtils/TruthParticleHelpers.h b/Generators/TruthUtils/TruthUtils/TruthParticleHelpers.h
new file mode 100644
index 0000000000000000000000000000000000000000..22a9ff510fc3f50f42fa20adc8295c7f392bcef6
--- /dev/null
+++ b/Generators/TruthUtils/TruthUtils/TruthParticleHelpers.h
@@ -0,0 +1,43 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#pragma once
+
+/// @file
+///
+/// Provides the HepMC tools from the external MCUtils header package,
+/// ATLAS-specific HepMC functions not suitable for MCUtils.
+
+#include "TruthUtils/PIDHelpers.h"
+
+namespace MC {
+
+  // Use the MCUtils and HEPUtils functions as if they were defined in the ATLAS MC and MC::PID namespaces
+  using namespace MCUtils;
+  using namespace HEPUtils;
+
+
+  /// @brief Constant defining the barcode threshold distinguishing generator record entries from detector sim ones
+  /// @todo The sim barcodes start at 1M in MC15, so we should update the 200k threshold,
+  ///   but >= 200k is still a valid test for b = 1M so let's keep it this way until MC12 is long-dead.
+  const int SIM_BARCODE_THRESHOLD = 200000;
+
+
+  /// @name Extra ATLAS-specific particle classifier functions
+  //@{
+
+  /// @brief Determine if the particle is stable at the generator (not det-sim) level,
+  ///
+  /// The receipe for this is barcode < 200k and status = 1. Gen-stable particles decayed by
+  /// G4 are not set to have status = 2 in ATLAS, but simply have more status = 1 children,
+  /// with barcodes > 200k.
+  inline bool isGenStable(int status, int barcode) {
+    if (status != 1) return false;
+    return barcode < SIM_BARCODE_THRESHOLD;
+  }
+
+  //@}
+
+
+}
diff --git a/Generators/TruthUtils/cmt/Makefile.RootCore b/Generators/TruthUtils/cmt/Makefile.RootCore
new file mode 100644
index 0000000000000000000000000000000000000000..fb79602e0c08ab4c09763cb558ec32602f05eaae
--- /dev/null
+++ b/Generators/TruthUtils/cmt/Makefile.RootCore
@@ -0,0 +1,24 @@
+# this makefile also gets parsed by shell scripts
+# therefore it does not support full make syntax and features
+# edit with care
+
+# for full documentation check:
+# https://twiki.cern.ch/twiki/bin/viewauth/Atlas/RootCore#Package_Makefile
+
+PACKAGE          = TruthUtils
+PACKAGE_PRELOAD  =
+PACKAGE_CXXFLAGS =
+PACKAGE_OBJFLAGS =
+PACKAGE_LDFLAGS  =
+PACKAGE_BINFLAGS =
+PACKAGE_LIBFLAGS =
+PACKAGE_DEP      = Asg_Boost
+PACKAGE_TRYDEP   =
+PACKAGE_CLEAN    =
+PACKAGE_NOGRID   =
+PACKAGE_PEDANTIC = 0
+PACKAGE_NOOPT    = 0
+PACKAGE_NOCC     = 0
+PACKAGE_REFLEX   = 0
+
+include $(ROOTCOREDIR)/Makefile-common
diff --git a/Generators/TruthUtils/cmt/requirements b/Generators/TruthUtils/cmt/requirements
new file mode 100644
index 0000000000000000000000000000000000000000..16a8a9a5b757572ce10c6e6d8c25cece53811831
--- /dev/null
+++ b/Generators/TruthUtils/cmt/requirements
@@ -0,0 +1,14 @@
+package TruthUtils
+
+author Andy Buckley
+
+use AtlasPolicy         AtlasPolicy-*
+use AtlasHepMC          AtlasHepMC-*          External
+use AtlasBoost          AtlasBoost-*          External
+use AtlasFastJet        AtlasFastJet-*        External
+use AtlasROOT           AtlasROOT-*           External
+use MCUtils             MCUtils-*             External
+use HEPUtils            HEPUtils-*            External
+
+library TruthUtils ../Root/*.cxx
+apply_pattern installed_library
diff --git a/Projects/Calypso/package_filters.txt b/Projects/Calypso/package_filters.txt
index 1eaecdb54f06cd6c309f009f84ae1e0bffa5ddb1..5e7804ee05b89fabc0506e40320b750890cb10c7 100644
--- a/Projects/Calypso/package_filters.txt
+++ b/Projects/Calypso/package_filters.txt
@@ -9,4 +9,4 @@
 - Database/.*
 - DetectorDescription/.*
 - Scintillator/.*
-- Tracker/TrackerDetDescr/.*
\ No newline at end of file
+- Tracker/.*
\ No newline at end of file
diff --git a/xAOD/xAODBase/CMakeLists.txt b/xAOD/xAODBase/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..866ebe3bf79054080bdd85fed766f956f862ee4c
--- /dev/null
+++ b/xAOD/xAODBase/CMakeLists.txt
@@ -0,0 +1,42 @@
+# $Id: CMakeLists.txt 744422 2016-05-03 11:34:39Z krasznaa $
+################################################################################
+# Package: xAODBase
+################################################################################
+
+# Declare the package name:
+atlas_subdir( xAODBase )
+
+# Extra dependencies based on what environment we are in:
+if( NOT XAOD_STANDALONE )
+   set( extra_deps Control/SGTools )
+   set( extra_libs SGTools )
+endif()
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs(
+   PUBLIC
+   Control/AthContainers
+   ${extra_deps}
+   PRIVATE
+   Control/AthLinks )
+
+# External dependencies:
+find_package( ROOT COMPONENTS Core Physics )
+
+# Component(s) in the package:
+atlas_add_library( xAODBase
+   xAODBase/*.h Root/*.cxx
+   PUBLIC_HEADERS xAODBase
+   INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
+   LINK_LIBRARIES ${ROOT_LIBRARIES} AthContainers ${extra_libs}
+   PRIVATE_LINK_LIBRARIES AthLinks )
+
+atlas_add_dictionary( xAODBaseDict
+   xAODBase/xAODBaseDict.h
+   xAODBase/selection.xml
+   LINK_LIBRARIES xAODBase )
+
+# Test(s) in the package:
+atlas_add_test( ut_xAODObjectType_test
+   SOURCES test/ut_xAODObjectType_test.cxx
+   LINK_LIBRARIES xAODBase )
diff --git a/xAOD/xAODBase/Root/IParticleHelpers.cxx b/xAOD/xAODBase/Root/IParticleHelpers.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..1350ca88bb59ed6d4de2d8993edd7ea3ea645aa5
--- /dev/null
+++ b/xAOD/xAODBase/Root/IParticleHelpers.cxx
@@ -0,0 +1,161 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: IParticleHelpers.cxx 700032 2015-10-12 11:38:33Z krasznaa $
+
+// System include(s):
+#include <iostream>
+
+// EDM include(s):
+#include "AthLinks/ElementLink.h"
+
+// Local include(s):
+#include "xAODBase/IParticleHelpers.h"
+
+namespace xAOD {
+
+   /// Object used for setting/getting the dynamic decoration in question
+   static SG::AuxElement::Accessor< ElementLink< IParticleContainer > >
+      acc( "originalObjectLink" );
+
+   /// This function should be used by CP tools when they make a deep copy
+   /// of an object in their correctedCopy(...) function. So that the deep
+   /// copy would hold an ElementLink pointing back to its original, which
+   /// the MET calculations can use later on.
+   ///
+   /// @param original Reference to the original object
+   /// @param copy Reference to the (deep/shallow) copy of the original object
+   /// @returns <code>true</code> if the link setting was successful,
+   ///          <code>false</code> if it wasn't
+   ///
+   bool setOriginalObjectLink( const IParticle& original,
+                               IParticle& copy ) {
+
+      // We mustn't check for the availability of the decoration on the copied
+      // object here. Since if the copy is already part of a container, the
+      // decoration may well exist on it already. But it will not be set to
+      // anything meaningful yet.
+
+      // Check if the original is part of a container. If not, we can't set
+      // up a link.
+      const IParticleContainer* container =
+         dynamic_cast< const IParticleContainer* >( original.container() );
+      if( ! container ) {
+         std::cerr << "xAOD::setOriginalObjectLink   ERROR Original object is "
+                   << "not part of a container" << std::endl;
+         return false;
+      }
+
+      // Construct the ElementLink that points back to the original.
+      // We have to be tricky here. The original itself may already be a
+      // copy. In which case the new object should point back to the same
+      // original that "our original" is pointing to.
+      const ElementLink< IParticleContainer > link =
+         ( acc.isAvailable( original ) ?
+           acc( original ) :
+           ElementLink< IParticleContainer >( *container, original.index() ) );
+
+      // Now set this link on the copy:
+      acc( copy ) = link;
+
+      // We were successful:
+      return true;
+   }
+
+   /// This function should be used by the users when they make deep/shallow
+   /// copies of an entire container. It sets up links from all the copied
+   /// object to their originals. So in later stages of the analysis one can
+   /// navigate back to them. (This is mostly necessary for proper MET
+   /// handling.)
+   ///
+   /// This function assumes that the original container is *not* a view
+   /// container, to be able to optimise the code a bit. If you want to use
+   /// a view container, loop over its elements by hand, and use the version
+   /// of this function operating on individual xAOD::IParticle objects.
+   ///
+   /// @param original Reference to the original container
+   /// @param copy Reference to the (deep/shallow) copy of the original
+   ///             container
+   /// @returns <code>true</code> if the link setting was successful,
+   ///          <code>false</code> if it wasn't
+   ///
+   bool setOriginalObjectLink( const IParticleContainer& original,
+                               IParticleContainer& copy ) {
+
+      // Check that the containers are of the same size:
+      if( original.size() != copy.size() ) {
+         std::cerr << "xAOD::setOriginalObjectLink   ERROR Size of original "
+                   << "and copy containers differs" << std::endl;
+         return false;
+      }
+
+      // Make sure that the original is not a view container. As the function
+      // doesn't work correctly for those.
+      if( original.ownPolicy() != SG::OWN_ELEMENTS ) {
+         std::cerr << "xAOD::setOriginalObjectLink   ERROR Received a view "
+                   << "container" << std::endl;
+         return false;
+      }
+
+      // If the containers are empty, we're done:
+      if( ! copy.size() ) {
+         return true;
+      }
+
+      // Create an ElementLink to the first element in the original container.
+      // To be able to re-use the hashed key of this object in the loop.
+      const ElementLink< IParticleContainer > refLink( original, 0 );
+
+      // Loop over the copied container:
+      IParticleContainer::const_iterator orig_itr = original.begin();
+      IParticleContainer::const_iterator orig_end = original.end();
+      IParticleContainer::iterator copy_itr = copy.begin();
+      // To speed up the loop over large containers a bit, make the decision
+      // about how to create the links, just once:
+      if( acc.isAvailable( **orig_itr ) ) {
+         for( ; orig_itr != orig_end; ++orig_itr, ++copy_itr ) {
+            // Copy the variable from the original object:
+            acc( **copy_itr ) = acc( **orig_itr );
+         }
+      } else {
+         for( ; orig_itr != orig_end; ++orig_itr, ++copy_itr ) {
+            // Construct the link from scratch:
+            acc( **copy_itr ) =
+               ElementLink< IParticleContainer >( refLink.key(),
+                                                  ( *orig_itr )->index() );
+         }
+      }
+
+      // We were successful:
+      return true;
+   }
+
+   /// This function can be used to conveniently get a pointer back to the
+   /// original object from which a copy was created. If there is no such
+   /// parent, the function silently returns a null pointer.
+   ///
+   /// @param copy The object that should have a parent set on it
+   /// @returns A pointer to the objects parent if it exists and its available,
+   ///          a null pointer otherwise
+   ///
+   const IParticle* getOriginalObject( const IParticle& copy ) {
+
+      // Check if the decoration is available on the object:
+      if( ! acc.isAvailable( copy ) ) {
+         return 0;
+      }
+
+      // Get the link:
+      const ElementLink< IParticleContainer >& link = acc( copy );
+
+      // Check if the link is valid:
+      if( ! link.isValid() ) {
+         return 0;
+      }
+
+      // Apparently all is fine:
+      return *link;
+   }
+
+} // namespace xAOD
diff --git a/xAOD/xAODBase/Root/ObjectType.cxx b/xAOD/xAODBase/Root/ObjectType.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..cfb84e6853322278fd337c620b1657aa403df6a4
--- /dev/null
+++ b/xAOD/xAODBase/Root/ObjectType.cxx
@@ -0,0 +1,53 @@
+// System include(s):
+#include <iostream>
+
+// Local include(s):
+#include "xAODBase/ObjectType.h"
+
+/// Helper macro for printing the object type as a string
+#define PRINT_TYPE( TYPE )                      \
+   case TYPE:                                   \
+      out << #TYPE;                             \
+      break
+
+/// This function can be used in (debug) printouts to easily show the type
+/// name returned by an object.
+///
+/// @param out The STL stream to print to
+/// @param type The type whose name to print in the stream
+/// @returns The same stream that it received
+///
+std::ostream& operator<< ( std::ostream& out, xAOD::Type::ObjectType type ) {
+
+   switch( type ) {
+
+      PRINT_TYPE( xAOD::Type::Other );
+
+      PRINT_TYPE( xAOD::Type::CaloCluster );
+      PRINT_TYPE( xAOD::Type::Track );
+      PRINT_TYPE( xAOD::Type::NeutralParticle );
+      PRINT_TYPE( xAOD::Type::Electron );
+      PRINT_TYPE( xAOD::Type::Photon );
+      PRINT_TYPE( xAOD::Type::Muon );
+
+      PRINT_TYPE( xAOD::Type::Vertex );
+
+      PRINT_TYPE( xAOD::Type::TruthParticle );
+      PRINT_TYPE( xAOD::Type::TruthVertex );
+      PRINT_TYPE( xAOD::Type::TruthEvent );
+      PRINT_TYPE( xAOD::Type::TruthPileupEvent );
+      
+      PRINT_TYPE( xAOD::Type::EventInfo );
+      PRINT_TYPE( xAOD::Type::EventFormat );
+
+      PRINT_TYPE( xAOD::Type::Particle );
+      PRINT_TYPE( xAOD::Type::CompositeParticle );
+
+   default:
+      out << "UNKNOWN";
+      break;
+   }
+
+   // Return the stream object:
+   return out;
+}
diff --git a/xAOD/xAODBase/cmt/Makefile.RootCore b/xAOD/xAODBase/cmt/Makefile.RootCore
new file mode 100644
index 0000000000000000000000000000000000000000..eb90d13563386d545435fa7d02ac78ecb49f14db
--- /dev/null
+++ b/xAOD/xAODBase/cmt/Makefile.RootCore
@@ -0,0 +1,24 @@
+# this makefile also gets parsed by shell scripts
+# therefore it does not support full make syntax and features
+# edit with care
+
+# for full documentation check:
+# https://twiki.cern.ch/twiki/bin/viewauth/Atlas/RootCore#Package_Makefile
+
+PACKAGE          = xAODBase
+PACKAGE_PRELOAD  = Physics
+PACKAGE_CXXFLAGS = 
+PACKAGE_OBJFLAGS = 
+PACKAGE_LDFLAGS  = 
+PACKAGE_BINFLAGS = 
+PACKAGE_LIBFLAGS = 
+PACKAGE_DEP      = AthContainers AthLinks
+PACKAGE_TRYDEP   = 
+PACKAGE_CLEAN    = 
+PACKAGE_NOGRID   = 
+PACKAGE_PEDANTIC = 1
+PACKAGE_NOOPT    = 0
+PACKAGE_NOCC     = 0
+PACKAGE_REFLEX   = 1
+
+include $(ROOTCOREDIR)/Makefile-common
diff --git a/xAOD/xAODBase/cmt/requirements b/xAOD/xAODBase/cmt/requirements
new file mode 100644
index 0000000000000000000000000000000000000000..8886e2cbdd84e4aa42f6de90907e8bd7041cdbcf
--- /dev/null
+++ b/xAOD/xAODBase/cmt/requirements
@@ -0,0 +1,31 @@
+package xAODBase
+# $Id: requirements 744422 2016-05-03 11:34:39Z krasznaa $
+#
+
+author Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch>
+
+# Base package(s):
+use AtlasPolicy   AtlasPolicy-*
+use AtlasROOT     AtlasROOT-*     External
+use SGTools       SGTools-*       Control
+
+# EDM package(s):
+use AthContainers AthContainers-* Control
+
+apply_tag ROOTMathLibs
+
+library xAODBase ../Root/*.cxx
+apply_pattern installed_library
+
+private
+
+use AtlasReflex   AtlasReflex-*   External
+use AthLinks      AthLinks-*      Control
+
+apply_pattern lcgdict dict=xAODBase selectionfile=selection.xml \
+                      headerfiles="../xAODBase/xAODBaseDict.h"
+
+# Set up the test(s):
+use TestTools     TestTools-*     AtlasTest
+
+apply_pattern UnitTest_run unit_test=ut_xAODObjectType
diff --git a/xAOD/xAODBase/doc/mainpage.h b/xAOD/xAODBase/doc/mainpage.h
new file mode 100644
index 0000000000000000000000000000000000000000..a13fe15701e55beb5a1a9297a4c112b09131119d
--- /dev/null
+++ b/xAOD/xAODBase/doc/mainpage.h
@@ -0,0 +1,31 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+   @mainpage xAODBase package
+
+   @author Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch>
+
+   $Revision: 567380 $
+   $Date: 2013-10-28 11:48:26 +0100 (Mon, 28 Oct 2013) $
+
+   @section xAODBaseOverview Overview
+
+   This is the most base-package of the xAOD EDM. It defines general
+   interfaces that are used in all parts of the xAOD code.
+
+   @section xAODBaseClasses Main Types
+
+   The main enumerations, definitions and classes of the package are
+   the following:
+      - xAOD::Type::ObjectType: Enumeration describing all major xAOD
+        object types.
+      - xAOD::IParticle: Interface for all particle-like EDM classes
+      - xAOD::IParticleContainer: Base class for all the particle-like
+        containers in the xAOD EDM.
+
+   @htmlinclude used_packages.html
+
+   @include requirements
+*/
diff --git a/xAOD/xAODBase/share/ut_xAODObjectType_test.ref b/xAOD/xAODBase/share/ut_xAODObjectType_test.ref
new file mode 100644
index 0000000000000000000000000000000000000000..4b97169887aa3febeae8301c2d28af06d3419ad0
--- /dev/null
+++ b/xAOD/xAODBase/share/ut_xAODObjectType_test.ref
@@ -0,0 +1,2 @@
+xAOD::Type::Track, xAOD::Type::CaloCluster
+UNKNOWN
diff --git a/xAOD/xAODBase/test/ut_xAODObjectType_test.cxx b/xAOD/xAODBase/test/ut_xAODObjectType_test.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..14e31e0ab642450876e904246b94510a34cdbde3
--- /dev/null
+++ b/xAOD/xAODBase/test/ut_xAODObjectType_test.cxx
@@ -0,0 +1,26 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: ut_xAODObjectType_test.cxx 618658 2014-09-26 09:31:10Z krasznaa $
+//
+// This is an extremely simple test to check the health of the output operator
+// defined in xAODBase/ObjectType.h.
+///
+
+// System include(s):
+#include <iostream>
+
+// Local include(s):
+#include "xAODBase/ObjectType.h"
+
+int main() {
+
+   // Print some random values:
+   std::cout << xAOD::Type::Track << ", " << xAOD::Type::CaloCluster
+             << std::endl;
+   std::cout << static_cast< xAOD::Type::ObjectType >( 1500 ) << std::endl;
+
+   // Return gracefully:
+   return 0;
+}
diff --git a/xAOD/xAODBase/xAODBase/IParticle.h b/xAOD/xAODBase/xAODBase/IParticle.h
new file mode 100644
index 0000000000000000000000000000000000000000..97e598ef97a242465ccf80cae6c8674f85eddf59
--- /dev/null
+++ b/xAOD/xAODBase/xAODBase/IParticle.h
@@ -0,0 +1,169 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: IParticle.h 604340 2014-07-01 04:04:52Z ssnyder $
+#ifndef XAODBASE_IPARTICLE_H
+#define XAODBASE_IPARTICLE_H
+
+// ROOT include(s):
+#include <TLorentzVector.h>
+
+// EDM include(s):
+#include "AthContainers/AuxElement.h"
+
+// Local include(s):
+#include "ObjectType.h"
+
+/// Namespace holding all the xAOD EDM classes
+namespace xAOD {
+
+   /// Class providing the definition of the 4-vector interface
+   ///
+   /// All particle-like classes in the xAOD EDM inherit from this simple
+   /// interface class to make it simple to write generic analysis code
+   /// for the objects.
+   ///
+   /// @author Andy Buckley <Andy.Buckley@cern.ch>
+   /// @author Till Eifert <Till.Eifert@cern.ch>
+   /// @author Markus Elsing <Markus.Elsing@cern.ch>
+   /// @author Dag Gillberg <Dag.Gillberg@cern.ch>
+   /// @author Karsten Koeneke <karstenkoeneke@gmail.com>
+   /// @author Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch>
+   /// @author Edward Moyse <Edward.Moyse@cern.ch>
+   ///
+   /// $Revision: 604340 $
+   /// $Date: 2014-07-01 06:04:52 +0200 (Tue, 01 Jul 2014) $
+   ///
+   class IParticle : public SG::AuxElement {
+
+   public:
+      /// Virtual destructor, to make vtable happy...
+      virtual ~IParticle() {}
+
+
+      /// @name Functions describing the 4-momentum of the object
+      /// @{
+
+      /// The transverse momentum (\f$p_T\f$) of the particle
+      virtual double           pt() const = 0;
+      /// The pseudorapidity (\f$\eta\f$) of the particle
+      virtual double           eta() const = 0;
+      /// The azimuthal angle (\f$\phi\f$) of the particle
+      virtual double           phi() const = 0;
+      /// The invariant mass of the particle
+      virtual double           m() const = 0;
+      /// The total energy of the particle
+      virtual double           e() const = 0;
+      /// The true rapidity (y) of the particle
+      virtual double           rapidity() const = 0;
+
+      /// Definition of the 4-momentum type
+      typedef TLorentzVector FourMom_t;
+
+      /// The full 4-momentum of the particle
+      virtual const FourMom_t& p4() const = 0;
+
+      /// @}
+
+
+      /// The type of the object as a simple enumeration
+      virtual Type::ObjectType type() const = 0;
+
+
+      /// @name Functions for getting and setting user properties
+      /// @{
+
+      /// Fetch an aux data variable, as a non-const reference
+      ///
+      /// This function provides an easy way for users to decorate objects
+      /// with auxiliary data.
+      ///
+      /// Take note that this function is slow. Should not be used inside
+      /// time-critical code.
+      ///
+      /// @param name Name of the aux variable
+      /// @param clsname The name of the associated class.  May be blank
+      /// @returns A modifyable reference to the decoration
+      ///
+      template< class T >
+      T& auxdata( const std::string& name,
+                  const std::string& clsname = "" ) {
+
+         return SG::AuxElement::auxdata< T >( name, clsname );
+      }
+
+      /// Fetch an aux data variable, as a const reference
+      ///
+      /// This function provides an easy way for users to retrieve auxiliary
+      /// decorations from an object.
+      ///
+      /// Take note that this function is slow. Should not be used inside
+      /// time-critical code.
+      ///
+      /// @param name Name of the aux variable
+      /// @param clsname The name of the associated class.  May be blank
+      /// @returns A constant reference to the decoration
+      ///
+      template< class T >
+      const T& auxdata( const std::string& name,
+                        const std::string& clsname = "" ) const {
+
+         return SG::AuxElement::auxdata< T >( name, clsname );
+      }
+
+      /// Check if a user property is available for reading or not
+      ///
+      /// This function should be used to check if a user property which
+      /// may or may not exist, is set on the object.
+      ///
+      /// @param name Name of the auxiliary variable
+      /// @param clsname The name of the associated class.  May be blank
+      /// @returns Whether the decoration exists or not
+      ///
+      template< class T >
+      bool isAvailable( const std::string& name,
+                        const std::string& clsname = "" ) const {
+
+         return SG::AuxElement::isAvailable< T >( name, clsname );
+      }
+
+      /// Check if a user property is available for writing or not
+      ///
+      /// This function can be used to check whether it will be possible to
+      /// set a user property on the object.
+      ///
+      /// @param name Name of the auxiliary variable
+      /// @param clsname The name of the associated class.  May be blank
+      /// @returns Whether the decoration is possible to set
+      ///
+      template< class T >
+      bool isAvailableWritable( const std::string& name,
+                                const std::string& clsname = "" ) const {
+
+         return SG::AuxElement::isAvailableWritable< T >( name, clsname );
+      }
+
+      /// @}
+
+
+   protected:
+      // Hide some functions from the regular xAOD users
+      using SG::AuxElement::getConstStore;
+      using SG::AuxElement::getStore;
+
+      // Hide the Accessor class from the regular xAOD users
+      using SG::AuxElement::Accessor;
+
+   }; // class IParticle
+
+} // namespace xAOD
+
+#ifndef XAOD_STANDALONE
+#include "SGTools/BaseInfo.h"
+SG_BASE (xAOD::IParticle, SG::AuxElement);
+#endif // not XAOD_STANDALONE
+
+#endif // XAODBASE_IPARTICLE_H
diff --git a/xAOD/xAODBase/xAODBase/IParticleContainer.h b/xAOD/xAODBase/xAODBase/IParticleContainer.h
new file mode 100644
index 0000000000000000000000000000000000000000..eef2cac5f653486eac3c943f305b1c9e2ad13667
--- /dev/null
+++ b/xAOD/xAODBase/xAODBase/IParticleContainer.h
@@ -0,0 +1,42 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: IParticleContainer.h 567380 2013-10-28 10:48:26Z krasznaa $
+#ifndef XAODBASE_IPARTICLECONTAINER_H
+#define XAODBASE_IPARTICLECONTAINER_H
+
+// EDM include(s):
+#include "AthContainers/DataVector.h"
+
+// Local include(s):
+#include "xAODBase/IParticle.h"
+
+namespace xAOD {
+
+   /// Simple convenience declaration of IParticleContainer
+   ///
+   /// Note that this structure should be used with care. It should
+   /// mainly be used in tool interfaces, and nowhere else. For instance
+   /// it is possible to put view containers of this type into StoreGate,
+   /// but it is not possible to write out an object of this type into
+   /// an output file.
+   ///
+   /// @author Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch>
+   ///
+   /// $Revision: 567380 $
+   /// $Date: 2013-10-28 11:48:26 +0100 (Mon, 28 Oct 2013) $
+   ///
+   typedef DataVector< IParticle > IParticleContainer;
+
+} // namespace xAOD
+
+// To make it possible to put IParticleContainers into StoreGate:
+#ifndef XAOD_STANDALONE
+#include "SGTools/CLASS_DEF.h"
+CLASS_DEF( xAOD::IParticleContainer, 1241842700, 1 )
+#endif // not XAOD_STANDALONE
+
+#endif // XAODBASE_IPARTICLECONTAINER_H
diff --git a/xAOD/xAODBase/xAODBase/IParticleHelpers.h b/xAOD/xAODBase/xAODBase/IParticleHelpers.h
new file mode 100644
index 0000000000000000000000000000000000000000..707cd033a0f3111bb3eec716a5fa755258194cc2
--- /dev/null
+++ b/xAOD/xAODBase/xAODBase/IParticleHelpers.h
@@ -0,0 +1,30 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: IParticleHelpers.h 618909 2014-09-29 10:16:52Z krasznaa $
+#ifndef XAODBASE_IPARTICLEHELPERS_H
+#define XAODBASE_IPARTICLEHELPERS_H
+
+// Local include(s):
+#include "xAODBase/IParticle.h"
+#include "xAODBase/IParticleContainer.h"
+
+namespace xAOD {
+
+   /// Function setting a link on a deep copy back to its original object
+   bool setOriginalObjectLink( const IParticle& original,
+                               IParticle& copy );
+
+   /// Function setting links on a deep/shallow copy container to the originals
+   bool setOriginalObjectLink( const IParticleContainer& original,
+                               IParticleContainer& copy );
+
+   /// Function getting a pointer to the original object from a deep/shallow copy
+   const IParticle* getOriginalObject( const IParticle& copy );
+
+} // namespace xAOD
+
+#endif // XAODBASE_IPARTICLEHELPERS_H
diff --git a/xAOD/xAODBase/xAODBase/ObjectType.h b/xAOD/xAODBase/xAODBase/ObjectType.h
new file mode 100644
index 0000000000000000000000000000000000000000..657a09ffa4baf4004c5ab2f4df2de71a9ba7bca9
--- /dev/null
+++ b/xAOD/xAODBase/xAODBase/ObjectType.h
@@ -0,0 +1,91 @@
+// $Id: ObjectType.h 618658 2014-09-26 09:31:10Z krasznaa $
+#ifndef XAODBASE_OBJECTTYPE_H
+#define XAODBASE_OBJECTTYPE_H
+
+// System include(s):
+#include <iosfwd>
+
+namespace xAOD {
+
+   /// Namespace for the xAOD object types
+   ///
+   /// The reason for introducing an extra namespace like this is so the users
+   /// will write things like
+   /// <code>if( mypart->type() == xAOD::Type::Muon ) {...}</code>
+   /// instead of using <code>xAOD::MuonType</code> or something similar.
+   ///
+   namespace Type {
+
+      /// Type of objects that have a representation in the xAOD EDM
+      ///
+      /// xAOD classes identify themselves by all of them providing a function
+      /// with the signature:
+      ///
+      ///  <code>
+      ///  xAOD::Type::ObjectType type() const;
+      ///  </code>
+      ///
+      /// This can be used to easily identify what sort of object some generic
+      /// code is dealing with, avoiding doing a lot of
+      /// <code>dynamic_cast</code>-s instead.
+      ///
+      /// Note that Doxygen doesn't allow to group enumeration variables
+      /// together like it does for members of a class, that's why the grouping
+      /// comments are not created according to the Doxygen rules.
+      ///
+      enum ObjectType {
+
+         Other = 0, ///< An object not falling into any of the other categories
+
+         // Reconstructed particle types
+         // {
+
+         CaloCluster  = 1, ///< The object is a calorimeter cluster
+
+         Track   = 2, ///< The object is a charged track particle
+         NeutralParticle = 3, ///< The object is a neutral particle
+
+         Electron = 4, ///< The object is an electron
+         Photon   = 5, ///< The object is a photon
+         Muon     = 6, ///< The object is a muon
+
+         // }
+
+         // Reconstructed non-particle types
+         // {
+
+         Vertex = 101, ///< The object is a vertex
+
+         // }
+
+         // Truth types
+         // {
+
+         TruthParticle    = 201, ///< The object is a truth particle
+         TruthVertex      = 202, ///< The object is a truth vertex
+         TruthEvent       = 203, ///< The object is a truth event
+         TruthPileupEvent = 204, ///< The object is a truth pileup event
+
+         // }
+
+         // Auxiliary types
+         // {
+
+         EventInfo   = 1001, ///< The object is an event information one
+         EventFormat = 1002, ///< The object is an event format one
+
+         Particle          = 1101, ///< Generic particle object, for analysis
+         CompositeParticle = 1102  ///< Particle composed of other particles
+
+         // }
+
+      }; // enum ObjectType
+
+   } // namespace Type
+
+} // namespace xAOD
+
+/// Convenience operator for printing the object type in a (debug) message
+std::ostream& operator<< ( std::ostream& out, xAOD::Type::ObjectType type );
+
+#endif // XAODBASE_OBJECTTYPE_H
diff --git a/xAOD/xAODBase/xAODBase/selection.xml b/xAOD/xAODBase/xAODBase/selection.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b85d3b28a25a37140c0015e1c86d728f77871f61
--- /dev/null
+++ b/xAOD/xAODBase/xAODBase/selection.xml
@@ -0,0 +1,33 @@
+<!-- $Id: selection.xml 618909 2014-09-29 10:16:52Z krasznaa $ -->
+<lcgdict>
+
+  <!-- All the dictionaries for xAOD::IParticle: -->
+  <class name="xAOD::IParticle" />
+  <class name="xAOD::IParticleContainer" />
+  <class name="std::vector<xAOD::IParticle*>" />
+
+  <!-- All smart pointer dictionaries for xAOD::IParticle -->
+  <class name="DataLink<xAOD::IParticleContainer>" />
+  <class name="std::vector<DataLink<xAOD::IParticleContainer> >" />
+
+  <class name="ElementLink<xAOD::IParticleContainer>" />
+  <class name="std::vector<ElementLink<xAOD::IParticleContainer> >" />
+  <class name="std::vector<std::vector<ElementLink<xAOD::IParticleContainer> > >" />
+
+  <class name="ElementLinkVector<xAOD::IParticleContainer>" />
+  <class name="std::vector<ElementLinkVector<xAOD::IParticleContainer> >" />
+
+  <!-- An attempt to make the ObjectType enumeration visible in Python...  -->
+  <enum name="xAOD::Type::ObjectType" />
+
+  <!-- The helper functions: -->
+  <function pattern="xAOD::*" />
+
+  <!-- Suppress the unwanted classes found by ROOT 6. -->
+  <!-- Hopefully we can remove these extra lines at one point... -->
+  <exclusion>
+    <class name="SG::IConstAuxStore" />
+    <class name="DataLink<SG::IConstAuxStore>" />
+  </exclusion>
+
+</lcgdict>
diff --git a/xAOD/xAODBase/xAODBase/xAODBaseDict.h b/xAOD/xAODBase/xAODBase/xAODBaseDict.h
new file mode 100644
index 0000000000000000000000000000000000000000..33067c7bfd1b83bcf846eacc86cda9ae55b3a409
--- /dev/null
+++ b/xAOD/xAODBase/xAODBase/xAODBaseDict.h
@@ -0,0 +1,108 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: xAODBaseDict.h 618909 2014-09-29 10:16:52Z krasznaa $
+#ifndef XAODBASE_XAODBASEDICT_H
+#define XAODBASE_XAODBASEDICT_H
+
+// STL include(s):
+#include <vector>
+
+// EDM include(s):
+#include "AthLinks/DataLink.h"
+#include "AthLinks/ElementLink.h"
+#include "AthLinks/ElementLinkVector.h"
+
+// Local include(s):
+#include "xAODBase/ObjectType.h"
+#include "xAODBase/IParticleContainer.h"
+#include "xAODBase/IParticleHelpers.h"
+
+namespace {
+   struct GCCXML_DUMMY_INSTANTIATION_XAODBASE {
+      xAOD::IParticleContainer c1;
+      DataLink< xAOD::IParticleContainer > l1;
+      ElementLink< xAOD::IParticleContainer > l2;
+      ElementLinkVector< xAOD::IParticleContainer > l3;
+      std::vector< DataLink< xAOD::IParticleContainer > > l4;
+      std::vector< ElementLink< xAOD::IParticleContainer > > l5;
+      std::vector< ElementLinkVector< xAOD::IParticleContainer > > l6;
+      std::vector< std::vector< ElementLink< xAOD::IParticleContainer > > > l7;
+   };
+}
+
+template
+bool& xAOD::IParticle::auxdata< bool >( const std::string& name,
+                                        const std::string& clsname = "" );
+
+template
+float& xAOD::IParticle::auxdata< float >( const std::string& name,
+                                          const std::string& clsname = "" );
+
+template
+int& xAOD::IParticle::auxdata< int >( const std::string& name,
+                                      const std::string& clsname = "" );
+
+template
+unsigned int&
+xAOD::IParticle::auxdata< unsigned int >( const std::string& name,
+                                          const std::string& clsname = "" );
+
+template
+uint8_t& xAOD::IParticle::auxdata< uint8_t >( const std::string& name,
+                                              const std::string& clsname = "" );
+
+template
+const bool&
+xAOD::IParticle::auxdata< bool >( const std::string& name,
+                                  const std::string& clsname = "" ) const;
+
+template
+const float&
+xAOD::IParticle::auxdata< float >( const std::string& name,
+                                   const std::string& clsname = "" ) const;
+
+template
+const int&
+xAOD::IParticle::auxdata< int >( const std::string& name,
+                                 const std::string& clsname = "" ) const;
+
+template
+const unsigned int&
+xAOD::IParticle::auxdata< unsigned int >( const std::string& name,
+                                          const std::string& clsname = "" ) const;
+
+template
+const uint8_t&
+xAOD::IParticle::auxdata< uint8_t >( const std::string& name,
+                                     const std::string& clsname = "" ) const;
+
+template
+bool
+xAOD::IParticle::isAvailable< bool >( const std::string& name,
+                                      const std::string& clsname = "" ) const;
+
+template
+bool
+xAOD::IParticle::isAvailable< float >( const std::string& name,
+                                       const std::string& clsname = "" ) const;
+
+template
+bool
+xAOD::IParticle::isAvailable< int >( const std::string& name,
+                                     const std::string& clsname = "" ) const;
+
+template
+bool
+xAOD::IParticle::isAvailable< unsigned int >( const std::string& name,
+                                              const std::string& clsname = "" ) const;
+
+template
+bool
+xAOD::IParticle::isAvailable< uint8_t >( const std::string& name,
+                                         const std::string& clsname = "" ) const;
+
+#endif // XAODBASE_XAODBASEDICT_H
diff --git a/xAOD/xAODTracking/CMakeLists.txt b/xAOD/xAODTracking/CMakeLists.txt
index 0af665fab93b84a0a687755682cc8fcf9e55f71e..a0e7480507737d3bdd5835df695c975f1c5081dc 100755
--- a/xAOD/xAODTracking/CMakeLists.txt
+++ b/xAOD/xAODTracking/CMakeLists.txt
@@ -7,6 +7,7 @@ atlas_depends_on_subdirs(
    PUBLIC
    Control/AthContainers
    Control/AthLinks
+   Event/xAOD/xAODBase
    Event/xAOD/xAODCore
    ${extra_deps} )
 
@@ -19,7 +20,7 @@ atlas_add_library( xAODTracking
    xAODTracking/*.h Root/*.cxx
    PUBLIC_HEADERS xAODTracking
    INCLUDE_DIRS ${EIGEN_INCLUDE_DIRS}
-   LINK_LIBRARIES ${EIGEN_LIBRARIES} ${ROOT_LIBRARIES} AthContainers AthLinks xAODCore ${extra_libs} )
+   LINK_LIBRARIES ${EIGEN_LIBRARIES} ${ROOT_LIBRARIES} AthContainers AthLinks xAODBase xAODCore ${extra_libs} )
 
 atlas_add_dictionary( xAODTrackingDict
    xAODTracking/xAODTrackingDict.h
@@ -36,7 +37,6 @@ atlas_add_test( xAODTracking_StripRawData_test
    SOURCES test/xAODTracking_StripRawData_test.cxx
    LINK_LIBRARIES xAODTracking )
     
-atlas_add_test( xAODTracking_TrackParticlexAODHelpers_test
-   SOURCES test/xAODTracking_TrackParticlexAODHelpers_test.cxx
-   LINK_LIBRARIES xAODTracking
-   EXTRA_PATTERNS "^DEBUG" )
\ No newline at end of file
+atlas_add_test( xAODTracking_Track_test
+   SOURCES test/xAODTracking_Track_test.cxx
+   LINK_LIBRARIES xAODTracking )
\ No newline at end of file
diff --git a/xAOD/xAODTracking/Root/Track.cxx b/xAOD/xAODTracking/Root/Track.cxx
index bd2c2c8d376fb563353246f4941043c7789acf68..2412c7f5b3f3c14d9148ecfe63430d0af6637655 100644
--- a/xAOD/xAODTracking/Root/Track.cxx
+++ b/xAOD/xAODTracking/Root/Track.cxx
@@ -7,11 +7,7 @@
 
 // Local include(s):
 #include "xAODTracking/Track.h"
-#include "xAODTracking/TrackSummaryAccessors_v1.h"
-#include "EventPrimitives/EventPrimitivesHelpers.h"
-
-// Amg include
-//#include "EventPrimitives/EventPrimitives.h"
+#include "xAODTracking/TrackSummaryAccessors.h"
 
 namespace xAOD {
 
@@ -38,16 +34,27 @@ namespace xAOD {
   Track::~Track(){
   }
   
-  double Track::p() const {
-    return p4().P();
+  double Track::pt() const {
+  return p4().Pt();
   }
-
+  
+  double Track::eta() const {
+  return p4().Eta(); 
+  }
+  
+  double Track::phi() const {
+  return p4().Phi(); 
+  }
+  
   double Track::m() const {
-    return p4().M();
+  return p4().M();
   }
-
+  
   double Track::e() const {
-    return p4().E(); 
+  return p4().E(); 
+  }
+  double Track::rapidity() const {
+  return p4().Rapidity();
   }
 
   const Track::FourMom_t& Track::p4() const {
@@ -71,7 +78,7 @@ namespace xAOD {
   }
 
   Type::ObjectType Track::type() const {
-     return Type::TrackParticle;
+     return Type::Track;
   }
 
   float Track::charge() const {
@@ -80,28 +87,24 @@ namespace xAOD {
 
   AUXSTORE_PRIMITIVE_GETTER(Track, float, x0)
   AUXSTORE_PRIMITIVE_GETTER(Track, float, y0)
+  AUXSTORE_PRIMITIVE_GETTER(Track, float, phi0)
   AUXSTORE_PRIMITIVE_GETTER(Track, float, theta)
   AUXSTORE_PRIMITIVE_GETTER(Track, float, qOverP)
 
   const DefiningParameters_t Track::definingParameters() const{
     DefiningParameters_t tmp;
-    tmp << d0() , z0() , phi0() , theta() , qOverP();
+    tmp << x0() , y0() , phi0() , theta() , qOverP();
     return tmp;
   }
 
-  void Track::setDefiningParameters(float d0, float z0, float phi0, float theta, float qOverP) {
-    m_perigeeCached=false;
-#if ( ! defined(XAOD_STANDALONE) ) && ( ! defined(XAOD_MANACORE) )
-    delete m_perigeeParameters;
-    m_perigeeParameters=0;
-#endif // not XAOD_STANDALONE and not XAOD_MANACORE
-    static Accessor< float > acc1( "d0" );
-    acc1( *this ) = d0;
+  void Track::setDefiningParameters(float x0, float y0, float phi0, float theta, float qOverP) {
+    static Accessor< float > acc1( "x0" );
+    acc1( *this ) = x0;
 
-    static Accessor< float > acc2( "z0" );
-    acc2( *this ) = z0;
+    static Accessor< float > acc2( "y0" );
+    acc2( *this ) = y0;
 
-    static Accessor< float > acc3( "phi" );
+    static Accessor< float > acc3( "phi0" );
     acc3( *this ) = phi0;
 
     static Accessor< float > acc4( "theta" );
@@ -115,20 +118,15 @@ namespace xAOD {
   }
 
   void Track::setDefiningParametersCovMatrix(const xAOD::ParametersCovMatrix_t& cov){
-    m_perigeeCached=false;
-#if ( ! defined(XAOD_STANDALONE) ) && ( ! defined(XAOD_MANACORE) )
-    delete m_perigeeParameters;
-    m_perigeeParameters=0;
-#endif // not XAOD_STANDALONE and not XAOD_MANACORE
 
     static Accessor< std::vector<float> > acc( "definingParametersCovMatrix" );
-    Amg::compress(cov,acc(*this));
+    FMath::compress(cov,acc(*this));
   }
 
   const xAOD::ParametersCovMatrix_t Track::definingParametersCovMatrix() const {
     xAOD::ParametersCovMatrix_t cov; 
     const std::vector<float>& covVec = definingParametersCovMatrixVec();
-    if( !covVec.empty() ) Amg::expand( covVec.begin(), covVec.end(),cov );
+    if( !covVec.empty() ) FMath::expand( covVec.begin(), covVec.end(),cov );
     else cov.setIdentity();
     return cov;
   }
@@ -160,43 +158,6 @@ namespace xAOD {
     acc3( *this ) = z;
   }
 
-#if ( ! defined(XAOD_STANDALONE) ) && ( ! defined(XAOD_MANACORE) )
-  const Trk::Perigee& Track::perigeeParameters() const {
-    if (m_perigeeCached)
-      return *m_perigeeParameters;
-    m_perigeeCached=true;
-
-    static Accessor< float > acc1( "d0" );
-    static Accessor< float > acc2( "z0" );
-    static Accessor< float > acc3( "phi" );
-    static Accessor< float > acc4( "theta" );
-    static Accessor< float > acc5( "qOverP" );
-    static Accessor< std::vector<float> > acc6( "definingParametersCovMatrix" );
-    ParametersCovMatrix_t* cov = new ParametersCovMatrix_t(definingParametersCovMatrix());
-    // cov->setZero();
-    // auto it= acc6(*this).begin();
-    // for (size_t irow = 0; irow<5; ++irow)
-    //   for (size_t icol =0; icol<=irow; ++icol)
-    //       cov->fillSymmetric(irow,icol,*it++) ;
-    static Accessor< float > acc7( "beamlineTiltX" );
-    static Accessor< float > acc8( "beamlineTiltY" );
-    
-    if(!acc7.isAvailable( *this ) || !acc8.isAvailable( *this )){
-      m_perigeeParameters = new Trk::Perigee(acc1(*this),acc2(*this),acc3(*this),acc4(*this),acc5(*this),Trk::PerigeeSurface(Amg::Vector3D(vx(),vy(),vz())),cov);
-       return *m_perigeeParameters;
-    }
-    
-    Amg::Transform3D * amgTransf = new Amg::Transform3D();  
-    Amg::Translation3D amgtranslation(vx(),vy(),vz());
-    *amgTransf = amgtranslation * Amg::RotationMatrix3D::Identity();
-    *amgTransf *= Amg::AngleAxis3D(acc8(*this), Amg::Vector3D(0.,1.,0.));
-    *amgTransf *= Amg::AngleAxis3D(acc7(*this), Amg::Vector3D(1.,0.,0.));
-    m_perigeeParameters = new Trk::Perigee(acc1(*this),acc2(*this),acc3(*this),acc4(*this),acc5(*this),Trk::PerigeeSurface(amgTransf),cov);
-    
-    return *m_perigeeParameters;
-  }
-#endif // not XAOD_STANDALONE and not XAOD_MANACORE
-
   AUXSTORE_PRIMITIVE_GETTER(Track, float, chiSquared)
   AUXSTORE_PRIMITIVE_GETTER(Track, float, numberDoF)
 
@@ -207,18 +168,10 @@ namespace xAOD {
     acc2( *this ) = numberDoF;   
   }
 
-  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER(Track, float, radiusOfFirstHit, setRadiusOfFirstHit)
-  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER(Track, uint64_t, identifierOfFirstHit, setIdentifierOfFirstHit)
-
-  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER(Track, float, beamlineTiltX, setBeamlineTiltX)
-  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER(Track, float, beamlineTiltY, setBeamlineTiltY)
-  
+  static SG::AuxElement::Accessor< Track::StripClusterLinks_t > clusterAcc( "clusterLinks" );
+  AUXSTORE_OBJECT_SETTER_AND_GETTER( Track, Track::StripClusterLinks_t, clusterLinks, setClusterLinks )
   AUXSTORE_PRIMITIVE_SETTER_AND_GETTER(Track, uint32_t, hitPattern, setHitPattern)
 
-  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER(Track, uint8_t,numberOfUsedHitsdEdx ,setNumberOfUsedHitsdEdx )
-
-   AUXSTORE_PRIMITIVE_SETTER_AND_GETTER(Track, uint8_t,numberOfIBLOverflowsdEdx , setNumberOfIBLOverflowsdEdx)
-
   size_t Track::numberOfParameters() const{
     ///@todo - Can we do this in a better way? Not great to force retrieval of one specific parameter - any would do.
     static Accessor< std::vector<float>  > acc( "parameterX" );
@@ -304,7 +257,7 @@ namespace xAOD {
     // copy the correct values into the temp matrix
     xAOD::ParametersCovMatrix_t tmp;
     std::vector<float>::const_iterator it = acc(*this).begin()+offset;
-    Amg::expand(it,it+15,tmp);
+    FMath::expand(it,it+15,tmp);
     return tmp;
   }
 
@@ -342,69 +295,14 @@ namespace xAOD {
     acc( *this ).at(index) = static_cast<uint8_t>(pos);
   }
 
-#if ( ! defined(XAOD_STANDALONE) ) && ( ! defined(XAOD_MANACORE) )
-  const Trk::CurvilinearParameters Track::curvilinearParameters(unsigned int index) const {    
-
-    static Accessor< std::vector<float>  > acc( "trackParameterCovarianceMatrices" );
-    unsigned int offset = index*15;
-    // copy the correct values into the temp matrix
-    ParametersCovMatrix_t* cov = new ParametersCovMatrix_t(); 
-    auto it = acc(*this).begin()+offset;
-    Amg::expand(it,it+15,*cov);
-    // retrieve the parameters to build the curvilinear frame
-    Amg::Vector3D pos(parameterX(index),parameterY(index),parameterZ(index));
-    Amg::Vector3D mom(parameterPX(index),parameterPY(index),parameterPZ(index));
-    Trk::CurvilinearParameters param(pos,mom,charge(),cov);
-
-    return param;
-  }
-#endif // not XAOD_STANDALONE and not XAOD_MANACORE
-
-  AUXSTORE_PRIMITIVE_GETTER_WITH_CAST(Track, uint8_t, xAOD::TrackProperties,trackProperties)
-  AUXSTORE_PRIMITIVE_SETTER_WITH_CAST(Track, uint8_t, xAOD::TrackProperties,trackProperties, setTrackProperties)
-
   AUXSTORE_PRIMITIVE_GETTER_WITH_CAST(Track, uint8_t, xAOD::TrackFitter,trackFitter)
   AUXSTORE_PRIMITIVE_SETTER_WITH_CAST(Track, uint8_t, xAOD::TrackFitter,trackFitter, setTrackFitter)
 
-  std::bitset<xAOD::NumberOfTrackRecoInfo>   Track::patternRecoInfo() const {
-    static Accessor< uint64_t > acc( "patternRecoInfo" );
-    std::bitset<xAOD::NumberOfTrackRecoInfo> tmp(acc(*this));
-    return tmp;
-  }
-
-  void Track::setPatternRecognitionInfo(uint64_t patternReco)  {
-    static Accessor< uint64_t > acc( "patternRecoInfo" );
-    acc( *this ) = patternReco;
-  }
-
-  void Track::setPatternRecognitionInfo(const std::bitset<xAOD::NumberOfTrackRecoInfo>& patternReco)  {
-    static Accessor< uint64_t > acc( "patternRecoInfo" );
-  #if __cplusplus < 201100
-    uint64_t value = 0;
-    unsigned int i = 0;
-    unsigned int size=patternReco.size();
-    for (;i<32;++i)       value   |= ((patternReco[i]) << i);
-    for (i=32;i<size;++i) value   |= ((patternReco[i]) << (i-32));
-    acc( *this ) = value;
-
-  #else
-    acc( *this ) = patternReco.to_ullong();
-  #endif
-  }
-
   AUXSTORE_PRIMITIVE_SETTER_WITH_CAST(Track, uint8_t, xAOD::ParticleHypothesis, particleHypothesis, setParticleHypothesis)
   AUXSTORE_PRIMITIVE_GETTER_WITH_CAST(Track, uint8_t, xAOD::ParticleHypothesis, particleHypothesis)
 
   bool Track::summaryValue(uint8_t& value, const SummaryType &information)  const {
-    xAOD::Track::Accessor< uint8_t >* acc = trackSummaryAccessorV1<uint8_t>( information );
-    if( ( ! acc ) || ( ! acc->isAvailable( *this ) ) ) return false;
-  // Retrieve the value:
-    value = ( *acc )( *this );
-    return true;
-  }
-  
-  bool Track::summaryValue(float& value, const SummaryType &information)  const {
-    xAOD::Track::Accessor< float >* acc = trackSummaryAccessorV1<float>( information );
+    xAOD::Track::Accessor< uint8_t >* acc = trackSummaryAccessor<uint8_t>( information );
     if( ( ! acc ) || ( ! acc->isAvailable( *this ) ) ) return false;
   // Retrieve the value:
     value = ( *acc )( *this );
@@ -412,85 +310,9 @@ namespace xAOD {
   }
   
   void Track::setSummaryValue(uint8_t& value, const SummaryType &information){
-    xAOD::Track::Accessor< uint8_t >* acc = trackSummaryAccessorV1<uint8_t>( information );
-  // Set the value:
-    ( *acc )( *this ) = value;
-  }
-
-  void Track::setSummaryValue(float& value, const SummaryType &information){
-    xAOD::Track::Accessor< float >* acc = trackSummaryAccessorV1<float>( information );
+    xAOD::Track::Accessor< uint8_t >* acc = trackSummaryAccessor<uint8_t>( information );
   // Set the value:
     ( *acc )( *this ) = value;
   }
- 
-
-#if ( ! defined(XAOD_STANDALONE) ) && ( ! defined(XAOD_MANACORE) )
-   /// The function will return an invalid ElementLink in case nothing was set
-   /// for it yet. This is to avoid users having to always check both for
-   /// the decoration being available, and the link being valid.
-   ///
-   /// @returns An element link to the parent Trk::Track of this track particle
-   ///
-   const ElementLink< TrackCollection >& Track::trackLink() const {
-
-      // The accessor:
-      static ConstAccessor< ElementLink< TrackCollection > > acc( "trackLink" );
-
-      // Check if one of them is available:
-      if( acc.isAvailable( *this ) ) {
-         return acc( *this );
-      }
-
-      // If no Trk::Track link was not set (yet), return a dummy object:
-      static const ElementLink< TrackCollection > dummy;
-      return dummy;
-   }
-
-   void Track::
-   setTrackLink( const ElementLink< TrackCollection >& el ) {
-
-      // The accessor:
-      static Accessor< ElementLink< TrackCollection > > acc( "trackLink" );
-
-      // Do the deed:
-      acc( *this ) = el;
-      return;
-   }
-
-   const Trk::Track* Track::track() const{
-
-      // The accessor:
-      static ConstAccessor< ElementLink< TrackCollection > > acc( "trackLink" );
-
-      if( ! acc.isAvailable( *this ) ) {
-         return 0;
-      }
-      if( ! acc( *this ).isValid() ) {
-         return 0;
-      }
-
-      return *( acc( *this ) );
-   }
-   
-#endif // not XAOD_STANDALONE and not XAOD_MANACORE
-
-   AUXSTORE_OBJECT_SETTER_AND_GETTER( Track,
-                                      ElementLink< VertexContainer >,
-                                      vertexLink, setVertexLink )
-
-   const Vertex* Track::vertex() const {
-
-      // The accessor:
-      static SG::AuxElement::Accessor< ElementLink< VertexContainer > >
-         acc( "vertexLink" );
-
-      if( ! acc.isAvailable( *this ) ) {
-         return 0;
-      }
-      if( ! acc( *this ).isValid() ) {
-         return 0;
-      }
-      return *( acc( *this ) );
-   }
 
 } // namespace xAOD
\ No newline at end of file
diff --git a/xAOD/xAODTracking/Root/TrackAuxContainer.cxx b/xAOD/xAODTracking/Root/TrackAuxContainer.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..93fcb47f62e1f6f116300141a3951fc85dfbcfcc
--- /dev/null
+++ b/xAOD/xAODTracking/Root/TrackAuxContainer.cxx
@@ -0,0 +1,73 @@
+// Local include(s):
+#include "xAODTracking/TrackAuxContainer.h"
+
+namespace xAOD {
+
+   TrackAuxContainer::TrackAuxContainer()
+      : AuxContainerBase() {
+
+      AUX_VARIABLE( x0 );
+      AUX_VARIABLE( y0 );
+      AUX_VARIABLE( phi0 );
+      AUX_VARIABLE( theta );
+      AUX_VARIABLE( qOverP );
+
+      AUX_VARIABLE( definingParametersCovMatrix );
+
+      AUX_VARIABLE( vx );
+      AUX_VARIABLE( vy );
+      AUX_VARIABLE( vz );
+      
+      AUX_VARIABLE( clusterLinks);
+      AUX_VARIABLE( hitPattern );
+     
+      AUX_VARIABLE( chiSquared          );
+      AUX_VARIABLE( numberDoF );
+
+      AUX_VARIABLE( trackFitter          );
+      AUX_VARIABLE( particleHypothesis );
+
+      // TrackSummary information
+#ifndef XAODTRACK_SUMMARYDYNAMIC
+      // uint8_ts
+      AUX_VARIABLE( numberOfContribStripLayers        );
+      AUX_VARIABLE( numberOfStripHits                   );
+      AUX_VARIABLE( numberOfStripOutliers               );
+      AUX_VARIABLE( numberOfStripHoles                  );
+      AUX_VARIABLE( numberOfStripDoubleHoles            );
+      AUX_VARIABLE( numberOfStripSharedHits             );
+      AUX_VARIABLE( numberOfStripDeadSensors            );
+      AUX_VARIABLE( numberOfStripSpoiltHits             );
+
+      AUX_VARIABLE( numberOfOutliersOnTrack           );
+      AUX_VARIABLE( standardDeviationOfChi2OS         );
+#endif
+
+   }
+
+   void TrackAuxContainer::dump() const {
+     std::cout<<" Dumping TrackAuxContainer"<<std::endl;
+     std::cout<<"x0:";
+     std::copy(x0.begin(), x0.end(),
+       std::ostream_iterator<float>(std::cout, ", "));
+     std::cout<<"y0:";
+     std::copy(y0.begin(), y0.end(),
+       std::ostream_iterator<float>(std::cout, ", "));
+     std::cout<<"phi0:";
+     std::copy(phi0.begin(), phi0.end(),
+       std::ostream_iterator<float>(std::cout, ", "));
+     std::cout<<"theta:";
+     std::copy(theta.begin(), theta.end(),
+       std::ostream_iterator<float>(std::cout, ", "));
+     std::cout<<"qOverP:";
+     std::copy(qOverP.begin(), qOverP.end(),
+       std::ostream_iterator<float>(std::cout, ", "));
+     std::cout<<"definingParametersCovMatrix: ["<<&definingParametersCovMatrix<<"]";
+     for (unsigned int i=0; i<definingParametersCovMatrix.size();++i){
+     std::copy(definingParametersCovMatrix[i].begin(), definingParametersCovMatrix[i].end(),
+       std::ostream_iterator<float>(std::cout, ", "));
+        std::cout<<std::endl;
+     }
+   }
+
+} // namespace xAOD
diff --git a/xAOD/xAODTracking/Root/TrackSummaryAccessors.cxx b/xAOD/xAODTracking/Root/TrackSummaryAccessors.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..d94ee097d53e9416c229634863b16bf80bff4848
--- /dev/null
+++ b/xAOD/xAODTracking/Root/TrackSummaryAccessors.cxx
@@ -0,0 +1,49 @@
+// System include(s):
+extern "C" {
+#   include <stdint.h>
+}
+#include <iostream>
+
+// Local include(s):
+#include "xAODTracking/TrackSummaryAccessors.h"
+
+/// Helper macro for Accessor objects
+#define DEFINE_ACCESSOR(TYPE, NAME )                               \
+   case xAOD::NAME:                                                \
+   {                                                               \
+      static SG::AuxElement::Accessor< TYPE > a( #NAME );          \
+      return &a;                                                   \
+   }                                                               \
+   break;
+
+namespace xAOD {
+
+  // Generic case. Maybe return warning?
+  template<class T>
+   SG::AuxElement::Accessor< T >*
+   trackSummaryAccessor( xAOD::SummaryType /*type*/ )
+   {}
+
+  template<>
+   SG::AuxElement::Accessor< uint8_t >*
+   trackSummaryAccessor<uint8_t>( xAOD::SummaryType type ) {
+
+      switch( type ) {
+        DEFINE_ACCESSOR( uint8_t, numberOfContribStripLayers        );
+        DEFINE_ACCESSOR( uint8_t, numberOfStripHits                   );
+        DEFINE_ACCESSOR( uint8_t, numberOfStripOutliers               );
+        DEFINE_ACCESSOR( uint8_t, numberOfStripHoles                  );
+        DEFINE_ACCESSOR( uint8_t, numberOfStripDoubleHoles            );
+        DEFINE_ACCESSOR( uint8_t, numberOfStripSharedHits             );
+        DEFINE_ACCESSOR( uint8_t, numberOfStripDeadSensors            );
+        DEFINE_ACCESSOR( uint8_t, numberOfStripSpoiltHits             );
+     
+        DEFINE_ACCESSOR( uint8_t, numberOfOutliersOnTrack           );
+        DEFINE_ACCESSOR( uint8_t, standardDeviationOfChi2OS         );
+      default:                  
+         std::cerr << "xAOD::Track ERROR Unknown SummaryType ("
+                   << type << ") requested" << std::endl;
+         return 0;
+      }
+   } 
+} // namespace xAOD
diff --git a/xAOD/xAODTracking/share/xAODTracking_Track_test.ref b/xAOD/xAODTracking/share/xAODTracking_Track_test.ref
new file mode 100644
index 0000000000000000000000000000000000000000..8f4fb0652d50f4df057dd14a6d9011da9b0eb8e1
--- /dev/null
+++ b/xAOD/xAODTracking/share/xAODTracking_Track_test.ref
@@ -0,0 +1,25 @@
+Filling Track
+setDefiningParameters
+setDefiningParametersCovMatrixVec
+setParametersOrigin
+setTrackParameters
+setParameterPosition
+Printing Track
+x0 = 1, y0 = 2, phi = 1.23, theta = 0.5, qOverP = 0.25
+definingParametersCovMatrixVec = [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3]
+vx = 0, vy = 1, vz = 2
+numberOfParameters = 2
+  - x = 0, y = 1, z = 2, px = 3, py = 4, pz = 5
+  - x = 6, y = 7, z = 8, px = 9, py = 10, pz = 11
+parameterPosition( 0 ) = 1
+parameterPosition( 1 ) = 3
+ Dumping TrackAuxContainer
+x0:1, y0:2, phi0:1.23, theta:0.5, qOverP:0.25, definingParametersCovMatrix: [0x7ffd160b5370]1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+x0 = 1, y0 = 2, phi = 1.23, theta = 0.5, qOverP = 0.25
+definingParametersCovMatrixVec = [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3]
+vx = 0, vy = 1, vz = 2
+numberOfParameters = 2
+  - x = 0, y = 1, z = 2, px = 3, py = 4, pz = 5
+  - x = 6, y = 7, z = 8, px = 9, py = 10, pz = 11
+parameterPosition( 0 ) = 1
+parameterPosition( 1 ) = 3
\ No newline at end of file
diff --git a/xAOD/xAODTracking/test/xAODTracking_Track_test.cxx b/xAOD/xAODTracking/test/xAODTracking_Track_test.cxx
index 9395da84ef19fa958b7ae896d557545021cd6934..97dc59998d2eaff9bf0e944db3efe00fdd8425da 100644
--- a/xAOD/xAODTracking/test/xAODTracking_Track_test.cxx
+++ b/xAOD/xAODTracking/test/xAODTracking_Track_test.cxx
@@ -21,10 +21,10 @@ std::ostream& operator<< ( std::ostream& out,
 }
 
 /// Function filling one Track with information
-void fill( xAOD::Track& tp ) {
-
+void fill( xAOD::Track& tp) {
+   
    tp.setDefiningParameters( 1.0, 2.0, 1.23, 0.5, 0.25 );
-
+   std::cout << "setDefiningParameters" << std::endl;
    static const float covMatrix[ 15 ] = {
       1.0, 1.0, 1.0, 1.0, 1.0,
       2.0, 2.0, 2.0, 2.0, 2.0,
@@ -33,9 +33,9 @@ void fill( xAOD::Track& tp ) {
    static const std::vector< float >
       covMatrixVec( covMatrix, covMatrix + 15 );
    tp.setDefiningParametersCovMatrixVec( covMatrixVec );
-
+   std::cout << "setDefiningParametersCovMatrixVec" << std::endl;
    tp.setParametersOrigin( 0.0, 1.0, 2.0 );
-
+   std::cout << "setParametersOrigin" << std::endl;
    static const float parameters[ 2 ][ 6 ] = {
       { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 },
       { 6.0, 7.0, 8.0, 9.0, 10.0, 11.0 }
@@ -49,9 +49,11 @@ void fill( xAOD::Track& tp ) {
       }
    }
    tp.setTrackParameters( parametersVec );
+   std::cout << "setTrackParameters" << std::endl;
 
    tp.setParameterPosition( 0, xAOD::FirstMeasurement );
    tp.setParameterPosition( 1, xAOD::CalorimeterEntrance );
+   std::cout << "setParameterPosition" << std::endl;
 
    return;
 }
@@ -60,7 +62,7 @@ void fill( xAOD::Track& tp ) {
 void print( const xAOD::Track& tp ) {
 
    std::cout << "x0 = " << tp.x0() << ", y0 = " << tp.y0()
-             << ", phi = " << tp.phi() << ", theta = " << tp.theta()
+             << ", phi = " << tp.phi0() << ", theta = " << tp.theta()
              << ", qOverP = " << tp.qOverP() << std::endl;
    std::cout << "definingParametersCovMatrixVec = "
              << tp.definingParametersCovMatrixVec() << std::endl;
@@ -89,14 +91,14 @@ int main() {
    xAOD::TrackAuxContainer aux;
    xAOD::TrackContainer tpc;
    tpc.setStore( &aux );
-
+   
    // Add one track particle to the container:
    xAOD::Track* p = new xAOD::Track();
    tpc.push_back( p );
-
+   std::cout << "Filling Track" << std::endl;
    // Fill it with information:
    fill( *p );
-
+   std::cout << "Printing Track" << std::endl;
    // Print the information:
    print( *p );
 
diff --git a/xAOD/xAODTracking/xAODTracking/Track.h b/xAOD/xAODTracking/xAODTracking/Track.h
index 123257ebc0c2bddc084e680899b88ff3781ef665..f06867b07e5af2fb094bf06612bdc4a3f54e26e9 100644
--- a/xAOD/xAODTracking/xAODTracking/Track.h
+++ b/xAOD/xAODTracking/xAODTracking/Track.h
@@ -13,6 +13,7 @@ extern "C" {
 
 // xAOD include(s):
 #include "xAODBase/IParticle.h"
+#include "xAODTracking/StripClusterContainer.h" 
 #include "xAODTracking/TrackingPrimitives.h" 
 
 namespace xAOD {
@@ -54,7 +55,14 @@ namespace xAOD {
             /// The type of the object as a simple enumeration
             virtual Type::ObjectType type() const;
         /// @}
-    
+        
+        /// @name ElementLinks to StripClusters
+        /// @{
+            typedef std::vector< ElementLink< xAOD::StripClusterContainer > > StripClusterLinks_t;
+            const StripClusterLinks_t& clusterLinks() const;
+            void setClusterLinks(const StripClusterLinks_t& clusterLinks);
+        /// @}
+        
         /// @name Defining parameters functions
         /// The 'defining parameters' are key to the concept of a Track, and give the values for the IParticle interface
         /// ( pt(), phi(), eta() etc.).
@@ -70,8 +78,8 @@ namespace xAOD {
             float x0() const;
             /// Returns the \f$y_0\f$ parameter
             float y0() const;
-            /// Returns the \f$\phi\f$ parameter, which has range \f$-\pi\f$ to \f$+\pi\f$.
-            float phi() const;
+            /// Returns the \f$phi_0\f$ parameter
+            float phi0() const;
             /// Returns the \f$\theta\f$  parameter, which has range 0 to \f$\pi\f$.
             float theta() const;
             /// Returns the \f$q/p\f$  parameter
@@ -85,7 +93,7 @@ namespace xAOD {
             /// Returns the length 6 vector containing the elements of defining parameters covariance matrix.
             const std::vector<float>& definingParametersCovMatrixVec() const;   
             /// Set the defining parameters.     
-            void setDefiningParameters(float x0, float y0, float phi, float theta, float qOverP);
+            void setDefiningParameters(float x0, float y0, float phi0, float theta, float qOverP);
             /// Set the defining parameters covariance matrix.
             void setDefiningParametersCovMatrix(const ParametersCovMatrix_t& cov);
             /// Set the defining parameters covariance matrix using a length 15 vector.
@@ -177,7 +185,7 @@ namespace xAOD {
             /// Method for setting the particle type, using the ParticleHypothesis enum.
             void setParticleHypothesis(const ParticleHypothesis hypo);
         /// Returns the particle hypothesis used for Track fitting.
-            ParticleHypothesis particleHypothesis() const
+            ParticleHypothesis particleHypothesis() const;
             /// Returns the fitter.
             TrackFitter trackFitter() const;
         /// @}
diff --git a/xAOD/xAODTracking/xAODTracking/TrackAuxContainer.h b/xAOD/xAODTracking/xAODTracking/TrackAuxContainer.h
index 97f7ffc9785d1ab532602d841dbefbc0bb164b21..867d274768d8f08f14e291bcbca395ae1af3f89a 100644
--- a/xAOD/xAODTracking/xAODTracking/TrackAuxContainer.h
+++ b/xAOD/xAODTracking/xAODTracking/TrackAuxContainer.h
@@ -12,7 +12,7 @@ extern "C" {
 #include "AthLinks/ElementLink.h"
 
 // Local include(s):
-#include "xAODTracking/TrackAuxContainer.h"
+#include "xAODTracking/Track.h"
  
 namespace xAOD {
     class TrackAuxContainer : public AuxContainerBase {
@@ -29,7 +29,7 @@ namespace xAOD {
     /// @{
     std::vector< float >                x0;
     std::vector< float >                y0;
-    std::vector< float >                phi;
+    std::vector< float >                phi0;
     std::vector< float >                theta;
     std::vector< float >                qOverP;
     
@@ -54,6 +54,7 @@ namespace xAOD {
         std::vector< std::vector<float> >   trackParameterCovarianceMatrices;
         std::vector< std::vector<uint8_t> > parameterPosition;
     
+    std::vector< xAOD::Track::StripClusterLinks_t > clusterLinks;
     std::vector< uint32_t > hitPattern;
     
     /// @name Fit quality functions
diff --git a/xAOD/xAODTracking/xAODTracking/TrackSummaryAccessors.h b/xAOD/xAODTracking/xAODTracking/TrackSummaryAccessors.h
new file mode 100644
index 0000000000000000000000000000000000000000..7e15800eace01216d6352b1aa90d7286950efe55
--- /dev/null
+++ b/xAOD/xAODTracking/xAODTracking/TrackSummaryAccessors.h
@@ -0,0 +1,30 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: TrackSummaryAccessors_v1.h 574227 2013-12-06 14:20:39Z emoyse $
+#ifndef XAOD_TRACKSUMMARYACCESSORS_H
+#define XAOD_TRACKSUMMARYACCESSORS_H
+
+// EDM include(s):
+#include "AthContainers/AuxElement.h"
+
+// Local include(s):
+#include "xAODTracking/TrackingPrimitives.h"
+
+namespace xAOD {
+
+   /// Helper function for managing TrackSummary Accessor objects
+   ///
+   /// This function holds on to Accessor objects that can be used by each
+   /// TrackParticle_v1 object at runtime to get/set summary values on themselves.
+   ///
+   template <class T>
+   SG::AuxElement::Accessor< T >*
+   trackSummaryAccessor( xAOD::SummaryType type );
+
+} // namespace xAOD
+
+#endif // XAODCALOEVENT_CALOCLUSTERACCESSORS_H
diff --git a/xAOD/xAODTracking/xAODTracking/TrackingPrimitives.h b/xAOD/xAODTracking/xAODTracking/TrackingPrimitives.h
index d75bce1058668d57fc7e242e654827efdf4aaed5..da9d408d7e0545bbff1627042d4b239d0b70194c 100644
--- a/xAOD/xAODTracking/xAODTracking/TrackingPrimitives.h
+++ b/xAOD/xAODTracking/xAODTracking/TrackingPrimitives.h
@@ -5,10 +5,41 @@
 #include <Eigen/Core>
 #include <Eigen/Dense>
 
+namespace  FMath{
+  template <int N>
+  inline void compress(const Eigen::Matrix<double, N,N,0,N,N>& covMatrix, std::vector<float>& vec) {
+      int rows = covMatrix.rows();
+      for (int i = 0; i < rows; ++i) {
+          for (int j = 0; j <= i; ++j) {
+              vec.push_back(covMatrix(i, j));
+          }
+      }
+  }
+  
+  template <int N>
+  inline void expand(std::vector<float>::const_iterator it,
+          std::vector<float>::const_iterator it_end, Eigen::Matrix<double,  N,N,0,N,N>& covMatrix) {
+      unsigned int dist = std::distance(it, it_end);
+      unsigned int n;
+      for (n = 1; dist > n; ++n) {
+          dist = dist - n;
+      }
+      covMatrix = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>(n, n);
+      for (unsigned int i = 0; i < n; ++i) {
+          for (unsigned int j = 0; j <= i; ++j) {
+              covMatrix(i,j) = *it;
+              ++it;
+          }
+      }
+  }
+}
+
 namespace xAOD {
     
-  using DefiningParameters_t  Eigen::Matrix<double, 5, 1>;
-  using ParametersCovMatrix_t Eigen::Matrix<double, 5, 5>;
+  using DefiningParameters_t  = Eigen::Matrix<double, 5, 1>;
+  using ParametersCovMatrix_t = Eigen::Matrix<double, 5, 5>;
+  using CurvilinearParameters_t = Eigen::Matrix<double, 6, 1>;
+  
     /// Enums to identify who created this track and which properties does it have.
   enum TrackFitter
   {
@@ -51,7 +82,7 @@ namespace xAOD {
   /// When adding a new transient information type, please make sure to increase numberOfTrackSummaryTypes.*/
   enum SummaryType {
     // --- Inner Detector
-    numberOfContribSCTLayers          = 1,  //!< number of contributing layers of the pixel detector [unit8_t].
+    numberOfContribStripLayers          = 1,  //!< number of contributing layers of the pixel detector [unit8_t].
     numberOfStripHits                 = 2,  //!< number of hits in Strip [unit8_t].
     numberOfStripOutliers             = 3,  //!< number of Strip outliers [unit8_t].
     numberOfStripHoles                = 4,  //!< number of Strip holes [unit8_t].
diff --git a/xAOD/xAODTracking/xAODTracking/xAODTrackingDict.h b/xAOD/xAODTracking/xAODTracking/xAODTrackingDict.h
index cb4bb673e608ac61b110e1a4c66dbbc5f5e3d7bf..f4cfd8d135a18e0b47d2b78fa8a989b47f80688b 100644
--- a/xAOD/xAODTracking/xAODTracking/xAODTrackingDict.h
+++ b/xAOD/xAODTracking/xAODTracking/xAODTrackingDict.h
@@ -17,11 +17,10 @@
  
 // EDM include(s):
 #include "AthLinks/DataLink.h"
-#include "AthLinks/ElementLink.h"
+#include "AthLinks/ElementLinkVector.h"
  
 // Local include(s):
 #include "xAODTracking/TrackContainer.h"
-#include "xAODTracking/TrackContainer.h"
 #include "xAODTracking/TrackAuxContainer.h"
 
 #include "xAODTracking/StripClusterContainer.h"
diff --git a/xAOD/xAODTruth/CMakeLists.txt b/xAOD/xAODTruth/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4d63992e69e11bb11f78d216565560daf12c584a
--- /dev/null
+++ b/xAOD/xAODTruth/CMakeLists.txt
@@ -0,0 +1,37 @@
+# $Id: CMakeLists.txt 761796 2016-07-14 08:06:02Z krasznaa $
+################################################################################
+# Package: xAODTruth
+################################################################################
+
+# Declare the package name:
+atlas_subdir( xAODTruth )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs(
+   PUBLIC
+   Control/AthContainers
+   Control/AthLinks
+   Event/xAOD/xAODBase
+   Event/xAOD/xAODCore
+   PRIVATE
+   Generators/TruthUtils )
+
+# Component(s) in the package:
+atlas_add_library( xAODTruth
+   xAODTruth/*.h xAODTruth/versions/*.h Root/*.h Root/*.cxx
+   PUBLIC_HEADERS xAODTruth
+   LINK_LIBRARIES AthContainers AthLinks xAODBase xAODCore
+   PRIVATE_LINK_LIBRARIES TruthUtils )
+
+atlas_add_dictionary( xAODTruthDict
+   xAODTruth/xAODTruthDict.h
+   xAODTruth/selection.xml
+   LINK_LIBRARIES xAODTruth
+   EXTRA_FILES Root/dict/*.cxx )
+
+atlas_generate_cliddb( xAODTruth )
+
+# Test(s) in the package:
+atlas_add_test( ut_xaodtruth_particle_test
+   SOURCES test/ut_xaodtruth_particle_test.cxx
+   LINK_LIBRARIES xAODTruth )
diff --git a/xAOD/xAODTruth/Root/TruthAccessors.cxx b/xAOD/xAODTruth/Root/TruthAccessors.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..0e8785e95a82cee519859354cc77bde790d61130
--- /dev/null
+++ b/xAOD/xAODTruth/Root/TruthAccessors.cxx
@@ -0,0 +1,74 @@
+// System include(s):
+#include <iostream>
+
+// Local include(s):
+#include "TruthAccessors.h"
+
+/// Helper macro for managing cluster moment Accessor objects
+#define DEFINE_ACCESSOR( PARENT, TYPE, NAME )                \
+   case PARENT::NAME:                                        \
+      {                                                      \
+         static SG::AuxElement::Accessor< TYPE > a( #NAME ); \
+         return &a;                                          \
+      }                                                      \
+      break
+
+namespace xAOD {
+
+   SG::AuxElement::Accessor< float >*
+   polarizationAccessor( TruthParticle::PolParam type ) {
+
+      switch( type ) {
+
+         DEFINE_ACCESSOR( TruthParticle, float, polarizationTheta );
+         DEFINE_ACCESSOR( TruthParticle, float, polarizationPhi );
+
+      default:
+         std::cerr << "xAOD::polarizationAccessor ERROR Unknown PolParam ("
+                   << type << ") requested" << std::endl;
+         return 0;
+      }
+
+      return 0;
+   }
+
+   SG::AuxElement::Accessor< int >*
+   pdfInfoAccessorInt( TruthEvent::PdfParam type ) {
+
+      switch( type ) {
+
+         DEFINE_ACCESSOR( TruthEvent, int, PDGID1 );
+         DEFINE_ACCESSOR( TruthEvent, int, PDGID2 );
+         DEFINE_ACCESSOR( TruthEvent, int, PDFID1 );
+         DEFINE_ACCESSOR( TruthEvent, int, PDFID2 );
+
+      default:
+         std::cerr << "xAOD::pdfInfoAccessorInt ERROR Unknown PdfParam ("
+                   << type << ") requested" << std::endl;
+         return 0;
+      }
+
+      return 0;
+   }
+
+   SG::AuxElement::Accessor< float >*
+   pdfInfoAccessorFloat( TruthEvent::PdfParam type ) {
+
+      switch( type ) {
+
+         DEFINE_ACCESSOR( TruthEvent, float, X1 );
+         DEFINE_ACCESSOR( TruthEvent, float, X2 );
+         DEFINE_ACCESSOR( TruthEvent, float, Q );
+         DEFINE_ACCESSOR( TruthEvent, float, XF1 );
+         DEFINE_ACCESSOR( TruthEvent, float, XF2 );
+
+      default:
+         std::cerr << "xAOD::pdfInfoAccessorFloat ERROR Unknown ParamDef ("
+                   << type << ") requested" << std::endl;
+         return 0;
+      }
+
+      return 0;
+   }
+
+} // namespace xAOD
diff --git a/xAOD/xAODTruth/Root/TruthAccessors.h b/xAOD/xAODTruth/Root/TruthAccessors.h
new file mode 100644
index 0000000000000000000000000000000000000000..704ad790ae8d6a1d13ba3d420707678c794b463c
--- /dev/null
+++ b/xAOD/xAODTruth/Root/TruthAccessors.h
@@ -0,0 +1,36 @@
+// -*- C++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: TruthAccessors_v1.h 623284 2014-10-22 14:07:48Z krasznaa $
+#ifndef XAODTRUTH_TRUTHACCESSORS_H
+#define XAODTRUTH_TRUTHACCESSORS_H
+
+// EDM include(s):
+#include "AthContainers/AuxElement.h"
+
+// Local include(s):
+#include "xAODTruth/TruthEvent.h"
+#include "xAODTruth/TruthParticle.h"
+
+namespace xAOD {
+
+   /// This function holds on to Accessor objects that can be used by each
+   /// TruthParticle object at runtime to get/set parameter values on
+   /// themselves.
+   SG::AuxElement::Accessor< float >*
+   polarizationAccessor( TruthParticle::PolParam type );
+
+   /// Helper function for getting accessors for integer type PDF information
+   SG::AuxElement::Accessor< int >*
+   pdfInfoAccessorInt( TruthEvent::PdfParam type );
+
+   /// Helper function for getting accessors for floating point PDF information
+   SG::AuxElement::Accessor< float >*
+   pdfInfoAccessorFloat( TruthEvent::PdfParam type );
+
+} // namespace xAOD
+
+#endif // XAODTRUTH_TRUTHACCESSORS_H
diff --git a/xAOD/xAODTruth/Root/TruthEvent.cxx b/xAOD/xAODTruth/Root/TruthEvent.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..aa83accfca23d73aca89821b3b3503438b5d2ba8
--- /dev/null
+++ b/xAOD/xAODTruth/Root/TruthEvent.cxx
@@ -0,0 +1,341 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: TruthEvent.cxx 761798 2016-07-14 08:15:01Z krasznaa $
+
+// System include(s):
+#include <cmath>
+
+// EDM include(s):
+#include "xAODCore/AuxStoreAccessorMacros.h"
+
+// Local include(s):
+#include "xAODTruth/TruthEvent.h"
+#include "TruthAccessors.h"
+
+namespace xAOD {
+
+
+   TruthEvent::TruthEvent()
+      : SG::AuxElement() {
+
+   }
+   
+   /////////////////////////////////////////////////////////////////////////////
+   // Implementation of the truth particle accessor functions
+
+   AUXSTORE_OBJECT_SETTER_AND_GETTER( TruthEvent,
+                                      TruthEvent::TruthParticleLinks_t,
+                                      truthParticleLinks,
+                                      setTruthParticleLinks )
+
+   /// Accessor for the truth particles
+   static SG::AuxElement::Accessor< TruthEvent::TruthParticleLinks_t >
+      truthParticleLinksAcc( "truthParticleLinks" );
+
+   size_t TruthEvent::nTruthParticles() const {
+
+      // If the variable is not available, we don't have any truth particles
+      // associated...
+      if( ! truthParticleLinksAcc.isAvailable( *this ) ) {
+         return 0;
+      }
+
+      // Return the size of the vector:
+      return truthParticleLinksAcc( *this ).size();
+   }
+
+   const TruthEvent::TruthParticleLink_t&
+   TruthEvent::truthParticleLink( size_t index ) const {
+
+      return truthParticleLinksAcc( *this ).at( index );
+   }
+
+   const TruthParticle* TruthEvent::truthParticle( size_t index ) const {
+
+      // Check if the variable is available:
+      if( ! truthParticleLinksAcc.isAvailable( *this ) ) {
+         return 0;
+      }
+
+      // Check if the link is valid:
+      const TruthParticleLinks_t& links = truthParticleLinksAcc( *this );
+      if( ! links[ index ].isValid() ) {
+         return 0;
+      }
+
+      // Return the de-referenced link:
+      return *( links[ index ] );
+   }
+
+   void
+   TruthEvent::addTruthParticleLink( const TruthParticleLink_t& link ) {
+
+      truthParticleLinksAcc( *this ).push_back( link );
+      return;
+   }
+
+   void TruthEvent::clearTruthParticleLinks() {
+
+      truthParticleLinksAcc( *this ).clear();
+      return;
+   }
+
+   /////////////////////////////////////////////////////////////////////////////
+
+   /////////////////////////////////////////////////////////////////////////////
+   // Implementation of the truth vertex accessor functions
+
+   AUXSTORE_OBJECT_SETTER_AND_GETTER( TruthEvent,
+                                      TruthEvent::TruthVertexLinks_t,
+                                      truthVertexLinks,
+                                      setTruthVertexLinks )
+
+   /// Accessor for the truth vertices
+   static SG::AuxElement::Accessor< TruthEvent::TruthVertexLinks_t >
+      truthVertexLinksAcc( "truthVertexLinks" );
+
+   size_t TruthEvent::nTruthVertices() const {
+
+      // If the variable is not available, we don't have any truth particles
+      // associated...
+      if( ! truthVertexLinksAcc.isAvailable( *this ) ) {
+         return 0;
+      }
+
+      // Return the size of the vector:
+      return truthVertexLinksAcc( *this ).size();
+   }
+
+   const TruthEvent::TruthVertexLink_t&
+   TruthEvent::truthVertexLink( size_t index ) const {
+
+      return truthVertexLinksAcc( *this ).at(index);
+   }
+
+   const TruthVertex* TruthEvent::truthVertex( size_t index ) const {
+
+      // Check if the variable is available:
+      if( ! truthVertexLinksAcc.isAvailable( *this ) ) {
+         return 0;
+      }
+
+      // Check if the link is valid:
+      const TruthVertexLinks_t& links = truthVertexLinksAcc( *this );
+      if( ! links[ index ].isValid() ) {
+         return 0;
+      }
+
+      // Return the de-referenced link:
+      return *( links[ index ] );
+   }
+
+   void TruthEvent::addTruthVertexLink( const TruthVertexLink_t& link ) {
+
+      truthVertexLinksAcc( *this ).push_back( link );
+      return;
+   }
+
+   void TruthEvent::clearTruthVertexLinks() {
+
+      truthVertexLinksAcc( *this ).clear();
+      return;
+   }
+
+   
+   /////////////////////////////////////////////////////////////////////////////
+   // Simple, always-present event properties
+
+   /// @todo Need upgrade to allow string-valued map-like access... or access a
+   /// corresponding vector of names
+   AUXSTORE_OBJECT_SETTER_AND_GETTER( TruthEvent, std::vector< float >,
+                                      weights, setWeights )
+
+   AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( TruthEvent, float, crossSection,
+                                         setCrossSection )
+   AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( TruthEvent, float,
+                                         crossSectionError,
+                                         setCrossSectionError )
+
+   void TruthEvent::setCrossSection( float value, float error ) {
+
+      setCrossSection( value );
+      setCrossSectionError( error );
+      return;
+   }
+
+   /////////////////////////////////////////////////////////////////////////////
+
+   /////////////////////////////////////////////////////////////////////////////
+   // Optional PDF info accessors
+
+   bool TruthEvent::pdfInfoParameter( int& value,
+                                         PdfParam information ) const {
+
+      // Look for the accessor object:
+      auto* acc = pdfInfoAccessorInt( information );
+      if( ! acc ) return false;
+
+      // Get the value:
+      value = ( *acc )( *this );
+      return true;
+   }
+
+   bool TruthEvent::pdfInfoParameter( float& value,
+                                         PdfParam information ) const {
+
+      // Look for the accessor object:
+      auto* acc = pdfInfoAccessorFloat( information );
+      if( ! acc ) return false;
+
+      // Get the value:
+      value = ( *acc )( *this );
+      return true;
+   }
+
+   bool TruthEvent::setPdfInfoParameter( int value,
+                                            PdfParam information ) {
+
+      // Look for the accessor object:
+      auto* acc = pdfInfoAccessorInt( information );
+      if( ! acc ) return false;
+
+      // Set the value:
+      ( *acc )( *this ) = value;
+      return true;
+   }
+
+   bool TruthEvent::setPdfInfoParameter( float value,
+                                            PdfParam information ) {
+
+      // Look for the accessor object:
+      auto* acc = pdfInfoAccessorFloat( information );
+      if( ! acc ) return false;
+
+      // Set the value:
+      ( *acc )( *this ) = value;
+      return true;
+   }
+
+   TruthEvent::PdfInfo::PdfInfo()
+      : pdgId1( 0 ), pdgId2( 0 ), pdfId1( -1 ), pdfId2( -1 ),
+        x1( NAN ), x2( NAN ), Q( NAN ), xf1( NAN ), xf2( NAN ) {
+
+   }
+
+   bool TruthEvent::PdfInfo::valid() const {
+
+      return ( ( pdgId1 != 0 ) && ( pdgId2 != 0 ) &&
+               ( pdfId1 >= 0 ) && ( pdfId2 >= 0 ) &&
+               ( ! std::isnan( x1 ) ) && ( ! std::isnan( x2 ) ) &&
+               ( ! std::isnan( Q ) ) &&
+               ( ! std::isnan( xf1 ) ) && ( ! std::isnan( xf2 ) ) );
+   }
+
+   TruthEvent::PdfInfo TruthEvent::pdfInfo() const {
+
+      // The result object:
+      PdfInfo rtn;
+
+      // Retrieve all of its elements:
+      pdfInfoParameter( rtn.pdgId1, PDGID1 );
+      pdfInfoParameter( rtn.pdgId2, PDGID2 );
+      pdfInfoParameter( rtn.pdfId1, PDFID1 );
+      pdfInfoParameter( rtn.pdfId2, PDFID2 );
+      pdfInfoParameter( rtn.x1,     X1 );
+      pdfInfoParameter( rtn.x2,     X2 );
+      pdfInfoParameter( rtn.Q,      Q );
+      pdfInfoParameter( rtn.xf1,    XF1 );
+      pdfInfoParameter( rtn.xf2,    XF2 );
+
+      return rtn;
+   }
+
+   /////////////////////////////////////////////////////////////////////////////
+
+   /////////////////////////////////////////////////////////////////////////////
+   // Implementation for the links to truth particles/vertices
+
+   // Accessor for the signal vertex
+   static SG::AuxElement::Accessor< TruthEvent::TruthVertexLink_t >
+      signalProcessVertexLinkAcc( "signalProcessVertexLink" );
+
+   const TruthVertex* TruthEvent::signalProcessVertex() const {
+
+      // Check if the link variable is available:
+      if( ! signalProcessVertexLinkAcc.isAvailable( *this ) ) {
+         return 0;
+      }
+
+      // Get the link:
+      const TruthVertexLink_t& vertLink = signalProcessVertexLinkAcc( *this );
+
+      // Check if it's valid:
+      if( ! vertLink.isValid() ) {
+         return 0;
+      }
+
+      // Return the de-referenced link:
+      return *vertLink;
+   }
+
+   AUXSTORE_OBJECT_SETTER_AND_GETTER( TruthEvent,
+                                      TruthEvent::TruthVertexLink_t,
+                                      signalProcessVertexLink,
+                                      setSignalProcessVertexLink )
+
+   // Accessors for the beam particles
+   static SG::AuxElement::Accessor< TruthEvent::TruthParticleLink_t >
+      primaryParticleLinkLinkAcc( "primaryParticleLink" );
+
+   AUXSTORE_OBJECT_SETTER_AND_GETTER( TruthEvent,
+                                      TruthEvent::TruthParticleLink_t,
+                                      primaryParticleLink,
+                                      setPrimaryParticleLink )
+
+   /////////////////////////////////////////////////////////////////////////////
+
+   Type::ObjectType TruthEvent::type() const {
+
+      return Type::TruthEvent;
+   }
+   
+   AUXSTORE_OBJECT_SETTER_AND_GETTER(TruthEvent, std::vector < std::string >, weightNames, setWeightNames )
+   AUXSTORE_PRIMITIVE_SETTER_AND_GETTER(TruthEvent, uint32_t, mcChannelNumber, setMcChannelNumber )
+
+   void TruthEvent::toPersistent() {
+
+      if( primaryParticleLinkLinkAcc.isAvailableWritable( *this ) ) {
+         primaryParticleLinkLinkAcc( *this ).toPersistent();
+      }
+
+      if( signalProcessVertexLinkAcc.isAvailableWritable( *this ) ) {
+         signalProcessVertexLinkAcc( *this ).toPersistent();
+      }
+
+      // Prepare the truth particle links for writing:
+      if( truthParticleLinksAcc.isAvailableWritable( *this ) ) {
+         TruthParticleLinks_t::iterator itr =
+            truthParticleLinksAcc( *this ).begin();
+         TruthParticleLinks_t::iterator end =
+            truthParticleLinksAcc( *this ).end();
+         for( ; itr != end; ++itr ) {
+            itr->toPersistent();
+         }
+      }
+
+      // Prepare the truth vertex links for writing:
+      if( truthVertexLinksAcc.isAvailableWritable( *this ) ) {
+         TruthVertexLinks_t::iterator itr =
+            truthVertexLinksAcc( *this ).begin();
+         TruthVertexLinks_t::iterator end =
+            truthVertexLinksAcc( *this ).end();
+         for( ; itr != end; ++itr ) {
+            itr->toPersistent();
+         }
+      }
+      return;
+   }
+
+} // namespace xAOD
diff --git a/xAOD/xAODTruth/Root/TruthEventAuxContainer.cxx b/xAOD/xAODTruth/Root/TruthEventAuxContainer.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..52bfe7e6cccee143a9a7b3b4825f48f2b7d4cf88
--- /dev/null
+++ b/xAOD/xAODTruth/Root/TruthEventAuxContainer.cxx
@@ -0,0 +1,23 @@
+// Local include(s):
+#include "xAODTruth/TruthEventAuxContainer.h"
+
+namespace xAOD {
+
+   TruthEventAuxContainer::TruthEventAuxContainer()
+      : AuxContainerBase() {
+
+      AUX_VARIABLE( signalProcessVertexLink );
+
+      AUX_VARIABLE( weights );
+
+      AUX_VARIABLE( crossSection );
+      AUX_VARIABLE( crossSectionError );
+
+      AUX_VARIABLE( truthVertexLinks );
+      AUX_VARIABLE( truthParticleLinks );
+      
+      AUX_VARIABLE( weightNames );
+      AUX_VARIABLE( mcChannelNumber );
+   }
+
+} // namespace xAOD
diff --git a/xAOD/xAODTruth/Root/TruthParticle.cxx b/xAOD/xAODTruth/Root/TruthParticle.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..39142e928fc06561e65286ab96b65aa227cd5788
--- /dev/null
+++ b/xAOD/xAODTruth/Root/TruthParticle.cxx
@@ -0,0 +1,391 @@
+// -*- C++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: TruthParticle.cxx 690336 2015-08-20 10:54:57Z abuckley $
+
+// System include(s):
+#include <cmath>
+#include <iostream>
+#include <stdexcept>
+
+// Utility include(s):
+#include "TruthUtils/PIDHelpers.h"
+
+// xAOD include(s):
+#include "xAODCore/AuxStoreAccessorMacros.h"
+
+// Local include(s):
+#include "xAODTruth/TruthParticle.h"
+#include "xAODTruth/TruthVertexContainer.h"
+#include "TruthAccessors.h"
+
+namespace xAOD {
+
+   TruthParticle::TruthParticle()
+   : IParticle(), m_p4(), m_p4Cached( false ) {
+
+   }
+
+   /////////////////////////////////////////////////////////////////////////////
+   //
+   //  Implementation for functions identifying the particle in the MC record
+   //
+
+   AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( TruthParticle, int, pdgId,
+                                         setPdgId )
+
+   int TruthParticle::absPdgId() const {
+
+      return std::abs( pdgId() );
+   }
+
+   AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( TruthParticle, int, barcode,
+                                         setBarcode )
+   AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( TruthParticle, int, status,
+                                         setStatus )
+
+   //
+   /////////////////////////////////////////////////////////////////////////////
+
+   /////////////////////////////////////////////////////////////////////////////
+   //
+   //                Implementation of the links to the vertices
+   //
+
+   /// Accessor for the production vertex
+   static SG::AuxElement::Accessor< ElementLink< TruthVertexContainer > >
+      prodVtxLinkAcc( "prodVtxLink" );
+   /// Accessor for the decay vertex
+   static SG::AuxElement::Accessor< ElementLink< TruthVertexContainer > >
+      decayVtxLinkAcc( "decayVtxLink" );
+
+   bool TruthParticle::hasProdVtx() const {
+
+      return ( prodVtxLinkAcc.isAvailable( *this ) &&
+               prodVtxLinkAcc( *this ).isValid() );
+   }
+
+   const TruthVertex* TruthParticle::prodVtx() const {
+
+      return hasProdVtx() ? *prodVtxLink() : 0;
+   }
+
+   AUXSTORE_OBJECT_SETTER_AND_GETTER( TruthParticle,
+                                      ElementLink< TruthVertexContainer >,
+                                      prodVtxLink, setProdVtxLink )
+
+   bool TruthParticle::hasDecayVtx() const {
+
+      return ( decayVtxLinkAcc.isAvailable( *this ) &&
+               decayVtxLinkAcc( *this ).isValid() );
+   }
+
+   const TruthVertex* TruthParticle::decayVtx() const {
+
+      return hasDecayVtx() ? *decayVtxLink() : 0;
+   }
+
+   AUXSTORE_OBJECT_SETTER_AND_GETTER( TruthParticle,
+                                      ElementLink< TruthVertexContainer >,
+                                      decayVtxLink, setDecayVtxLink )
+
+   //
+   /////////////////////////////////////////////////////////////////////////////
+
+   /////////////////////////////////////////////////////////////////////////////
+   //
+   //                 Direct access to parents and children
+   //
+
+   size_t TruthParticle::nParents() const {
+
+      return hasProdVtx() ? prodVtx()->nIncomingParticles() : 0;
+   }
+
+   const TruthParticle* TruthParticle::parent( size_t i ) const {
+
+      return hasProdVtx() ? prodVtx()->incomingParticle( i ) : 0;
+   }
+
+   size_t TruthParticle::nChildren() const {
+
+      return hasDecayVtx() ? decayVtx()->nOutgoingParticles() : 0;
+   }
+
+   const TruthParticle* TruthParticle::child( size_t i ) const {
+
+      return hasDecayVtx() ? decayVtx()->outgoingParticle( i ) : 0;
+   }
+
+   //
+   /////////////////////////////////////////////////////////////////////////////
+
+   /////////////////////////////////////////////////////////////////////////////
+   //
+   //               Implementation of the IParticle interface
+   //
+
+   double TruthParticle::pt() const {
+
+      // Do the calculation by hand:
+      const double localPx = static_cast< double >( px() );
+      const double localPy = static_cast< double >( py() );
+      return std::sqrt( localPx * localPx + localPy * localPy );
+   }
+
+   double TruthParticle::eta() const {
+
+      // Calculate the pseudo-rapidity using TLorentzVector.
+      // Could do something more lightweight later on.
+      return p4().Eta();
+   }
+
+   double TruthParticle::phi() const {
+
+      // Calculate the azimuth angle using TLorentzVector.
+      // Could do something more lightweight later on.
+      return p4().Phi();
+   }
+
+   AUXSTORE_PRIMITIVE_GETTER_WITH_CAST( TruthParticle, float, double, m )
+   AUXSTORE_PRIMITIVE_GETTER_WITH_CAST( TruthParticle, float, double, e )
+
+   double TruthParticle::rapidity() const {
+
+      return p4().Rapidity();
+   }
+
+   const TruthParticle::FourMom_t& TruthParticle::p4() const {
+
+      // Cache the 4-momentum if it's not already:
+      if( ! m_p4Cached ) {
+         m_p4.SetPxPyPzE( px(), py(), pz(), e() );
+         m_p4Cached = true;
+      }
+
+      return m_p4;
+   }
+
+   Type::ObjectType TruthParticle::type() const {
+
+      return Type::TruthParticle;
+   }
+
+   //
+   /////////////////////////////////////////////////////////////////////////////
+
+   /////////////////////////////////////////////////////////////////////////////
+   //
+   //    Implementation of the truth particle specific 4-momentum functions
+   //
+
+   double TruthParticle::abseta() const {
+
+      return std::abs( eta() );
+   }
+
+   double TruthParticle::absrapidity() const {
+
+      return std::abs( rapidity() );
+   }
+
+   AUXSTORE_PRIMITIVE_GETTER( TruthParticle, float, px )
+
+   void TruthParticle::setPx( float value ) {
+      static Accessor< float > acc( "px" );
+      m_p4Cached = false;
+      acc( *this ) = value;
+      return;
+   }
+
+   AUXSTORE_PRIMITIVE_GETTER( TruthParticle, float, py )
+
+   void TruthParticle::setPy( float value ) {
+      static Accessor< float > acc( "py" );
+      m_p4Cached = false;
+      acc( *this ) = value;
+      return;
+   }
+
+   AUXSTORE_PRIMITIVE_GETTER( TruthParticle, float, pz )
+
+   void TruthParticle::setPz( float value ) {
+      static Accessor< float > acc( "pz" );
+      m_p4Cached = false;
+      acc( *this ) = value;
+      return;
+   }
+   
+   void TruthParticle::setE( float value ) {
+      static Accessor< float > acc( "e" );
+      m_p4Cached = false;
+      acc( *this ) = value;
+      return;
+   }
+   
+   void TruthParticle::setM( float value ) {
+      static Accessor< float > acc( "m" );
+      // note: this does not invalidate the cache
+      acc( *this ) = value;
+      return;
+   }
+   
+   //
+   /////////////////////////////////////////////////////////////////////////////
+
+   /////////////////////////////////////////////////////////////////////////////
+   //
+   //         Implementation of the particle species decoder functions
+   //
+
+/// Helper macro to implement the functions that rely in functions from MC::PID
+#define MC_PID_HELPER( TYPE, FNAME )      \
+   TYPE TruthParticle::FNAME() const { \
+      return MC::PID::FNAME( pdgId() );   \
+   }
+
+   MC_PID_HELPER( double, charge )
+   MC_PID_HELPER( int, threeCharge )
+
+   MC_PID_HELPER( bool, isCharged )
+   MC_PID_HELPER( bool, isNeutral )
+
+   MC_PID_HELPER( bool, isPhoton )
+   MC_PID_HELPER( bool, isLepton )
+   MC_PID_HELPER( bool, isChLepton )
+   MC_PID_HELPER( bool, isElectron )
+   MC_PID_HELPER( bool, isMuon )
+   MC_PID_HELPER( bool, isTau )
+   MC_PID_HELPER( bool, isNeutrino )
+
+   MC_PID_HELPER( bool, isHadron )
+   MC_PID_HELPER( bool, isMeson )
+   MC_PID_HELPER( bool, isBaryon )
+
+   MC_PID_HELPER( bool, hasStrange )
+   MC_PID_HELPER( bool, hasCharm )
+   MC_PID_HELPER( bool, hasBottom )
+
+   MC_PID_HELPER( bool, isLightMeson )
+   MC_PID_HELPER( bool, isLightBaryon )
+   MC_PID_HELPER( bool, isLightHadron )
+
+   MC_PID_HELPER( bool, isHeavyMeson )
+   MC_PID_HELPER( bool, isHeavyBaryon )
+   MC_PID_HELPER( bool, isHeavyHadron )
+
+   MC_PID_HELPER( bool, isBottomMeson )
+   MC_PID_HELPER( bool, isBottomBaryon )
+   MC_PID_HELPER( bool, isBottomHadron )
+
+   MC_PID_HELPER( bool, isCharmMeson )
+   MC_PID_HELPER( bool, isCharmBaryon )
+   MC_PID_HELPER( bool, isCharmHadron )
+
+   MC_PID_HELPER( bool, isStrangeMeson )
+   MC_PID_HELPER( bool, isStrangeBaryon )
+   MC_PID_HELPER( bool, isStrangeHadron )
+
+   MC_PID_HELPER( bool, isQuark )
+   MC_PID_HELPER( bool, isParton )
+   MC_PID_HELPER( bool, isTop )
+   MC_PID_HELPER( bool, isW )
+   MC_PID_HELPER( bool, isZ )
+   MC_PID_HELPER( bool, isHiggs )
+   MC_PID_HELPER( bool, isResonance )
+   MC_PID_HELPER( bool, isGenSpecific )
+
+// Forget about this macro:
+#undef MC_PID_HELPER
+
+   //
+   /////////////////////////////////////////////////////////////////////////////
+
+   /////////////////////////////////////////////////////////////////////////////
+   //
+   //          Implementation of the optional polarization accessors
+   //
+
+   bool TruthParticle::polarizationParameter( float& value,
+                                                 PolParam param ) const {
+
+      // Get the accessor object:
+      Accessor< float >* acc = polarizationAccessor( param );
+      if( ! acc ) {
+         // The user asked for a non-existent parameter type. o.O
+         std::cerr << "xAOD::TruthParticle::polarizationParameter ERROR "
+                   << "Request for an unknown (" << param << ") polarization "
+                   << "parameter type" << std::endl;
+         return false;
+      }
+      // Check if the variable is available:
+      if( ! acc->isAvailable( *this ) ) {
+         // No, it is not.
+         return false;
+      }
+
+      // Read the value:
+      value = ( *acc )( *this );
+      return true;
+   }
+
+   bool TruthParticle::setPolarizationParameter( float value,
+                                                    PolParam param ) {
+
+      // Get the accessor object:
+      Accessor< float >* acc = polarizationAccessor( param );
+      if( ! acc ) {
+         // The user asked for a non-existent parameter type. o.O
+         std::cerr << "xAOD::TruthParticle::setPolarizationParameter ERROR "
+                   << "Request for an unknown (" << param << ") polarization "
+                   << "parameter type" << std::endl;
+         return false;
+      }
+
+      // Set the value:
+      ( *acc )( *this ) = value;
+      return true;
+   }
+
+   float TruthParticle::polarizationPatameter( PolParam param ) const {
+
+      // Get the accessor object:
+      Accessor< float >* acc = polarizationAccessor( param );
+      if( ! acc ) {
+         // Throw an exception:
+         throw std::runtime_error( "Unrecognized polarization parameter "
+                                   "requested" );
+      }
+
+      // Read the value:
+      return ( *acc )( *this );
+   }
+
+   TruthParticle::Polarization TruthParticle::polarization() const {
+
+      // Construct the object:
+      Polarization rtn;
+      polarizationParameter( rtn.phi, polarizationPhi );
+      polarizationParameter( rtn.theta, polarizationTheta );
+
+      return rtn;
+   }
+
+   //
+   /////////////////////////////////////////////////////////////////////////////
+
+   void TruthParticle::toPersistent() {
+
+      if( prodVtxLinkAcc.isAvailableWritable( *this ) ) {
+         prodVtxLinkAcc( *this ).toPersistent();
+      }
+      if( decayVtxLinkAcc.isAvailableWritable( *this ) ) {
+         decayVtxLinkAcc( *this ).toPersistent();
+      }
+      return;
+   }
+
+} // namespace xAOD
diff --git a/xAOD/xAODTruth/Root/TruthParticleAuxContainer.cxx b/xAOD/xAODTruth/Root/TruthParticleAuxContainer.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..8a4fede3de464d9cb78628e8a34ab25b98ff82fe
--- /dev/null
+++ b/xAOD/xAODTruth/Root/TruthParticleAuxContainer.cxx
@@ -0,0 +1,21 @@
+// Local include(s):
+#include "xAODTruth/TruthParticleAuxContainer.h"
+
+namespace xAOD {
+
+   TruthParticleAuxContainer::TruthParticleAuxContainer()
+   : AuxContainerBase() {
+
+      AUX_VARIABLE( pdgId );
+      AUX_VARIABLE( barcode );
+      AUX_VARIABLE( status );
+      AUX_VARIABLE( prodVtxLink );
+      AUX_VARIABLE( decayVtxLink );
+      AUX_VARIABLE( px );
+      AUX_VARIABLE( py );
+      AUX_VARIABLE( pz );
+      AUX_VARIABLE( e );
+      AUX_VARIABLE( m );
+   }
+
+} // namespace xAOD
diff --git a/xAOD/xAODTruth/Root/TruthVertex.cxx b/xAOD/xAODTruth/Root/TruthVertex.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..fcc606097f29f9caae6a664be94ec454b7d59710
--- /dev/null
+++ b/xAOD/xAODTruth/Root/TruthVertex.cxx
@@ -0,0 +1,251 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: TruthVertex.cxx 624338 2014-10-27 15:08:55Z krasznaa $
+
+// System include(s):
+#include <cmath>
+
+// xAOD include(s):
+#include "xAODCore/AuxStoreAccessorMacros.h"
+
+// Local include(s):
+#include "xAODTruth/TruthVertex.h"
+#include "xAODTruth/TruthParticleContainer.h"
+
+namespace xAOD {
+
+   TruthVertex::TruthVertex()
+   : SG::AuxElement(), m_v4(), m_v4Cached( false ) {
+
+   }
+
+   /////////////////////////////////////////////////////////////////////////////
+   //
+   //            Implementation for the "MC specific" functions
+   //
+
+   AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( TruthVertex, int, id, setId )
+   AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( TruthVertex, int, barcode,
+                                         setBarcode )
+
+   //
+   /////////////////////////////////////////////////////////////////////////////
+
+   /////////////////////////////////////////////////////////////////////////////
+   //
+   //           Implementation for the links to the truth particles
+   //
+
+   AUXSTORE_OBJECT_SETTER_AND_GETTER( TruthVertex, TruthVertex::TPLinks_t,
+                                      incomingParticleLinks,
+                                      setIncomingParticleLinks )
+
+   /// Accessor for the incoming particles
+   static SG::AuxElement::Accessor< TruthVertex::TPLinks_t >
+      incomingParticleLinksAcc( "incomingParticleLinks" );
+
+   size_t TruthVertex::nIncomingParticles() const {
+   
+      // Check if the variable is available:
+      if( ! incomingParticleLinksAcc.isAvailable( *this ) ) {
+         // If not, just tell the user that there aren't any incoming particles:
+         return 0;
+      }
+
+      // Return the size of the vector:
+      return incomingParticleLinksAcc( *this ).size();
+   }
+
+   const TruthParticle* TruthVertex::incomingParticle( size_t index ) const {
+
+      // Check that the variable exists, and that it has enough elements in it:
+      if( ( ! incomingParticleLinksAcc.isAvailable( *this ) ) ||
+          ( incomingParticleLinksAcc( *this ).size() <= index ) ) {
+         return 0;
+      }
+
+      // Retrieve the link object and check its validity:
+      const TPLink_t& ipl = incomingParticleLinksAcc( *this )[ index ];
+      if( ! ipl.isValid() ) {
+         return 0;
+      }
+
+      // Finally, de-reference the link:
+      return *ipl;
+   }
+
+   void TruthVertex::addIncomingParticleLink( const TPLink_t& link ) {
+
+      incomingParticleLinksAcc( *this ).push_back( link );
+      return;
+   }
+
+   void TruthVertex::clearIncomingParticleLinks() {
+
+      incomingParticleLinksAcc( *this ).clear();
+      return;
+   }
+
+   AUXSTORE_OBJECT_SETTER_AND_GETTER( TruthVertex, TruthVertex::TPLinks_t,
+                                      outgoingParticleLinks,
+                                      setOutgoingParticleLinks )
+
+   /// Accessor for the outgoing particles
+   static SG::AuxElement::Accessor< TruthVertex::TPLinks_t >
+      outgoingParticleLinksAcc( "outgoingParticleLinks" );
+
+   size_t TruthVertex::nOutgoingParticles() const {
+
+      // Check if the variable is available:
+      if( ! outgoingParticleLinksAcc.isAvailable( *this ) ) {
+         // If not, just tell the user that there aren't any outgoing particles:
+         return 0;
+      }
+
+      // Return the size of the vector:
+      return outgoingParticleLinksAcc( *this ).size();
+   }
+
+   const TruthParticle* TruthVertex::outgoingParticle( size_t index ) const {
+
+      // Check that the variable exists, and that it has enough elements in it:
+      if( ( ! outgoingParticleLinksAcc.isAvailable( *this ) ) ||
+          ( outgoingParticleLinksAcc( *this ).size() <= index ) ) {
+         return 0;
+      }
+
+      // Retrieve the link object and check its validity:
+      const TPLink_t& opl = outgoingParticleLinksAcc( *this )[ index ];
+      if( ! opl.isValid() ) {
+         return 0;
+      }
+      
+      // Finally, de-reference the link:
+      return *opl;
+   }
+
+   void TruthVertex::addOutgoingParticleLink( const TPLink_t& link ) {
+
+      outgoingParticleLinksAcc( *this ).push_back( link );
+      return;
+   }
+
+   void TruthVertex::clearOutgoingParticleLinks() {
+
+      outgoingParticleLinksAcc( *this ).clear();
+      return;
+   }
+
+   //
+   /////////////////////////////////////////////////////////////////////////////
+
+   /////////////////////////////////////////////////////////////////////////////
+   //
+   //     Implementation of the functions specifying the vertex's position
+   //
+
+   AUXSTORE_PRIMITIVE_GETTER( TruthVertex, float, x )
+
+   void TruthVertex::setX( float x ) {
+
+      static SG::AuxElement::Accessor< float > acc( "x" );
+      m_v4Cached = false;
+      acc( *this ) = x;
+      return;
+   }
+
+   AUXSTORE_PRIMITIVE_GETTER( TruthVertex, float, y )
+
+   void TruthVertex::setY( float y ) {
+
+      static SG::AuxElement::Accessor< float > acc( "y" );
+      m_v4Cached = false;
+      acc( *this ) = y;
+      return;
+   }
+
+   AUXSTORE_PRIMITIVE_GETTER( TruthVertex, float, z )
+
+   void TruthVertex::setZ( float z ) {
+
+      static SG::AuxElement::Accessor< float > acc( "z" );
+      m_v4Cached = false;
+      acc( *this ) = z;
+      return;
+   }
+
+   float TruthVertex::perp() const {
+
+      // Do the calculation by hand. Could make it faster than this even in a
+      // future iteration...
+      return std::sqrt( x() * x() + y() * y() );
+   }
+
+   float TruthVertex::eta() const {
+
+      // This is not necessarily what Andy was thinking about...
+      return v4().Eta();
+   }
+
+   float TruthVertex::phi() const {
+
+      // This is not necessarily what Andy was thinking about...
+      return v4().Phi();
+   }
+
+   AUXSTORE_PRIMITIVE_GETTER( TruthVertex, float, t )
+
+   void TruthVertex::setT( float t ) {
+
+      static SG::AuxElement::Accessor< float > acc( "t" );
+      m_v4Cached = false;
+      acc( *this ) = t;
+      return;
+   }
+
+   const TruthVertex::FourVec_t& TruthVertex::v4() const {
+
+      // Cache the 4-vector if it's not already:
+      if( ! m_v4Cached ) {
+         m_v4.SetXYZT( x(), y(), z(), t() );
+         m_v4Cached = true;
+      }
+
+      // Return the cached object:
+      return m_v4;
+   }
+
+   //
+   /////////////////////////////////////////////////////////////////////////////
+
+   Type::ObjectType TruthVertex::type() const {
+
+      return Type::TruthVertex;
+   }
+
+   void TruthVertex::toPersistent() {
+
+      // Prepare the incoming particle links for persistification:
+      if( incomingParticleLinksAcc.isAvailableWritable( *this ) ) {
+         TPLinks_t::iterator itr = incomingParticleLinksAcc( *this ).begin();
+         TPLinks_t::iterator end = incomingParticleLinksAcc( *this ).end();
+         for( ; itr != end; ++itr ) {
+            itr->toPersistent();
+         }
+      }
+
+      // Prepare the outgoing particle links for persistification:
+      if( outgoingParticleLinksAcc.isAvailableWritable( *this ) ) {
+         TPLinks_t::iterator itr = outgoingParticleLinksAcc( *this ).begin();
+         TPLinks_t::iterator end = outgoingParticleLinksAcc( *this ).end();
+         for( ; itr != end; ++itr ) {
+            itr->toPersistent();
+         }
+      }
+
+      return;
+   }
+
+} // namespace xAOD
diff --git a/xAOD/xAODTruth/Root/TruthVertexAuxContainer.cxx b/xAOD/xAODTruth/Root/TruthVertexAuxContainer.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..a0b3f0d606f64ff8224cabeeb4760fb857acc548
--- /dev/null
+++ b/xAOD/xAODTruth/Root/TruthVertexAuxContainer.cxx
@@ -0,0 +1,25 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: TruthVertexAuxContainer.cxx 624338 2014-10-27 15:08:55Z krasznaa $
+
+// Local include(s):
+#include "xAODTruth/TruthVertexAuxContainer.h"
+
+namespace xAOD {
+
+   TruthVertexAuxContainer::TruthVertexAuxContainer()
+   : AuxContainerBase() {
+
+      AUX_VARIABLE( id );
+      AUX_VARIABLE( barcode );
+      AUX_VARIABLE( incomingParticleLinks );
+      AUX_VARIABLE( outgoingParticleLinks );
+      AUX_VARIABLE( x );
+      AUX_VARIABLE( y );
+      AUX_VARIABLE( z );
+      AUX_VARIABLE( t );
+   }
+
+} // namespace xAOD
diff --git a/xAOD/xAODTruth/Root/dict/ContainerProxies.cxx b/xAOD/xAODTruth/Root/dict/ContainerProxies.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..c3086181764205a40e47b54a7cabdde37ea85bbe
--- /dev/null
+++ b/xAOD/xAODTruth/Root/dict/ContainerProxies.cxx
@@ -0,0 +1,12 @@
+// EDM include(s):
+#include "xAODCore/AddDVProxy.h"
+
+// Local include(s):
+#include "xAODTruth/TruthParticleContainer.h"
+#include "xAODTruth/TruthVertexContainer.h"
+#include "xAODTruth/TruthEventContainer.h"
+
+// Set up the collection proxies:
+ADD_NS_DV_PROXY( xAOD, TruthParticleContainer );
+ADD_NS_DV_PROXY( xAOD, TruthVertexContainer );
+ADD_NS_DV_PROXY( xAOD, TruthEventContainer );
diff --git a/xAOD/xAODTruth/Root/xAODTruthCLIDs.cxx b/xAOD/xAODTruth/Root/xAODTruthCLIDs.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..50c624ca9b6fe760a22eaba20505d412f3e02359
--- /dev/null
+++ b/xAOD/xAODTruth/Root/xAODTruthCLIDs.cxx
@@ -0,0 +1,14 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+//simple includes to force the CLASS_DEF to be encountered during compile
+
+#include "xAODTruth/TruthVertexContainer.h"
+#include "xAODTruth/TruthVertexAuxContainer.h"
+#include "xAODTruth/TruthEventContainer.h"
+#include "xAODTruth/TruthEventAuxContainer.h"
+#include "xAODTruth/TruthParticleContainer.h"
+#include "xAODTruth/TruthParticleAuxContainer.h"
+
diff --git a/xAOD/xAODTruth/Root/xAODTruthHelpers.cxx b/xAOD/xAODTruth/Root/xAODTruthHelpers.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..3d00de95e602944a5a772eff2a659cb1f4afe9cf
--- /dev/null
+++ b/xAOD/xAODTruth/Root/xAODTruthHelpers.cxx
@@ -0,0 +1,90 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: xAODTruthHelpers.cxx 668406 2015-05-19 15:32:15Z krasznaa $
+
+// Core EDM include(s):
+#include "AthLinks/ElementLink.h"
+#include "AthContainers/AuxElement.h"
+
+// xAOD include(s):
+#include "xAODBase/IParticle.h"
+
+// Local include(s):
+#include "xAODTruth/xAODTruthHelpers.h"
+#include "xAODTruth/TruthParticle.h"
+#include "xAODTruth/TruthParticleContainer.h"
+
+namespace xAOD {
+
+   namespace TruthHelpers {
+
+      /// @param p The particle that we find the associated truth particle for
+      /// @returns A pointer to the associated truth particle if available,
+      ///          or a null pointer if not
+      ///
+      const xAOD::TruthParticle* getTruthParticle( const xAOD::IParticle& p ) {
+
+         /// A convenience type declaration
+         typedef ElementLink< xAOD::TruthParticleContainer > Link_t;
+
+         /// A static accessor for the information
+         static SG::AuxElement::ConstAccessor< Link_t > acc( "truthParticleLink" );
+
+         // Check if such a link exists on the object:
+         if( ! acc.isAvailable( p ) ) {
+            return 0;
+         }
+
+         // Get the link:
+         const Link_t& link = acc( p );
+
+         // Check if the link is valid:
+         if( ! link.isValid() ) {
+            return 0;
+         }
+
+         // Everything has passed, let's return the pointer:
+         return *link;
+      }
+
+      /// @param p The particle that we want to find the truth type of
+      /// @returns 0 if the truth type is not available, or the truth type
+      ///          determined by MCTruthClassifier, if it is
+      ///
+      int getParticleTruthType( const xAOD::IParticle& p ) {
+
+         /// A static accessor for the information
+         static SG::AuxElement::ConstAccessor< int > acc( "truthType" );
+
+         // Check if such a variable exists on the object:
+         if( ! acc.isAvailable( p ) ) {
+            return 0;
+         }
+
+         // Let's return the value:
+         return acc( p );
+      }
+
+      /// @param p The particle that we want to find the truth origin of
+      /// @returns 0 if the truth origin is not available, or the truth origin
+      ///          determined by MCTruthClassifier, if it is
+      ///
+      int getParticleTruthOrigin( const xAOD::IParticle& p ) {
+
+         /// A static accessor for the information
+         static SG::AuxElement::ConstAccessor< int > acc( "truthOrigin" );
+
+         // Check if such a variable exists on the object:
+         if( ! acc.isAvailable( p ) ) {
+            return 0;
+         }
+
+         // Let's return the value:
+         return acc( p );
+      }
+
+   } // namespace TruthHelpers
+
+} // namespace xAOD
diff --git a/xAOD/xAODTruth/TODO b/xAOD/xAODTruth/TODO
new file mode 100644
index 0000000000000000000000000000000000000000..65552242600f222c6c7417e5bd35dd24d2af6b29
--- /dev/null
+++ b/xAOD/xAODTruth/TODO
@@ -0,0 +1,8 @@
+xAOD truth TODOs
+================
+
+* Tidy TruthEvent attrs, add named weight vector
+
+* Handling run-level info like cross-sections?
+
+* Add a vector of separate TruthPileupEvent objects, which store no event-level info
diff --git a/xAOD/xAODTruth/cmt/Makefile.RootCore b/xAOD/xAODTruth/cmt/Makefile.RootCore
new file mode 100644
index 0000000000000000000000000000000000000000..e44442caa389d2963ed687991bbed33a412b1654
--- /dev/null
+++ b/xAOD/xAODTruth/cmt/Makefile.RootCore
@@ -0,0 +1,24 @@
+# this makefile also gets parsed by shell scripts
+# therefore it does not support full make syntax and features
+# edit with care
+
+# for full documentation check:
+# https://twiki.cern.ch/twiki/bin/viewauth/Atlas/RootCore#Package_Makefile
+
+PACKAGE          = xAODTruth
+PACKAGE_PRELOAD  =
+PACKAGE_CXXFLAGS =
+PACKAGE_OBJFLAGS =
+PACKAGE_LDFLAGS  =
+PACKAGE_BINFLAGS =
+PACKAGE_LIBFLAGS =
+PACKAGE_DEP      = AthContainers AthLinks xAODBase xAODCore TruthUtils
+PACKAGE_TRYDEP   =
+PACKAGE_CLEAN    =
+PACKAGE_NOGRID   =
+PACKAGE_PEDANTIC = 1
+PACKAGE_NOOPT    = 0
+PACKAGE_NOCC     = 0
+PACKAGE_REFLEX   = 1
+
+include $(ROOTCOREDIR)/Makefile-common
diff --git a/xAOD/xAODTruth/cmt/requirements b/xAOD/xAODTruth/cmt/requirements
new file mode 100644
index 0000000000000000000000000000000000000000..44f457ab07aacdadc7b5440f8ba1ab3fcd1062ec
--- /dev/null
+++ b/xAOD/xAODTruth/cmt/requirements
@@ -0,0 +1,42 @@
+package xAODTruth
+# $Id: requirements 761796 2016-07-14 08:06:02Z krasznaa $
+
+author Andy Buckley <andy.buckley@cern.ch>
+author James Catmore <james.catmore@cern.ch>
+author Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch>
+author Jovan Mitrevski <Jovan.Mitrevski@cern.ch>
+
+public
+
+# Central packages:
+use AtlasPolicy     AtlasPolicy-*
+use AthContainers   AthContainers-*    Control
+use AthLinks        AthLinks-*         Control
+
+# EDM packages:
+use xAODBase        xAODBase-*         Event/xAOD
+use xAODCore        xAODCore-*         Event/xAOD
+use AtlasROOT       AtlasROOT-*        External
+
+# Specify the ROOT components that are necessary for cmake. Transparent to CMT
+apply_pattern cmake_add_command command="find_package(ROOT COMPONENTS Physics)"
+
+library xAODTruth ../Root/*.cxx
+apply_pattern installed_library
+
+private
+
+use TruthUtils      TruthUtils-*       Generators
+use AtlasReflex     AtlasReflex-*      External
+
+# Generate a dictionary for the package:
+apply_pattern lcgdict dict=xAODTruth selectionfile=selection.xml \
+                      headerfiles="../xAODTruth/xAODTruthDict.h" \
+                      extralibfiles=../Root/dict/*.cxx
+
+apply_pattern do_genCLIDDB library=xAODTruth
+
+# Specify the unit test(s) of the package:
+use TestTools       TestTools-*        AtlasTest
+apply_pattern UnitTest_run unit_test=ut_xaodtruth_particle
+
diff --git a/xAOD/xAODTruth/share/ut_xaodtruth_particle_test.ref b/xAOD/xAODTruth/share/ut_xaodtruth_particle_test.ref
new file mode 100644
index 0000000000000000000000000000000000000000..fdaff706b58a58b373166733cd7d08319568a231
--- /dev/null
+++ b/xAOD/xAODTruth/share/ut_xaodtruth_particle_test.ref
@@ -0,0 +1 @@
+All tests succeeded
diff --git a/xAOD/xAODTruth/test/ut_xaodtruth_helpers_test.py b/xAOD/xAODTruth/test/ut_xaodtruth_helpers_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..4147126363f0779555b4663a4acca857d0c98252
--- /dev/null
+++ b/xAOD/xAODTruth/test/ut_xaodtruth_helpers_test.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+#
+# $Id: ut_xaodtruth_helpers_test.py 761304 2016-07-12 12:03:36Z krasznaa $
+#
+# This is a simple unit test for checking the health of the truth helper
+# functions in the standalone analysis environment.
+#
+
+## C/C++ style main function
+def main():
+
+    # Initialise the environment:
+    import ROOT
+    ROOT.gROOT.Macro( "$ROOTCOREDIR/scripts/load_packages.C" )
+
+    # Open an input xAOD file:
+    import os
+    FNAME = os.getenv( "ROOTCORE_TEST_FILE", "FileNotSpecifiedInEnvironment" )
+    f = ROOT.TFile.Open( FNAME, "READ" )
+    if not f:
+        print( "Couldn't open \"%s\"" % FNAME )
+        return 1
+    print( "Opened: %s" % FNAME )
+
+    # Make a transient tree from it:
+    treeMgr = ROOT.xAOD.TTreeMgr( ROOT.xAOD.TEvent.kAthenaAccess )
+    if not treeMgr.readFrom( f ).isSuccess():
+        print( "Couldn't make a transient tree from the input file!" )
+        return 1
+    import xAODRootAccess.GenerateDVIterators
+    t = treeMgr.eventTree()
+
+    # Loop on the first few events:
+    for entry in xrange( 10 ):
+        # Load the event:
+        if t.GetEntry( entry ) < 0:
+            print( "Couldn't load entry %i from the input!" % entry )
+            return 1
+        # Print some header info:
+        print( "Processing run #%i event #%i (%i events processed so far)" % \
+               ( t.EventInfo.runNumber(), t.EventInfo.eventNumber(), entry ) )
+        # Exercise the functions on electrons:
+        for el in t.Electrons:
+            print( " - Electron: eta = %g, phi = %g, pt = %g" % \
+                   ( el.eta(), el.phi(), el.pt() ) )
+            print( "             truthType = %i, truthOrigin = %i" % \
+                   ( ROOT.xAOD.TruthHelpers.getParticleTruthType( el ),
+                     ROOT.xAOD.TruthHelpers.getParticleTruthOrigin( el ) ) )
+            tp = ROOT.xAOD.TruthHelpers.getTruthParticle( el )
+            if tp:
+                print( "   - TruthParticle: eta = %g, phi = %g, pt = %g" % \
+                       ( tp.eta(), tp.phi(), tp.pt() ) )
+                pass
+            pass
+        pass
+
+    return 0;
+
+# Execute the main function:
+if __name__ == "__main__":
+    import sys
+    sys.exit( main() )
diff --git a/xAOD/xAODTruth/test/ut_xaodtruth_particle_test.cxx b/xAOD/xAODTruth/test/ut_xaodtruth_particle_test.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..363f3b15cb5bc712f1111babdea7cde394b23718
--- /dev/null
+++ b/xAOD/xAODTruth/test/ut_xaodtruth_particle_test.cxx
@@ -0,0 +1,73 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: ut_xaodtruth_particle_test.cxx 687313 2015-08-04 12:07:38Z krasznaa $
+
+// System include(s):
+#include <iostream>
+#include <cmath>
+
+// Local include(s):
+#include "xAODTruth/TruthParticle.h"
+#include "xAODTruth/TruthParticleContainer.h"
+#include "xAODTruth/TruthParticleAuxContainer.h"
+
+/// Helper macro to test assertions
+#define SIMPLE_ASSERT( EXP )                                                \
+   do {                                                                     \
+      if( ! ( EXP ) ) {                                                     \
+         std::cout << "Error evaluating: " << #EXP << std::endl;            \
+         return 1;                                                          \
+      }                                                                     \
+   } while( 0 )
+
+int main() {
+
+   // Create a container to test:
+   xAOD::TruthParticleContainer c;
+   xAOD::TruthParticleAuxContainer aux;
+   c.setStore( &aux );
+
+   // Construct a particle that we can test. The values are chosen on purpose
+   // to not be possible to represent in exactly the same way at single and
+   // double precision.
+   static const double PX = std::sqrt( ( double ) 1.2345 );
+   static const double PY = std::sqrt( ( double ) 2.3456 );
+   static const double PZ = std::sqrt( ( double ) 3.4567 );
+   static const double E  = std::sqrt( ( double ) 4.5678 );
+   static const double M  = std::sqrt( ( double ) 5.6789 );
+   xAOD::TruthParticle* p = new xAOD::TruthParticle();
+   c.push_back( p );
+   p->setPx( PX );
+   p->setPy( PY );
+   p->setPz( PZ );
+   p->setE( E );
+   p->setM( M );
+
+   // The precisions that we want:
+   static const double FLOAT_PRECISION  = 1e-5;
+   static const double DOUBLE_PRECISION = 1e-10;
+
+   // Start with the most basic checks:
+   SIMPLE_ASSERT( std::abs( p->px() - PX ) < FLOAT_PRECISION );
+   SIMPLE_ASSERT( std::abs( p->py() - PY ) < FLOAT_PRECISION );
+   SIMPLE_ASSERT( std::abs( p->pz() - PZ ) < FLOAT_PRECISION );
+   SIMPLE_ASSERT( std::abs( p->e() - E ) < FLOAT_PRECISION );
+   SIMPLE_ASSERT( std::abs( p->m() - M ) < FLOAT_PRECISION );
+
+   // Now something more tricky:
+   SIMPLE_ASSERT( std::abs( p->pt() - p->p4().Pt() ) < DOUBLE_PRECISION );
+   SIMPLE_ASSERT( std::abs( p->eta() - p->p4().Eta() ) < DOUBLE_PRECISION );
+   SIMPLE_ASSERT( std::abs( p->phi() - p->p4().Phi() ) < DOUBLE_PRECISION );
+   SIMPLE_ASSERT( std::abs( p->e() - p->p4().E() ) < DOUBLE_PRECISION );
+
+   // And finally something not completely obvious:
+   SIMPLE_ASSERT( std::abs( p->m() - p->p4().M() ) > 0.1 );
+
+   // Let the user know what happened:
+   std::cout << "All tests succeeded" << std::endl;
+
+   // Return gracefully:
+   return 0;
+}
diff --git a/xAOD/xAODTruth/xAODTruth/TruthEvent.h b/xAOD/xAODTruth/xAODTruth/TruthEvent.h
new file mode 100644
index 0000000000000000000000000000000000000000..939dd937c16c70a64fa3bf5dbee0fb48802b1ddf
--- /dev/null
+++ b/xAOD/xAODTruth/xAODTruth/TruthEvent.h
@@ -0,0 +1,210 @@
+#ifndef XAODTRUTH_TRUTHEVENT_H
+#define XAODTRUTH_TRUTHEVENT_H
+
+// System include(s):
+#include <utility>
+#include <vector>
+
+// EDM include(s):
+#include "AthContainers/AuxElement.h"
+#include "AthLinks/ElementLink.h"
+#include "xAODBase/ObjectType.h"
+
+// Local include(s):
+#include "xAODTruth/TruthParticleContainer.h"
+#include "xAODTruth/TruthVertexContainer.h"
+
+namespace xAOD {
+
+   /// Class describing a signal truth event in the MC record
+   ///
+   class TruthEvent : public SG::AuxElement {
+
+   public:
+      /// Default constructor
+      TruthEvent();
+      /// Virtual destructor, to make vtable happy
+      virtual ~TruthEvent() {}
+
+      /// @name Access to all the particles associated with the event
+      /// @{
+
+      /// Type of a single truth particle link
+      typedef ElementLink< TruthParticleContainer > TruthParticleLink_t;
+      /// Type of the truth particle links vector
+      typedef std::vector< TruthParticleLink_t > TruthParticleLinks_t;
+
+      /// Get all the truth particles
+      const TruthParticleLinks_t& truthParticleLinks() const;
+      /// Set all the truth particles
+      void setTruthParticleLinks( const TruthParticleLinks_t& plinks );
+      /// Get the number of truth particles
+      size_t nTruthParticles() const;
+      /// Get the link to one of the truth particles
+      const TruthParticleLink_t& truthParticleLink( size_t index ) const;
+      /// Get a pointer to one of the truth particles
+      const TruthParticle* truthParticle( size_t index ) const;
+      /// Add one truth particle
+      void addTruthParticleLink( const TruthParticleLink_t& plink );
+      /// Remove all truth particles
+      void clearTruthParticleLinks();
+
+      /// @}
+      
+      /// @name Access to all the vertices associated with the event
+      /// @{
+
+      /// Type of a single truth vertex link
+      typedef ElementLink< TruthVertexContainer > TruthVertexLink_t;
+      /// Type of the truth particle links vector
+      typedef std::vector< TruthVertexLink_t > TruthVertexLinks_t;
+
+      /// Get all the truth vertices
+      const TruthVertexLinks_t& truthVertexLinks() const;
+      /// Set all the truth vertices
+      void setTruthVertexLinks( const TruthVertexLinks_t& links );
+      /// Get the number of truth vertices
+      size_t nTruthVertices() const;
+      /// Get the link to one of the truth vertices
+      const TruthVertexLink_t& truthVertexLink( size_t index ) const;
+      /// Get a pointer to one of the truth vertices
+      const TruthVertex* truthVertex( size_t index ) const;
+      /// Add one truth vertex
+      void addTruthVertexLink( const TruthVertexLink_t& vlink );
+      /// Remove all truth vertices
+      void clearTruthVertexLinks();
+
+      /// @}
+      
+      /// @name Simple event properties
+      /// @{
+
+      /// Const access to the weights vector
+      /// @todo Need to add the map-like interface for the weights: very important!
+      const std::vector< float >& weights() const;
+      /// Set the event weights
+      /// @todo Need to add named weight access: vector<string>
+      void setWeights( const std::vector< float >& weights );
+
+      /// Get the cross section
+      float crossSection() const;
+      /// Set the cross-section
+      void setCrossSection( float value );
+
+      /// Get the cross section error
+      float crossSectionError() const;
+      /// Set the cross-section error
+      void setCrossSectionError( float value );
+
+      /// Set the cross-section and its error
+      void setCrossSection( float value, float error );
+
+      /// @}
+
+      /// @name Parton density info
+      ///
+      /// Optional due to particle gun & NLO events where a single PDF info
+      /// doesn't work.
+      ///
+      /// @{
+
+      /// Accessor enums for PDF info parameter lookup
+      enum PdfParam {
+         PDGID1 = 0, ///< [int]
+         PDGID2 = 1, ///< [int]
+         PDFID1 = 2, ///< [int]
+         PDFID2 = 3, ///< [int]
+         X1 = 4,     ///< [float]
+         X2 = 5,     ///< [float]
+         SCALE = 6,  ///< Not implemented!!!
+         Q = 6,      ///< [float]
+         PDF1 = 7,   ///< Not implemented!!!
+         PDF2 = 8,   ///< Not implemented!!!
+         XF1 = 7,    ///< [float]
+         XF2 = 8     ///< [float]
+      }; // enum PdfParam
+
+      /// Read an integer PDF info parameter
+      bool pdfInfoParameter( int& value, PdfParam parameter ) const;
+      /// Read a floating point PDF info parameter
+      bool pdfInfoParameter( float& value, PdfParam parameter ) const;
+
+      /// Set an integer PDF info parameter
+      bool setPdfInfoParameter( int value, PdfParam parameter );
+      /// Set a floating point PDF info parameter
+      bool setPdfInfoParameter( float value, PdfParam parameter );
+
+      /// Helper struct holding a full set of PDF info values
+      struct PdfInfo {
+
+         /// Constructor to set (invalid) defaults
+         PdfInfo();
+
+         /// Check if all the variables in the object are valid
+         bool valid() const;
+
+         int pdgId1;
+         int pdgId2;
+         int pdfId1;
+         int pdfId2;
+         float x1;
+         float x2;
+         float Q;
+         float xf1;
+         float xf2;
+
+      }; // struct PdfInfo
+
+      /// Retrieve a full PdfInfo with a single call
+      /// @note May have invalid values -- use valid() to check.
+      PdfInfo pdfInfo() const;
+
+      /// @}
+
+      /// @name Links to particles and vertices in the event
+      /// @{
+
+      /// Pointer to a vertex representing the primary interaction point
+      ///
+      /// The naming of the function is a bit misleading. The returned vertex
+      /// can only be interpreted as an interaction *position*.
+      ///
+      const TruthVertex* signalProcessVertex() const;
+      /// Link to the vertex representing the primary interaction point
+      const TruthVertexLink_t& signalProcessVertexLink() const;
+      /// Set pointer to a vertex representing the primary interaction point
+      void setSignalProcessVertexLink( const TruthVertexLink_t& link );
+
+      /// Pointer to the incoming primary particle
+      const TruthParticle* primaryParticle() const;
+
+      /// Get the link to the primary particle
+      const TruthParticleLink_t& primaryParticleLink() const;
+
+      /// Set incoming primary particle
+      void setPrimaryParticleLink( const TruthParticleLink_t& pcl);
+
+      /// @}
+
+      /// The type of the object as a simple enumeration
+      virtual Type::ObjectType type() const;
+      
+      /// @name Simple truth meta data properties 
+      /// @{
+
+      uint32_t mcChannelNumber() const;
+      void setMcChannelNumber( uint32_t value );
+
+      const std::vector< std::string >& weightNames() const;
+      void setWeightNames( const std::vector< std::string >& value );
+
+      /// @}
+
+      /// Function making sure that the object is ready for persistification
+      void toPersistent();
+
+   }; // class TruthEvent
+
+} // namespace xAOD
+
+#endif // XAODTRUTH_TRUTHEVENT_H
diff --git a/xAOD/xAODTruth/xAODTruth/TruthEventAuxContainer.h b/xAOD/xAODTruth/xAODTruth/TruthEventAuxContainer.h
new file mode 100644
index 0000000000000000000000000000000000000000..57c6e62ccd9de8455859654f3dbd3d2cc10a71fe
--- /dev/null
+++ b/xAOD/xAODTruth/xAODTruth/TruthEventAuxContainer.h
@@ -0,0 +1,62 @@
+#ifndef XAODTRUTH_TRUTHEVENTAUXCONTAINER_H
+#define XAODTRUTH_TRUTHEVENTAUXCONTAINER_H
+
+// System include(s):
+#include <vector>
+
+// EDM include(s):
+#include "AthLinks/ElementLink.h"
+#include "xAODCore/AuxContainerBase.h"
+
+// Local include(s):
+#include "xAODTruth/TruthParticleContainer.h"
+#include "xAODTruth/TruthVertexContainer.h"
+
+namespace xAOD {
+
+   /// Auxiliary store for the truth vertices
+   ///
+   class TruthEventAuxContainer : public AuxContainerBase {
+
+   public:
+      /// Default constructor
+      TruthEventAuxContainer();
+
+   private:
+      /// @name Links to the interaction particles/vertices
+      /// @{
+      std::vector< ElementLink< TruthVertexContainer > >
+      signalProcessVertexLink;
+      /// @}
+
+      /// @todo Needs to be a map or similar (perhaps two linked vectors?)
+      std::vector< std::vector< float > > weights;
+
+      /// @name Cross sections and errors coming from the generator
+      /// @{
+      std::vector< float > crossSection;
+      std::vector< float > crossSectionError;
+      /// @}
+
+      /// @name Links to the generated/simulated particles/vertices
+      /// @{
+      std::vector< std::vector< ElementLink< TruthParticleContainer > > >
+      truthParticleLinks;
+      std::vector< std::vector< ElementLink< TruthVertexContainer > > >
+      truthVertexLinks;
+      /// @}
+      
+      //Two vectors (of vectors) to store association between weight name and weight
+      //index. No std::map is used for increased read-back speed in ROOT
+      std::vector < std::vector < std::string > > weightNames;
+      std::vector < uint32_t > mcChannelNumber;
+
+   }; // class TruthEventAuxContainer
+
+} // namespace xAOD
+
+// Declare the class's inheritance to StoreGate:
+#include "xAODCore/BaseInfo.h"
+SG_BASE( xAOD::TruthEventAuxContainer, xAOD::AuxContainerBase ); 
+
+#endif // XAODTRUTH_TRUTHEVENTAUXCONTAINER_H
diff --git a/xAOD/xAODTruth/xAODTruth/TruthEventContainer.h b/xAOD/xAODTruth/xAODTruth/TruthEventContainer.h
new file mode 100644
index 0000000000000000000000000000000000000000..eb99877bae90dab0f76ace26b4fff0b3f7371d2b
--- /dev/null
+++ b/xAOD/xAODTruth/xAODTruth/TruthEventContainer.h
@@ -0,0 +1,22 @@
+// -*- C++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: TruthEventContainer_v1.h 622193 2014-10-16 16:08:34Z krasznaa $
+#ifndef XAODTRUTH_TRUTHEVENTCONTAINER_H
+#define XAODTRUTH_TRUTHEVENTCONTAINER_H
+
+// EDM include(s):
+#include "AthContainers/DataVector.h"
+
+// Local include(s):
+#include "xAODTruth/TruthEvent.h"
+
+namespace xAOD {
+   /// Alias
+   typedef DataVector< TruthEvent > TruthEventContainer;
+}
+
+#endif // XAODTRUTH_TRUTHEVENTCONTAINER_H
diff --git a/xAOD/xAODTruth/xAODTruth/TruthParticle.h b/xAOD/xAODTruth/xAODTruth/TruthParticle.h
new file mode 100644
index 0000000000000000000000000000000000000000..3a230b018d4e8ad54afe337312efe6de18b1aa34
--- /dev/null
+++ b/xAOD/xAODTruth/xAODTruth/TruthParticle.h
@@ -0,0 +1,360 @@
+#ifndef XAODTRUTH_TRUTHPARTICLE_H
+#define XAODTRUTH_TRUTHPARTICLE_H
+
+// EDM include(s):
+#include "AthLinks/ElementLink.h"
+#include "AthContainers/DataVector.h"
+
+// xAOD include(s):
+#include "xAODBase/IParticle.h"
+#include "xAODBase/ObjectType.h"
+
+namespace xAOD {
+   class TruthVertex;
+   typedef DataVector< TruthVertex > TruthVertexContainer;
+
+   /// Class describing a truth particle in the MC record
+   ///
+   /// The xAOD truth record mimics the structure of HepMC. Truth particles
+   /// and truth vertices form a decay tree. Where each truth particle is
+   /// connected to a single production and decay vertex. And each vertex is
+   /// connected to one or more incoming, and one or more outgoing particles.
+   ///
+   class TruthParticle : public IParticle {
+
+   public:
+      /// Default constructor
+      TruthParticle();
+
+      /// @name Functions identifying the particle in the MC record
+      /// @{
+
+      /// Set PDG ID code
+      void setPdgId( int pid );
+      /// PDG ID code
+      int pdgId() const;
+      /// Absolute PDG ID code (often useful)
+      int absPdgId() const;
+
+      /// Barcode
+      /// @note Meaning of barcode may change -- be careful!
+      int barcode() const;
+      /// Set barcode
+      void setBarcode( int value );
+
+      /// Status code
+      int status() const;
+      /// Set status code
+      void setStatus( int value );
+
+      /// @}
+
+      /// @name Links to the production and decay vertices
+      /// @{
+
+      /// Check for a production vertex on this particle
+      bool hasProdVtx() const;
+      /// The production vertex of this particle
+      const TruthVertex* prodVtx() const;
+      /// The production vertex link of this particle
+      const ElementLink< TruthVertexContainer >& prodVtxLink() const;
+      /// Set the production vertex of the particle
+      void setProdVtxLink( const ElementLink< TruthVertexContainer >& link );
+
+      /// Check for a decay vertex on this particle
+      bool hasDecayVtx() const;
+      /// The decay vertex of this particle
+      const TruthVertex* decayVtx() const;
+      /// The decay vertex link of this particle
+      const ElementLink< TruthVertexContainer >& decayVtxLink() const;
+      /// Set the decay vertex of the particle
+      void setDecayVtxLink( const ElementLink< TruthVertexContainer >& link );
+
+      /// @}
+
+      /// @name Particle connection / origin / decay information
+      /// @{
+
+      /// Number of parents of this particle
+      size_t nParents() const;
+
+      /// Retrieve the i-th mother (TruthParticle) of this TruthParticle
+      const TruthParticle* parent( size_t i = 0 ) const;
+
+      /// Number of children of this particle
+      size_t nChildren() const;
+
+      /// Retrieve the i-th mother (TruthParticle) of this TruthParticle
+      const TruthParticle* child( size_t i = 0 ) const;
+
+      /// @}
+
+      /// @name Functions implementing the xAOD::IParticle interface
+      /// @{
+
+      /// The transverse momentum (\f$p_T\f$) of the particle
+      virtual double pt() const;
+      /// The pseudorapidity (\f$\eta\f$) of the particle
+      virtual double eta() const;
+      /// The azimuthal angle (\f$\phi\f$) of the particle
+      virtual double phi() const;
+      /// The mass of the particle
+      ///
+      /// Note, not necessarily = \f$E^2-p^2\f$ if not on mass shell.
+      ///
+      virtual double m() const;
+      /// The total energy of the particle
+      virtual double e() const;
+      /// The true rapidity (\f$y\f$) of the particle
+      virtual double rapidity() const;
+
+      /// Definition of the 4-momentum type
+      typedef IParticle::FourMom_t FourMom_t;
+
+      /// The full 4-momentum of the particle
+      ///
+      /// Note that m may not be right, though, if not on mass shell. In which
+      /// case <code>p4().M()</code> will be different from <code>m()</code>.
+      ///
+      virtual const FourMom_t& p4() const;
+
+      /// The type of the object as a simple enumeration
+      virtual Type::ObjectType type() const;
+
+      /// @}
+
+      /// @name 4-momentum accessors specific to truth particles
+      /// @{
+
+      /// The absolute pseudorapidity (\f$|\eta|\f$) of the particle
+      double abseta() const;
+      /// The true absolute rapidity (\f$|y|\f$) of the particle
+      double absrapidity() const;
+
+      /// The x component of the particle's momentum
+      float px() const;
+      /// Set the x component of the particle's momentum
+      void setPx( float value );
+
+      /// The y component of the particle's momentum
+      float py() const;
+      /// Set the y component of the particle's momentum
+      void setPy( float value );
+
+      /// The z component of the particle's momentum
+      float pz() const;
+      /// Set the z component of the particle's momentum
+      void setPz( float value );
+
+      /// Set the energy of the particle
+      void setE( float value );
+
+      /// Also store the mass
+      void setM( float value );
+
+      /// @}
+
+      /// @name Particle species information
+      ///
+      /// Just convenience methods here, since they all just forward to the
+      /// utility functions operating on the PDG particle ID code.
+      ///
+      /// @{
+
+      /// Physical charge
+      double charge() const;
+      /// 3 x the physical charge (so it can be an int for quarks)
+      int threeCharge() const;
+
+      /// Whether the particle is electrically charged
+      bool isCharged() const;
+      /// Whether the particle is electrically neutral
+      bool isNeutral() const;
+
+      /// Whether the particle is a photon
+      bool isPhoton() const;
+      /// Whether the particle is a lepton
+      bool isLepton() const;
+      /// Whether the particle is a charged lepton
+      bool isChLepton() const;
+      /// Whether the particle is an electron (or positron)
+      bool isElectron() const;
+      /// Whether the particle is a muon (or antimuon)
+      bool isMuon() const;
+      /// Whether the particle is a tau (or antitau)
+      bool isTau() const;
+      /// Whether the particle is a neutrino (or antineutrino)
+      bool isNeutrino() const;
+
+      /// Whether the particle is a hadron
+      bool isHadron() const;
+      /// Whether the particle is a meson
+      bool isMeson() const;
+      /// Whether the particle is a baryon
+      bool isBaryon() const;
+
+      /// Whether the particle contains a strange quark (or antiquark)
+      bool hasStrange() const;
+      /// Whether the particle contains a charm quark (or antiquark)
+      bool hasCharm() const;
+      /// Whether the particle contains a bottom quark (or antiquark)
+      bool hasBottom() const;
+
+      /// Determine if the PID is that of a light flavour (not b or c) meson
+      bool isLightMeson() const;
+      /// Determine if the PID is that of a light flavour (not b or c) baryon
+      bool isLightBaryon() const;
+      /// Determine if the PID is that of a light flavour (not b or c) hadron
+      bool isLightHadron() const;
+
+      /// Determine if the PID is that of a heavy flavour (b or c) meson
+      bool isHeavyMeson() const;
+      /// Determine if the PID is that of a heavy flavour (b or c) baryon
+      bool isHeavyBaryon() const;
+      /// Determine if the PID is that of a heavy flavour (b or c) hadron
+      bool isHeavyHadron() const;
+
+      /// Determine if the PID is that of a b-meson.
+      bool isBottomMeson() const;
+      /// Determine if the PID is that of a b-baryon.
+      bool isBottomBaryon() const;
+      /// Determine if the PID is that of a b-hadron.
+      bool isBottomHadron() const;
+
+      /// @brief Determine if the PID is that of a c-meson.
+      ///
+      /// Specifically, the _heaviest_ quark is a c: a B_c is a b-meson and NOT
+      /// a c-meson. Charmonia (closed charm) are counted as c-mesons here.
+      ///
+      bool isCharmMeson() const;
+      /// @brief Determine if the PID is that of a c-baryon.
+      ///
+      /// Specifically, the _heaviest_ quark is a c: a baryon containing a b & c
+      /// is a b-baryon and NOT a c-baryon. To test for the simpler case, just
+      /// use a combination of hasCharm() and isBaryon().
+      ///
+      bool isCharmBaryon() const;
+      /// Determine if the PID is that of a c-hadron.
+      bool isCharmHadron() const;
+
+      /// Determine if the PID is that of a strange meson
+      bool isStrangeMeson() const;
+      /// Determine if the PID is that of a strange baryon
+      bool isStrangeBaryon() const;
+      /// Determine if the PID is that of a strange hadron
+      bool isStrangeHadron() const;
+
+      /// Check if this particle is a quark
+      bool isQuark() const;
+      /// Check if this particle is a parton
+      bool isParton() const;
+      /// Check if this particle is a top quark
+      bool isTop() const;
+      /// Check if this particle is a W boson
+      bool isW() const;
+      /// Check if this particle is a Z boson
+      bool isZ() const;
+      /// Check if this particle is a Higgs boson
+      bool isHiggs() const;
+      /// Check if this particle is a resonant state
+      bool isResonance() const;
+      /// Check if this is a generator specific (non-physical) particle
+      bool isGenSpecific() const;
+
+      /// @}
+
+      /// @name Polarization properties (optional)
+      /// @{
+
+      /// Polarization parameter types
+      enum PolParam {
+         polarizationPhi   = 0, ///< Polarization in (\f$\phi\f$)
+         polarizationTheta = 1  ///< Polarization in (\f$\theta\f$)
+      };
+
+      /// Accessor for polarization parameters
+      ///
+      /// Generic C++ code should use this function to retrieve the polarization
+      /// parameters of a truth particle. Since these parameters are optional,
+      /// the function is designed to tell the user whether the requested
+      /// parameter could be retrieved or not.
+      ///
+      /// @param value The polarization parameter value read from the object
+      /// @param parameter The polarization parameter that we are interested in
+      /// @return <code>true</code> if the retrieval was successful,
+      ///         <code>false</code> if it wasn't
+      ///
+      bool polarizationParameter( float& value, PolParam parameter ) const;
+
+      /// Set method for polarization parameter values
+      ///
+      /// In order to keep the symmetry with the getter function, this setter
+      /// communicates a possible failure in its operation through a return
+      /// value. Setting a polariozation parameter is much less likely to fail
+      /// than retrieving one, but in some situations it may still happen...
+      ///
+      /// @param value The polarization parameter value to set on the object
+      /// @param parameter The polarization parameter type that we want to set
+      /// @return <code>true</code> if the operation was successful, or
+      ///         <code>false</code> if it wasn't
+      ///
+      bool setPolarizationParameter( float value, PolParam parameter );
+
+      /// Convenience accessor for a polariozation parameter.
+      ///
+      /// Throws an exception if the request can't be completed. It should
+      /// mostly be used in PyROOT, as the other form of this function is very
+      /// hard to use there. But one needs to know for sure that the requested
+      /// parameter will exist.
+      ///
+      /// @param parameter The polarion parameter that we are interested in
+      /// @return The value of the polarization parameter requested
+      ///
+      float polarizationPatameter( PolParam parameter ) const;
+
+      /// Single container for full polarization information
+      ///
+      /// It can be used as a convenient way for accessing the polarization of
+      /// the particle with a single call.
+      ///
+      struct Polarization {
+
+         /// Constructor to set (invalid) defaults
+         /// @todo Use C++11 inline member init when allowed
+         Polarization()
+         : phi( -1.0 ), theta( -1.0 ) {}
+
+         /// Check if the stored values are valid
+         bool valid() const {
+            return ( ( phi > 0.0 ) && ( theta > 0.0 ) );
+         }
+
+         float phi;   ///< Polarization in (\f$\phi\f$)
+         float theta; ///< Polarization in (\f$\theta\f$)
+
+      }; // struct Polarization
+
+      /// Retrieve a full Polarization with a single call
+      ///
+      /// @note May have invalid values -- use valid() to check.
+      ///
+      /// @return An object holding the full polarization information
+      ///
+      Polarization polarization() const;
+
+      /// @}
+
+      /// Function making sure that the object is ready for persistification
+      void toPersistent();
+
+   private:
+      /// Cached four momentum
+      mutable FourMom_t m_p4;
+      /// Flag specifying if the four-momentum is cached
+      mutable bool m_p4Cached;
+
+   }; // class TruthParticle
+
+} // namespace xAOD
+
+#endif
diff --git a/xAOD/xAODTruth/xAODTruth/TruthParticleAuxContainer.h b/xAOD/xAODTruth/xAODTruth/TruthParticleAuxContainer.h
new file mode 100644
index 0000000000000000000000000000000000000000..ca8ec36160eec199005d0f664863ae426d4e74cb
--- /dev/null
+++ b/xAOD/xAODTruth/xAODTruth/TruthParticleAuxContainer.h
@@ -0,0 +1,47 @@
+#ifndef XAODTRUTH_TRUTHPARTICLEAUXCONTAINER_H
+#define XAODTRUTH_TRUTHPARTICLEAUXCONTAINER_H
+
+#include <vector>
+
+#include "AthLinks/ElementLink.h"
+#include "xAODCore/AuxContainerBase.h"
+
+#include "xAODTruth/TruthParticleContainer.h"
+#include "xAODTruth/TruthVertexContainer.h"
+
+namespace xAOD {
+
+
+  /// Auxiliary store for the truth vertices
+  ///
+  /// @author Andy Buckley <Andy.Buckey@cern.ch>
+  /// @author Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch>
+  /// @author Jovan Mitrevski <Jovan.Mitrevski@cern.h>
+  ///
+  class TruthParticleAuxContainer : public AuxContainerBase {
+
+  public:
+    /// Default constructor
+    TruthParticleAuxContainer();
+
+  private:
+    std::vector< int > pdgId;
+    std::vector< int > barcode;
+    std::vector< int > status;
+    std::vector< ElementLink< TruthVertexContainer > > prodVtxLink;
+    std::vector< ElementLink< TruthVertexContainer > > decayVtxLink;
+    std::vector< float > px;
+    std::vector< float > py;
+    std::vector< float > pz;
+    std::vector< float > e;
+    std::vector< float > m; // needed since not necessarily on shell
+
+  }; // class TruthParticleAuxContainer
+
+} // namespace xAOD
+
+// Declare a CLID for the class
+#include "xAODCore/CLASS_DEF.h"
+CLASS_DEF( xAOD::TruthParticleAuxContainer, 1107340896, 1 )
+
+#endif // XAODTRUTH_TRUTHPARTICLEAUXCONTAINER_H
diff --git a/xAOD/xAODTruth/xAODTruth/TruthParticleContainer.h b/xAOD/xAODTruth/xAODTruth/TruthParticleContainer.h
new file mode 100644
index 0000000000000000000000000000000000000000..89dc05cb0e73d2cf5914a7a11b2858d17d365af4
--- /dev/null
+++ b/xAOD/xAODTruth/xAODTruth/TruthParticleContainer.h
@@ -0,0 +1,26 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: TruthParticleContainer.h 622193 2014-10-16 16:08:34Z krasznaa $
+#ifndef XAODTRUTH_TRUTHPARTICLECONTAINER_H
+#define XAODTRUTH_TRUTHPARTICLECONTAINER_H
+
+// Local include(s):
+#include "xAODTruth/TruthParticle.h"
+// EDM include(s):
+#include "AthContainers/DataVector.h"
+
+
+namespace xAOD {
+   // Alias
+   typedef DataVector< TruthParticle > TruthParticleContainer;
+}
+
+// Declare a CLID for the class for Athena:
+#include "xAODCore/CLASS_DEF.h"
+CLASS_DEF( xAOD::TruthParticleContainer, 1237340765, 1 )
+
+#endif // XAODTRUTH_TRUTHPARTICLECONTAINER_H
diff --git a/xAOD/xAODTruth/xAODTruth/TruthVertex.h b/xAOD/xAODTruth/xAODTruth/TruthVertex.h
new file mode 100644
index 0000000000000000000000000000000000000000..6f24fbd975800bc3708c9256dccc1f32c931276e
--- /dev/null
+++ b/xAOD/xAODTruth/xAODTruth/TruthVertex.h
@@ -0,0 +1,142 @@
+#ifndef XAODTRUTH_TRUTHVERTEX_H
+#define XAODTRUTH_TRUTHVERTEX_H
+
+// ROOT include(s):
+#include <TLorentzVector.h>
+
+// EDM include(s):
+#include "AthContainers/AuxElement.h"
+#include "AthLinks/ElementLink.h"
+
+// xAOD include(s):
+#include "xAODBase/ObjectType.h"
+
+// Local include(s):
+#include "xAODTruth/TruthParticleContainer.h"
+
+namespace xAOD {
+
+   /// Class describing a truth vertex in the MC record
+   ///
+   /// The xAOD truth record mimics the structure of HepMC. Truth particles
+   /// and truth vertices form a decay tree. Where each truth particle is
+   /// connected to a single production and decay vertex. And each vertex is
+   /// connected to one or more incoming, and one or more outgoing particles.
+   ///
+   /// @author Andy Buckley <Andy.Buckley@cern.ch>
+   ///
+   /// $Revision: 624338 $
+   /// $Date: 2014-10-27 16:08:55 +0100 (Mon, 27 Oct 2014) $
+   ///
+   class TruthVertex : public SG::AuxElement {
+
+   public:
+      /// Default constructor
+      TruthVertex();
+
+      /// @name Functions identifying the vertex in the MC record
+      /// @{
+
+      /// Set vertex ID code
+      void setId( int value );
+      /// Vertex ID code
+      int id() const;
+
+      /// Set barcode
+      void setBarcode( int value );
+      /// Barcode
+      int barcode() const;
+
+      /// @}
+
+      /// @name Links to the particles associated with this vertex
+      /// @{
+
+      /// Type of one truth particle link
+      typedef ElementLink< TruthParticleContainer > TPLink_t;
+      /// Type used to save the links to incoming and outgoing particles
+      typedef std::vector< TPLink_t > TPLinks_t;
+
+      /// Get all the incoming particles
+      const TPLinks_t& incomingParticleLinks() const;
+      /// Set all the incoming particles
+      void setIncomingParticleLinks( const TPLinks_t& links );
+      /// Get the number of incoming particles
+      size_t nIncomingParticles() const;
+      /// Get one of the incoming particles
+      const TruthParticle* incomingParticle( size_t index ) const;
+      /// Add one incoming particle
+      void addIncomingParticleLink( const TPLink_t& link );
+      /// Remove all incoming particles
+      void clearIncomingParticleLinks();
+
+      /// Get all the outgoing particles
+      const TPLinks_t& outgoingParticleLinks() const;
+      /// Set all the outgoing particles
+      void setOutgoingParticleLinks( const TPLinks_t& links );
+      /// Get the number of outgoing particles
+      size_t nOutgoingParticles() const;
+      /// Get one of the outgoing particles
+      const TruthParticle* outgoingParticle( size_t index ) const;
+      /// Add one outgoing particle
+      void addOutgoingParticleLink( const TPLink_t& link );
+      /// Remove all outgoing particles
+      void clearOutgoingParticleLinks();
+
+      /// @}
+
+      /// @name Vertex position functions
+      /// @{
+
+      /// Vertex x displacement
+      float x() const;
+      /// Set the x displacement of the vertex
+      void setX( float value );
+
+      /// Vertex y displacement
+      float y() const;
+      /// Set the y displacement of the vertex
+      void setY( float value );
+
+      /// Vertex longitudinal distance along the beam line form the origin
+      float z() const;
+      /// Set the vertex's longitudinal distance from the origin
+      void setZ( float value );
+
+      /// Vertex transverse distance from the beam line
+      float perp() const;
+      /// Vertex pseudorapidity
+      float eta() const;
+      /// Vertex azimuthal angle
+      float phi() const;
+
+      /// Vertex time
+      float t() const;
+      /// Set the vertex time
+      void setT( float value );
+
+      /// The 4-vector type
+      typedef TLorentzVector FourVec_t;
+
+      /// The full 4-vector of the vertex
+      const FourVec_t& v4() const;
+
+      /// @}
+
+      /// The type of the object as a simple enumeration
+      Type::ObjectType type() const;
+
+      /// Function making sure that the object is ready for persistification
+      void toPersistent();
+
+   private:
+      /// Cached four vector
+      mutable FourVec_t m_v4;
+      /// Flag showing whether the four-vector is cached
+      mutable bool m_v4Cached;
+
+   }; // class TruthVertex
+
+} // namespace xAOD
+
+#endif
diff --git a/xAOD/xAODTruth/xAODTruth/TruthVertexAuxContainer.h b/xAOD/xAODTruth/xAODTruth/TruthVertexAuxContainer.h
new file mode 100644
index 0000000000000000000000000000000000000000..b6098f4323eeee6a834f33495c00133a942571ea
--- /dev/null
+++ b/xAOD/xAODTruth/xAODTruth/TruthVertexAuxContainer.h
@@ -0,0 +1,50 @@
+#ifndef XAODTRUTH_TRUTHVERTEXAUXCONTAINER_H
+#define XAODTRUTH_TRUTHVERTEXAUXCONTAINER_H
+
+// System include(s):
+#include <vector>
+
+// EDM include(s):
+#include "AthLinks/ElementLink.h"
+#include "xAODCore/AuxContainerBase.h"
+
+// Local include(s):
+#include "xAODTruth/TruthParticleContainer.h"
+
+namespace xAOD {
+
+  /// Auxiliary store for the truth vertices
+  ///
+  /// @author Andy Buckley <Andy.Buckey@cern.ch>
+  /// @author Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch>
+  ///
+  /// $Revision: 624338 $
+  /// $Date: 2014-10-27 16:08:55 +0100 (Mon, 27 Oct 2014) $
+  ///
+  class TruthVertexAuxContainer : public AuxContainerBase {
+
+  public:
+    /// Default constructor
+    TruthVertexAuxContainer();
+
+  private:
+    std::vector< int > id;
+    std::vector< int > barcode;
+    std::vector< std::vector< ElementLink< TruthParticleContainer > > >
+    incomingParticleLinks;
+    std::vector< std::vector< ElementLink< TruthParticleContainer > > >
+    outgoingParticleLinks;
+    std::vector< float > x;
+    std::vector< float > y;
+    std::vector< float > z;
+    std::vector< float > t;
+
+  }; // class TruthVertexAuxContainer
+
+} // namespace xAOD
+
+// Declare a CLID for the class
+#include "xAODCore/CLASS_DEF.h"
+CLASS_DEF( xAOD::TruthVertexAuxContainer, 1254939514, 1 )
+
+#endif // XAODTRUTH_TRUTHVERTEXAUXCONTAINER_H
diff --git a/xAOD/xAODTruth/xAODTruth/TruthVertexContainer.h b/xAOD/xAODTruth/xAODTruth/TruthVertexContainer.h
new file mode 100644
index 0000000000000000000000000000000000000000..464ffd7766ce27c26973140b316cb2d0682f7463
--- /dev/null
+++ b/xAOD/xAODTruth/xAODTruth/TruthVertexContainer.h
@@ -0,0 +1,25 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: TruthVertexContainer.h 622193 2014-10-16 16:08:34Z krasznaa $
+#ifndef XAODTRUTH_TRUTHVERTEXCONTAINER_H
+#define XAODTRUTH_TRUTHVERTEXCONTAINER_H
+
+// Local include(s):
+#include "xAODTruth/TruthVertex.h"
+// EDM include(s):
+#include "AthContainers/DataVector.h"
+
+namespace xAOD {
+   // Alias
+   typedef DataVector< TruthVertex > TruthVertexContainer;
+}
+
+// Declare a CLID for the class for Athena:
+#include "xAODCore/CLASS_DEF.h"
+CLASS_DEF( xAOD::TruthVertexContainer, 1239726567, 1 )
+
+#endif // XAODTRUTH_TRUTHVERTEXCONTAINER_H
diff --git a/xAOD/xAODTruth/xAODTruth/selection.xml b/xAOD/xAODTruth/xAODTruth/selection.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f1ab8990a0e2c13bf7ef2154c6f593a9368805aa
--- /dev/null
+++ b/xAOD/xAODTruth/xAODTruth/selection.xml
@@ -0,0 +1,66 @@
+<!-- $Id: selection.xml 670153 2015-05-27 11:42:29Z tbisanz $ -->
+<lcgdict>
+
+  <!-- The TruthParticle class(es): -->
+  <class name="xAOD::TruthParticle" >
+    <field name="m_p4" transient="true" />
+    <field name="m_p4Cached" transient="true" />
+  </class>
+  <read sourceClass="xAOD::TruthParticle" version="[1-]"
+        targetClass="xAOD::TruthParticle" source="" target="m_p4Cached" >
+    <![CDATA[
+       m_p4Cached = false;
+    ]]>
+  </read>
+  <class name="xAOD::TruthParticle::Polarization" />
+
+  <!-- The TruthVertex class: -->
+  <class name="xAOD::TruthVertex" >
+    <field name="m_v4" transient="true" />
+    <field name="m_v4Cached" transient="true" />
+  </class>
+  <read sourceClass="xAOD::TruthVertex" version="[1-]"
+        targetClass="xAOD::TruthVertex" source="" target="m_v4Cached" >
+    <![CDATA[
+       m_v4Cached = false;
+    ]]>
+  </read>
+
+  <!-- The TruthEvent class(es): -->
+  <class name="xAOD::TruthEvent" />
+  <class name="xAOD::TruthEvent::PdfInfo" />
+  <class name="xAOD::TruthMetaData" />
+
+  <!-- The persistent classes: -->
+  <class name="xAOD::TruthParticleContainer"
+         id="58F98A16-E465-4CA5-A099-73033206D8E3" />
+  <class name="xAOD::TruthVertexContainer"
+         id="5FBAE0AB-09F7-4B6C-B066-0A003FC38ECF" />
+  <class name="xAOD::TruthEventContainer"
+         id="6290F297-F529-40EE-9FE5-1C577678306D" />
+
+  <class name="xAOD::TruthParticleAuxContainer"
+         id="BA8FA08F-8DD6-420D-97D5-8B54EABECD65" />
+  <class name="xAOD::TruthVertexAuxContainer"
+         id="B6BD3B02-C411-4EB9-903F-5B099D3B1A3E" />
+  <class name="xAOD::TruthEventAuxContainer"
+         id="1B945EFD-4F7D-4BDD-9FB1-6FB975315961" />
+
+  <!-- Smart pointers for TruthParticle: -->
+  <class name="DataLink<xAOD::TruthParticleContainer>" />
+  <class name="std::vector<DataLink<xAOD::TruthParticleContainer> >" />
+  <class name="ElementLink<xAOD::TruthParticleContainer>" />
+  <class name="std::vector<ElementLink<xAOD::TruthParticleContainer> >" />
+  <class name="std::vector<std::vector<ElementLink<xAOD::TruthParticleContainer> > >" />
+
+  <!-- Smart pointers for TruthVertex: -->
+  <class name="DataLink<xAOD::TruthVertexContainer>" />
+  <class name="std::vector<DataLink<xAOD::TruthVertexContainer> >" />
+  <class name="ElementLink<xAOD::TruthVertexContainer>" />
+  <class name="std::vector<ElementLink<xAOD::TruthVertexContainer> >" />
+  <class name="std::vector<std::vector<ElementLink<xAOD::TruthVertexContainer> > >" />
+
+  <!-- The helper functions: -->
+  <function pattern="xAOD::TruthHelpers::*" />
+
+</lcgdict>
diff --git a/xAOD/xAODTruth/xAODTruth/xAODTruthDict.h b/xAOD/xAODTruth/xAODTruth/xAODTruthDict.h
new file mode 100644
index 0000000000000000000000000000000000000000..e7aec67bad32a4ef53afa3f23e493bc4ad0696a7
--- /dev/null
+++ b/xAOD/xAODTruth/xAODTruth/xAODTruthDict.h
@@ -0,0 +1,41 @@
+#ifndef XAODTRUTH_XAODTRUTHDICT_H
+#define XAODTRUTH_XAODTRUTHDICT_H
+
+// System include(s):
+#include <vector>
+
+// EDM include(s):
+#include "AthLinks/DataLink.h"
+#include "AthLinks/ElementLink.h"
+
+// Local include(s):
+#include "xAODTruth/TruthParticleContainer.h"
+#include "xAODTruth/TruthParticleAuxContainer.h"
+#include "xAODTruth/TruthVertexContainer.h"
+#include "xAODTruth/TruthVertexAuxContainer.h"
+#include "xAODTruth/TruthEventContainer.h"
+#include "xAODTruth/TruthEventAuxContainer.h"
+#include "xAODTruth/xAODTruthHelpers.h"
+
+namespace {
+   struct GCCXML_DUMMY_INSTANTIATION_XAODTRUTH {
+      // The DataVector types:
+      xAOD::TruthParticleContainer    c1;
+      xAOD::TruthVertexContainer      c2;
+      xAOD::TruthEventContainer       c3;
+
+      // The smart pointer types:
+      DataLink< xAOD::TruthParticleContainer > dl1;
+      std::vector< DataLink< xAOD::TruthParticleContainer > > dl2;
+      DataLink< xAOD::TruthVertexContainer > dl3;
+      std::vector< DataLink< xAOD::TruthVertexContainer > > dl4;
+      ElementLink< xAOD::TruthParticleContainer > el1;
+      std::vector< ElementLink< xAOD::TruthParticleContainer > > el2;
+      std::vector< std::vector< ElementLink< xAOD::TruthParticleContainer > > > el3;
+      ElementLink< xAOD::TruthVertexContainer > el4;
+      std::vector< ElementLink< xAOD::TruthVertexContainer > > el5;
+      std::vector< std::vector< ElementLink< xAOD::TruthVertexContainer > > > el6;
+   };
+}
+
+#endif // XAODTRUTH_XAODTRUTHDICT_H
diff --git a/xAOD/xAODTruth/xAODTruth/xAODTruthHelpers.h b/xAOD/xAODTruth/xAODTruth/xAODTruthHelpers.h
new file mode 100644
index 0000000000000000000000000000000000000000..cb8ca9cdb3ffee257b1af09c0d2427f8d177e8ff
--- /dev/null
+++ b/xAOD/xAODTruth/xAODTruth/xAODTruthHelpers.h
@@ -0,0 +1,37 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: xAODTruthHelpers.h 668406 2015-05-19 15:32:15Z krasznaa $
+#ifndef XAODTRUTH_XAODTRUTHHELPERS_H
+#define XAODTRUTH_XAODTRUTHHELPERS_H
+
+// Local include(s):
+#include "xAODTruth/TruthParticle.h"
+
+namespace xAOD {
+
+   // Forward declaration(s):
+   class IParticle;
+
+   /// Dedicated namespace for the helper functions
+   namespace TruthHelpers {
+
+      /// Return the truthParticle associated to the given IParticle (if any)
+      const TruthParticle* getTruthParticle( const xAOD::IParticle& p );
+
+      /// Return the particle's truth type (as defined by the MC Truth
+      /// Classifier)
+      int getParticleTruthType( const xAOD::IParticle& p );
+
+      /// Return the particle's truth origin (as defined by the MC Truth
+      /// Classifier)
+      int getParticleTruthOrigin( const xAOD::IParticle& p );
+
+   } // namespace TruthHelpers
+
+} // namespace xAOD
+
+#endif // XAODTRUTH_XAODTRUTHHELPERS_H