diff --git a/Control/AthContainersRoot/AthContainersRoot/AthContainersRootTestDict.h b/Control/AthContainersRoot/AthContainersRoot/AthContainersRootTestDict.h
new file mode 100644
index 0000000000000000000000000000000000000000..4dc5747140c8474150a5af3fbf5b1dfcc223e5cc
--- /dev/null
+++ b/Control/AthContainersRoot/AthContainersRoot/AthContainersRootTestDict.h
@@ -0,0 +1,39 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file AthContainersRoot/AthContainersRootTestDict.h
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Oct, 2016
+ * @brief For AthContainersRoot unit tests.
+ */
+
+
+#ifndef ATHCONTAINERSROOT_ATHCONTAINERSROOTTESTDICT_H
+#define ATHCONTAINERSROOT_ATHCONTAINERSROOTTESTDICT_H
+
+
+#include "AthContainers/tools/AuxTypeVectorFactory.h"
+
+
+namespace AthContainersRootTest {
+
+
+class Foo {};
+class Bar {};
+class Baz {};
+
+
+} // namespace AthContainersRootTest
+
+
+namespace SG {
+template class AuxTypeVectorFactory<AthContainersRootTest::Foo>;
+}
+
+
+#endif // not ATHCONTAINERSROOT_ATHCONTAINERSROOTTESTDICT_H
diff --git a/Control/AthContainersRoot/AthContainersRoot/AuxStoreRoot.h b/Control/AthContainersRoot/AthContainersRoot/AuxStoreRoot.h
new file mode 100644
index 0000000000000000000000000000000000000000..93e4749b8047862bc80ed0a3a5dd9b2d3b44661e
--- /dev/null
+++ b/Control/AthContainersRoot/AthContainersRoot/AuxStoreRoot.h
@@ -0,0 +1,215 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file AthContainersRoot/AuxStoreRoot.h
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Oct, 2016
+ * @brief Base class for root-based dynamic auxiliary store.
+ */
+
+
+#ifndef ATHCONTAINERSROOT_AUXSTOREROOT_H
+#define ATHCONTAINERSROOT_AUXSTOREROOT_H
+
+
+#include "AthContainers/AuxStoreInternal.h"
+#include "AthContainersRoot/IAuxBranches.h"
+class TClass;
+
+
+namespace SG {
+
+
+/**
+ * @brief Base class for root-based dynamic auxiliary store.
+ *
+ * This class is used to implement the dynamic part of an auxiliary store
+ * where the data are stored in root.  It is the result of factoring
+ * common code from AuxStoreAPR (pool) and AuxStoreARA (AthenaROOTAccess).
+ *
+ * The class is based on @c AuxStoreInternal.  Derived classes must implement
+ * two methods: @c resolveAuxID, to assign an auxiliary ID to a branch,
+ * and @c doReadData to actually read data from the file into the store.
+ * The derived class constructor should also call @c fillAuxIDs
+ * to complete initialization.
+ *
+ * Communication is via an instance of @c IAuxBranches, which provides
+ * interfaces to enumerate the dynamic branches and to read data.
+ */
+class AuxStoreRoot
+  : public SG::AuxStoreInternal
+{
+public:
+  /**
+   * @brief Constructor.
+   * @param container Representation of the object for which we're reading.
+   * @param entry The entry in the root tree to read.
+   * @param standalone If true, this is a standalone auxiliary object.
+   */
+  AuxStoreRoot (IAuxBranches& container, long long entry, bool standalone);
+
+
+  /// Destructor.
+  virtual ~AuxStoreRoot() {}
+
+
+  /// implementation of the IAuxStore interface
+
+  /**
+   * @brief Return the data vector for one aux data item
+   * @param auxid The identifier of the desired aux data item.
+   *
+   * Each aux data item is stored as a vector, with one entry
+   * per entry in the owning container.  This returns a pointer
+   * to the start of the vector.
+   *
+   * This should return 0 if the item doesn't exist.
+   */
+  virtual const void*                getData(SG::auxid_t auxid) const override;
+
+
+  /**
+   * @brief Return the data vector for one aux data item
+   * @param auxid The identifier of the desired aux data item.
+   * @param size The current size of the container (in case the data item
+   *             does not already exist).
+   * @param capacity The current capacity of the container (in case
+   *                 the data item does not already exist).
+   *
+   * Each aux data item is stored as a vector, with one entry
+   * per entry in the owning container.  This returns a pointer
+   * to the start of the vector.
+   *
+   * If the data item does not exist, it should be created and initialized
+   * to default values.  @c size and @c capacity give the size for the
+   * new aux data item vector.
+   *
+   * If the container is locked, throw an exception.
+   */
+  virtual void*
+  getData(SG::auxid_t auxid, size_t size, size_t capacity) override;
+
+
+  /**
+   * @brief Return the data vector for one aux data decoration item.
+   * @param auxid The identifier of the desired aux data item.
+   * @param size The current size of the container (in case the data item
+   *             does not already exist).
+   * @param capacity The current capacity of the container (in case
+   *                 the data item does not already exist).
+   */
+  virtual void*
+  getDecoration (SG::auxid_t auxid, size_t size, size_t capacity) override;
+
+
+  /// Implementation of the IAuxStoreIO interface
+
+  
+  /**
+   * @brief Return a pointer to the data to be stored for one aux data item.
+   * @param auxid The identifier of the desired aux data item.
+   *
+   * This will usually be a pointer to a @c std::vector; however, it may
+   * be something different for a standalone object.
+   *
+   * Returns 0 and reports an error if the requested aux data item
+   * does not exist.
+   */
+  virtual const void* getIOData(SG::auxid_t auxid) const override;
+
+
+  /// Methods to be implemented by derived classes.
+
+
+  /**
+   * @brief Determine auxiliary ID for a branch.
+   * @param container Representation of the object being read.
+   * @param ti @c type_info for the element, or nullptr.
+   * @param name Name of the attribute.
+   * @param elemTypeName Name of the type of this attribute.
+   * @param branchTypeName Name of the type of the object stored
+   *        in the branch.  Should be the same as @c elemTypeName
+   *        for standalone objects.
+   */
+  virtual SG::auxid_t resolveAuxID (IAuxBranches& container,
+                                    const std::type_info* ti,
+                                    const std::string& name,
+                                    const std::string& elemTypeName,
+                                    const std::string& branchTypeName) = 0;
+
+
+  /**
+   * @brief Actually read data into the attribute.
+   * @param container Representation of the object being read.
+   * @param auxid ID of the variable being read.
+   * @param branch Root branch being read.
+   * @param cl Class of the data stored in the branch.
+   * @param vector Pointer to the I/O data for this attribute.
+   *               (Will be a vector for the normal case, the element
+   *               itself for standalone objects.)
+   * @param entry Entry being read in the TTree.
+   *
+   * Returns true on success, false on failure.
+   */
+  virtual bool doReadData (IAuxBranches& container,
+                           SG::auxid_t auxid,
+                           TBranch& branch,
+                           TClass* cl,
+                           void* vector,
+                           long long entry) = 0;
+
+
+
+protected:
+  /// Methods to be called by derived classes.
+
+  /**
+   * @brief Derived classes should call this from their constructor
+   *        to complete initialization.
+   *
+   * Creates the auxid set from the list of branches.
+   * This cannot be done from the @c AuxStoreRoot constructor as it needs
+   * to call the @c resolveAuxID virtual method.
+   */  
+  void fillAuxIDs();
+
+
+  /**
+   * @brief Change the TTree entry being read.
+   * @param entry New entry being read.
+   */
+  void setEntry (long long entry);
+
+     
+private:
+  /**
+   * @brief Read data from ROOT and store it in the internal vector.
+   *
+   * Returns true on success, false on failure.
+   */
+  bool readData(SG::auxid_t auxid);
+
+
+  /// Current TTree entry being read.
+  long long          m_entry;
+
+  /// Representation of the object being read.
+  IAuxBranches&      m_container;
+
+  
+  /// Mutex used to synchronize modifications to the cache vector.
+  typedef AthContainers_detail::mutex mutex_t;
+  typedef AthContainers_detail::lock_guard<mutex_t> guard_t;
+  mutable mutex_t m_mutex;
+};
+
+
+} // namespace SG
+
+
+#endif // not ATHCONTAINERSROOT_AUXSTOREROOT_H
diff --git a/Control/AthContainersRoot/AthContainersRoot/IAuxBranches.h b/Control/AthContainersRoot/AthContainersRoot/IAuxBranches.h
new file mode 100644
index 0000000000000000000000000000000000000000..91fb068eaf2ed2adfed540e73b46aa854a9d3b2b
--- /dev/null
+++ b/Control/AthContainersRoot/AthContainersRoot/IAuxBranches.h
@@ -0,0 +1,50 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file AthContainersRoot/IAuxBranches.h
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Oct, 2016
+ * @brief 
+ */
+
+
+#ifndef ATHCONTAINERSROOT_IAUXBRANCHES_H
+#define ATHCONTAINERSROOT_IAUXBRANCHES_H
+
+
+#include "AthContainersInterfaces/AuxTypes.h"
+#include "GaudiKernel/StatusCode.h"
+#include <utility>
+#include <string>
+#include <vector>
+#include <typeinfo>
+class TBranch;
+
+
+namespace SG {
+
+
+class IAuxBranches
+{
+public:
+  virtual ~IAuxBranches() {}
+
+  virtual const std::string& getName() const = 0;
+  typedef std::pair<std::string, TBranch*> auxpair_t;
+  virtual std::vector<auxpair_t> auxBranches() const = 0;
+  virtual TBranch* findAuxBranch (SG::auxid_t auxid) = 0;
+  virtual StatusCode readAuxBranch (TBranch& br, void* p, long long entry) = 0;
+  virtual StatusCode readAuxBranch (TBranch& br, void* p,
+                                    const std::type_info& ti, long long entry) = 0;
+};
+
+
+} // namespace SG
+
+
+#endif // not ATHCONTAINERSROOT_IAUXBRANCHES_H
diff --git a/Control/AthContainersRoot/AthContainersRoot/RootAuxVectorFactory.h b/Control/AthContainersRoot/AthContainersRoot/RootAuxVectorFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..aa19a699cf608f98c3f7d4fbe7c04c8922a2835c
--- /dev/null
+++ b/Control/AthContainersRoot/AthContainersRoot/RootAuxVectorFactory.h
@@ -0,0 +1,361 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file AthContainersRoot/RootAuxVectorFactory.h
+ * @author scott snyder <snyder@bnl.gov>
+ * @date May, 2014
+ * @brief Dynamic implementation of @c IAuxVectorFactory,
+ *        relying on root's vector proxy.
+ */
+
+
+#ifndef ATHCONTAINERSROOT_ROOTAUXVECTORFACTORY_H
+#define ATHCONTAINERSROOT_ROOTAUXVECTORFACTORY_H
+
+
+#include "AthContainersInterfaces/IAuxTypeVectorFactory.h"
+#include "AthContainersInterfaces/IAuxTypeVector.h"
+#include "RootUtils/Type.h"
+
+
+class TClass;
+class TVirtualCollectionProxy;
+
+
+namespace SG {
+
+
+class RootAuxVectorFactory;
+
+
+/**
+ * @brief Dynamic implementation of @c IAuxTypeVector,
+ *        relying on root vector proxy.
+ *
+ * This is used for the case when we need to manipulate an aux data vector
+ * present in an input data file but we have neither a proper template
+ * instantiation for the factory (because the variable was never explicitly
+ * referenced), nor can we find a dictionary entry for the factory.j
+ *
+ * This implementation works by relying entirely on the root
+ * dictionary information.
+ */
+class RootAuxVector
+  : public SG::IAuxTypeVector
+{
+public:
+  /**
+   * @brief Constructor.  Makes a new vector.
+   * @param factory The factory object for this type.
+   * @param size Initial size of the new vector.
+   * @param capacity Initial capacity of the new vector.
+   */
+  RootAuxVector (const RootAuxVectorFactory* factory,
+                 size_t size,
+                 size_t capacity);
+
+
+  /**
+   * @brief Constructor, from a pointer to a vector object.
+   * @param data The vector object.
+   * @param isPacked If true, @c data is a @c PackedContainer.
+   * @param ownFlag If true, then take ownership of @c data.
+   *
+   * If the element type is T, then @c data should be a pointer
+   * to a std::vector<T> object, which was obtained with @c new.
+   *
+   * This version does not support packed containers, so @c isPacked
+   * must be false.
+   */
+  RootAuxVector (const RootAuxVectorFactory* factory,
+                 void* data,
+                 bool isPacked,
+                 bool ownFlag);
+
+
+  
+  /**
+   * @brief Copy constructor.
+   * @param other The vector to copy.
+   */
+  RootAuxVector (const RootAuxVector& other);
+
+
+  // Disallow assignment.
+  RootAuxVector& operator= (const RootAuxVector&) = delete;
+
+
+  /**
+   * @brief Destructor.
+   *
+   * This will free the vector data.
+   */
+  virtual ~RootAuxVector() override;
+
+
+  /**
+   * @brief Make a copy of this vector.
+   */
+  virtual SG::IAuxTypeVector* clone() const override;
+
+
+  /**
+   * @brief Return a pointer to the start of the vector's data.
+   */
+  virtual void* toPtr() override;
+
+
+  /**
+   * @brief Return a pointer to the overall object.
+   */
+  virtual void* toVector() override;
+
+
+
+  /**
+   * @brief Return the size of the vector.
+   */
+  virtual size_t size() const override;
+
+
+  /**
+   * @brief Change the size of the vector.
+   * @param sz The new vector size.
+   */
+  virtual void resize (size_t sz) override;
+
+
+  /**
+   * @brief Change the capacity of the vector.
+   * @param sz The new vector capacity.
+   */
+  virtual void reserve (size_t sz) override;
+
+
+  /**
+   * @brief Shift the elements of the vector.
+   * @param pos The starting index for the shift.
+   * @param offs The (signed) amount of the shift.
+   *
+   * This operation shifts the elements in the vectors for all
+   * aux data items, to implement an insertion or deletion.
+   * @c offs may be either positive or negative.
+   *
+   * If @c offs is positive, then the container is growing.
+   * The container size should be increased by @c offs,
+   * the element at @c pos moved to @c pos + @c offs,
+   * and similarly for following elements.
+   * The elements between @c pos and @c pos + @c offs should
+   * be default-initialized.
+   *
+   * If @c offs is negative, then the container is shrinking.
+   * The element at @c pos should be moved to @c pos + @c offs,
+   * and similarly for following elements.
+   * The container should then be shrunk by @c -offs elements
+   * (running destructors as appropriate).
+   */
+  virtual void shift (size_t pos, ptrdiff_t offs) override;
+
+
+  /**
+   * @brief Return the type of the complete object to be saved.
+   *
+   * For example, if the object is a @c std::vector, then we return
+   * the @c type_info of the vector.  But if we're holding
+   * a @c PackedContainer, then we return the @c type_info of the
+   * @c PackedContainer.
+   *
+   * Can return null if the operation is not supported.  In that case,
+   * I/O will use the type found from the variable registry.
+   */
+  virtual const std::type_info* objType() const override;
+
+
+private:
+  /// Pointer back to the factory class for this type.
+  const RootAuxVectorFactory* m_factory;
+
+  /// The collection proxy for the vector.
+  TVirtualCollectionProxy* m_proxy;
+
+  /// Pointer to the overall object itself.
+  void* m_obj;
+
+  /// Pointer to the vector object itself.
+  void* m_vec;
+
+  /// Should be delete the vector object?
+  bool m_ownFlag;
+};
+
+
+/**
+ * @brief Dynamic implementation of @c IAuxVectorFactory,
+ *        relying on root's vector proxy.
+ *
+ * This is used for the case when we need to manipulate an aux data vector
+ * present in an input data file but we have neither a proper template
+ * instantiation for the factory (because the variable was never explicitly
+ * referenced), nor can we find a dictionary entry for the factory.j
+ *
+ * This implementation works by relying entirely on the root
+ * dictionary information.
+ *
+ * We may either be dealing directly with an STL vector class, or with
+ * embedded in another class (as for PackedContainer).  Here, @a vecClass
+ * is the class of the STL vector and @a objClass is the overall object
+ * class.  In the case of a direct STL vector, these are identical.
+ */
+class RootAuxVectorFactory
+  : public SG::IAuxTypeVectorFactory
+{
+public:
+  /**
+   * @brief Constructor.
+   * @param vecClass The @c TClass for the vector object.
+   */
+  RootAuxVectorFactory (TClass* objClass);
+
+
+  /**
+   * @brief Destructor.
+   */
+  virtual ~RootAuxVectorFactory() override;
+
+
+  /**
+   * @brief Return the ROOT type wrapper.
+   */
+  const RootUtils::Type& rootType() const { return m_type; }
+
+
+  /**
+   * @brief Return the @c TClass for the overall object.
+   */
+  TClass* objClass() const { return m_objClass; }
+
+
+  /**
+   * @brief Return the @c TClass for the @c std::vector.
+   */
+  TClass* vecClass() const { return m_vecClass; }
+
+
+  /**
+   * @brief Return the offset of the vector within the object.
+   */
+  size_t offset() const { return m_offset; }
+
+
+  /**
+   * @brief Create a vector object of this type.
+   * @param size Initial size of the new vector.
+   * @param capacity Initial capacity of the new vector.
+   *
+   * Returns a newly-allocated object.
+   * FIXME: Should return a unique_ptr.
+   */
+  virtual SG::IAuxTypeVector* create (size_t size, size_t capacity) const
+    override;
+
+
+  /**
+   * @brief Create a vector object of this type from a data blob.
+   * @param data The vector object.
+   * @param isPacked If true, @c data is a @c PackedContainer.
+   * @param ownFlag If true, the newly-created IAuxTypeVector object
+   *                will take ownership of @c data.
+   *
+   * If the element type is T, then @c data should be a pointer
+   * to a std::vector<T> object, which was obtained with @c new.
+   *
+   * This version does not support packed containers, so @c isPacked
+   * must be false.
+   *
+   * Returns a newly-allocated object.
+   * FIXME: Should return a unique_ptr.
+   */
+  virtual SG::IAuxTypeVector* createFromData (void* data,
+                                              bool isPacked,
+                                              bool ownFlag) const
+    override;
+
+
+  /**
+   * @brief Copy an element between vectors.
+   * @param dst Pointer to the start of the destination vector's data.
+   * @param dst_index Index of destination element in the vector.
+   * @param src Pointer to the start of the source vector's data.
+   * @param src_index Index of source element in the vector.
+   *
+   * @c dst and @ src can be either the same or different.
+   */
+  virtual void copy (void* dst,        size_t dst_index,
+                     const void* src,  size_t src_index) const override;
+
+
+  /**
+   * @brief Swap an element between vectors.
+   * @param a Pointer to the start of the first vector's data.
+   * @param aindex Index of the element in the first vector.
+   * @param b Pointer to the start of the second vector's data.
+   * @param bindex Index of the element in the second vector.
+   *
+   * @c a and @ b can be either the same or different.
+   */
+  virtual void swap (void* a, size_t aindex,
+                     void* b, size_t bindex) const override;
+
+
+  /**
+   * @brief Clear an element within a vector (static method).
+   * @param dst Pointer to the start of the vector's data.
+   * @param dst_index Index of the element in the vector.
+   */
+  virtual void clear (void* dst, size_t dst_index) const override;
+
+
+  /**
+   * @brief Return the size of an element of this vector type.
+   */
+  virtual size_t getEltSize() const override;
+
+
+  /**
+   * @brief Return the @c type_info of the overall object.
+   */
+  virtual const std::type_info* tiVec() const override;
+
+
+  /**
+   * @brief True if the vectors created by this factory work by dynamic
+   *        emulation (via @c TVirtualCollectionProxy or similar); false
+   *        if the std::vector code is used directly.
+   */
+  virtual bool isDynamic() const override;
+
+
+private:
+  /// The @c TClass for the overall object.
+  TClass* m_objClass;
+
+  /// The @c TClass for the std::vector.
+  TClass* m_vecClass;
+
+  /// Offset of the STL vector within the overall object.
+  size_t m_offset;
+
+  /// Wrapper for the ROOT type of the element.
+  RootUtils::Type m_type;
+};
+
+
+} // namespace SG
+
+
+#endif // not ATHCONTAINERSROOT_ROOTAUXVECTORFACTORY_H
diff --git a/Control/AthContainersRoot/AthContainersRoot/getDynamicAuxID.h b/Control/AthContainersRoot/AthContainersRoot/getDynamicAuxID.h
new file mode 100644
index 0000000000000000000000000000000000000000..19ad34f5594b21fc8555acbdbe29f2c1974cbda1
--- /dev/null
+++ b/Control/AthContainersRoot/AthContainersRoot/getDynamicAuxID.h
@@ -0,0 +1,51 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file AthContainersRoot/getDynamicAuxID.h
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Oct, 2016
+ * @brief Find the auxid for a dynamic branch.
+ */
+
+
+#ifndef ATHCONTAINERSROOT_GETDYNAMICAUXID_H
+#define ATHCONTAINERSROOT_GETDYNAMICAUXID_H
+
+
+#include "AthContainersInterfaces/AuxTypes.h"
+#include <typeinfo>
+#include <string>
+
+
+
+namespace SG {
+
+
+/**
+ * @brief Find the auxid for a dynamic branch.
+ * @param ti Type of the auxiliary variable.
+ *           Usually the type of the vector payload, but if @c standalone
+ *           is true, then this is the type of the stored object.
+ * @param name Auxiliary variable name.
+ * @param elementTypeName Name of the type for one aux data element.
+ *                        Should be the samr as @c branchTypeName
+ *                        if @c standalone is true.
+ * @param branchTypeName Name of the type for this branch.
+ * @param standalone True if this is a standalone object.
+ */
+SG::auxid_t getDynamicAuxID (const std::type_info& ti,
+                             const std::string& name,
+                             const std::string& elementTypeName,
+                             const std::string& branch_type_name,
+                             bool standalone);
+
+
+} // namespace SG
+
+
+#endif // not ATHCONTAINERSROOT_GETDYNAMICAUXID_H
diff --git a/Control/AthContainersRoot/AthContainersRoot/selection.xml b/Control/AthContainersRoot/AthContainersRoot/selection.xml
new file mode 100644
index 0000000000000000000000000000000000000000..907467a8a1e0db18d5535ee406cbe791a73a6ab0
--- /dev/null
+++ b/Control/AthContainersRoot/AthContainersRoot/selection.xml
@@ -0,0 +1,11 @@
+<lcgdict>
+
+<class name="AthContainersRootTest::Foo"/>
+<class name="AthContainersRootTest::Bar"/>
+<class name="AthContainersRootTest::Baz"/>
+<class name="std::vector<AthContainersRootTest::Foo>"/>
+<class name="std::vector<AthContainersRootTest::Bar>"/>
+<class name="std::vector<AthContainersRootTest::Baz>"/>
+<class name="SG::AuxTypeVectorFactory<AthContainersRootTest::Foo>"/>
+
+</lcgdict>
diff --git a/Control/AthContainersRoot/CMakeLists.txt b/Control/AthContainersRoot/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..15ae2c6f986f1ccef92c4283051e017f9bd827df
--- /dev/null
+++ b/Control/AthContainersRoot/CMakeLists.txt
@@ -0,0 +1,55 @@
+################################################################################
+# Package: AthContainersRoot
+################################################################################
+
+# Declare the package name:
+atlas_subdir( AthContainersRoot )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          GaudiKernel
+                          Control/AthContainersInterfaces
+                          Control/RootUtils
+                          PRIVATE
+                          AtlasTest/TestTools
+                          Control/AthContainers
+                          Control/CxxUtils )
+
+# External dependencies:
+find_package( ROOT COMPONENTS Core )
+
+# Component(s) in the package:
+atlas_add_library( AthContainersRoot
+                   src/*.cxx
+                   PUBLIC_HEADERS AthContainersRoot
+                   PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
+                   PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} AthContainers RootUtils )
+
+
+atlas_add_dictionary( AthContainersRootTestDict
+   AthContainersRoot/AthContainersRootTestDict.h
+   AthContainersRoot/selection.xml
+   INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
+   LINK_LIBRARIES ${ROOT_LIBRARIES} AthContainersRoot AthContainers )
+
+
+atlas_add_test( RootAuxVectorFactory_test
+                SOURCES
+                test/RootAuxVectorFactory_test.cxx
+                INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
+                LINK_LIBRARIES ${ROOT_LIBRARIES} AthContainers CxxUtils RootUtils AthContainersRoot )
+
+
+atlas_add_test( getDynamicAuxID_test
+                SOURCES
+                test/getDynamicAuxID_test.cxx
+                INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
+                LINK_LIBRARIES ${ROOT_LIBRARIES} AthContainers CxxUtils RootUtils AthContainersRoot )
+
+
+atlas_add_test( AuxStoreRoot_test
+                SOURCES
+                test/AuxStoreRoot_test.cxx
+                INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
+                LINK_LIBRARIES ${ROOT_LIBRARIES} AthContainers CxxUtils RootUtils AthContainersRoot )
+
diff --git a/Control/AthContainersRoot/cmt/requirements b/Control/AthContainersRoot/cmt/requirements
new file mode 100644
index 0000000000000000000000000000000000000000..f12fd3db6ddc103c626aadf67715a2f1dcb03e40
--- /dev/null
+++ b/Control/AthContainersRoot/cmt/requirements
@@ -0,0 +1,32 @@
+package AthContainersRoot
+
+author Scott Snyder <snyder@fnal.gov>
+
+use AtlasPolicy      AtlasPolicy-*    
+use AtlasROOT        AtlasROOT-*        External
+use GaudiInterface   GaudiInterface-*   External
+use RootUtils        RootUtils-*        Control
+use AthContainersInterfaces AthContainersInterfaces-* Control
+use AthContainers    AthContainers-*    Control
+
+private
+use CxxUtils         CxxUtils-*         Control
+
+public
+apply_pattern installed_library
+library AthContainersRoot  *.cxx
+
+macro_append DOXYGEN_INPUT " ../doc" 
+
+private
+use TestTools      TestTools-*         AtlasTest 
+apply_pattern UnitTest_run unit_test=RootAuxVectorFactory
+apply_pattern UnitTest_run unit_test=getDynamicAuxID
+apply_pattern UnitTest_run unit_test=AuxStoreRoot
+
+
+private
+use AtlasReflex      AtlasReflex-*         External
+apply_pattern lcgdict dict=AthContainersRootTest selectionfile=selection.xml \
+                      headerfiles="../AthContainersRoot/AthContainersRootTestDict.h"
+
diff --git a/Control/AthContainersRoot/share/AuxStoreRoot_test.ref b/Control/AthContainersRoot/share/AuxStoreRoot_test.ref
new file mode 100644
index 0000000000000000000000000000000000000000..bae42c55f9e0a4e297a4d197d8aadfe147ef269b
--- /dev/null
+++ b/Control/AthContainersRoot/share/AuxStoreRoot_test.ref
@@ -0,0 +1,2 @@
+test1
+test2
diff --git a/Control/AthContainersRoot/share/RootAuxVectorFactory_test.ref b/Control/AthContainersRoot/share/RootAuxVectorFactory_test.ref
new file mode 100644
index 0000000000000000000000000000000000000000..45aaa06da1e7fc094ff05eb350b62d7b3dbc746e
--- /dev/null
+++ b/Control/AthContainersRoot/share/RootAuxVectorFactory_test.ref
@@ -0,0 +1,5 @@
+test1
+test2
+test3
+test4
+test5
diff --git a/Control/AthContainersRoot/share/getDynamicAuxID_test.ref b/Control/AthContainersRoot/share/getDynamicAuxID_test.ref
new file mode 100644
index 0000000000000000000000000000000000000000..a5bce3fd2565d8f458555a0c6f42d0504a848bd5
--- /dev/null
+++ b/Control/AthContainersRoot/share/getDynamicAuxID_test.ref
@@ -0,0 +1 @@
+test1
diff --git a/Control/AthContainersRoot/src/AuxStoreRoot.cxx b/Control/AthContainersRoot/src/AuxStoreRoot.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..cdbcbd28f2bd2bd09a31ce8a1e81867c713c0ab6
--- /dev/null
+++ b/Control/AthContainersRoot/src/AuxStoreRoot.cxx
@@ -0,0 +1,306 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file AthContainersRoot/src/AuxStoreRoot.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Oct, 2016
+ * @brief Base class for root-based dynamic auxiliary store.
+ */
+
+
+#include "AthContainersRoot/AuxStoreRoot.h"
+#include "AthContainers/AuxTypeRegistry.h"
+#include "AthContainers/exceptions.h"
+#include "AthContainers/tools/error.h"
+#include "RootUtils/Type.h"
+#include "TROOT.h"
+#include "TBranch.h"
+#include "TLeaf.h"
+#include "TClass.h"
+#include "TClassEdit.h"
+#include "TVirtualCollectionProxy.h"
+
+
+namespace {
+
+
+/**
+ * @brief Decode a ROOT @c EDataType.
+ * @param type ROOT type to decode.
+ * @param[out] typeName Name of the type.
+ *
+ * Returns the @c std::type_info for the type.
+ */
+const std::type_info* dataTypeToTypeInfo (EDataType type, std::string& typeName)
+{
+  RootUtils::Type typ (type);
+  typeName = typ.getTypeName();
+  return typ.getTypeInfo();
+}
+
+
+/**
+ * @brief Given a branch, return the aux data type for that branch.
+ * @param br The branch for which we want to get the type.
+ * @param standalone Is this for a standalone object?
+ * @param[out] elementTypeName Name of the type for one aux data element.
+ *                             Same as branchTypeName if @c standalone is true.
+ * @param[out] branchTypeName Name of the type for this branch.
+ *
+ * If standalone is true, then we return the type of the branch
+ * directly.  Otherwise, the branch should be a STL vector;
+ * we return the type of the vector's payload.
+ *
+ * Returns 0 on failure.
+ */
+const std::type_info* getElementType (TBranch* br,
+                                      bool standalone,
+                                      std::string& elementTypeName,
+                                      std::string& branchTypeName)
+{
+  TClass* expectedClass = 0;
+  EDataType expectedType = kOther_t;
+  if (br->GetExpectedType (expectedClass, expectedType) != 0) {
+    return 0;
+  }
+
+  if (standalone) {
+    if (expectedClass) {
+      elementTypeName = expectedClass->GetName();
+      branchTypeName = elementTypeName;
+      return expectedClass->GetTypeInfo();
+    }
+    const std::type_info* ret = dataTypeToTypeInfo (expectedType,
+                                                    elementTypeName);
+    branchTypeName = elementTypeName;
+    return ret;
+  }
+
+  // Not standalone; branch should be a vector.
+  if (!expectedClass) return 0;
+
+  branchTypeName = expectedClass->GetName();
+  if (strncmp (expectedClass->GetName(), "vector<", 7) == 0) {
+    TVirtualCollectionProxy* prox = expectedClass->GetCollectionProxy();
+    if (!prox) return 0;
+    if (prox->GetValueClass()) {
+      elementTypeName = prox->GetValueClass()->GetName();
+      return prox->GetValueClass()->GetTypeInfo();
+    }
+    return dataTypeToTypeInfo (prox->GetType(), elementTypeName);
+  }
+  else if (strncmp (expectedClass->GetName(), "SG::PackedContainer<", 20) == 0){
+    TClassEdit::TSplitType split (expectedClass->GetName());
+    if (split.fElements.size() > 1) {
+      elementTypeName = split.fElements[1];
+      RootUtils::Type typ (elementTypeName);
+      return typ.getTypeInfo();
+    }
+  }
+  return 0;
+}
+
+
+} // Anonymous namespace
+
+
+namespace SG {
+
+
+/**
+ * @brief Constructor.
+ * @param container Representation of the object for which we're reading.
+ * @param entry The entry in the root tree to read.
+ * @param standalone If true, this is a standalone auxiliary object.
+ */
+AuxStoreRoot::AuxStoreRoot(IAuxBranches& container,
+                           long long entry,
+                           bool standalone) :
+  SG::AuxStoreInternal (standalone),
+  m_entry(entry),
+  m_container(container)
+{
+}
+
+
+/**
+ * @brief Return the data vector for one aux data item
+ * @param auxid The identifier of the desired aux data item.
+ *
+ * Each aux data item is stored as a vector, with one entry
+ * per entry in the owning container.  This returns a pointer
+ * to the start of the vector.
+ *
+ * This should return 0 if the item doesn't exist.
+ */
+const void* AuxStoreRoot::getData(SG::auxid_t auxid) const
+{
+  guard_t guard (m_mutex);
+  // lock
+  const void* ret = SG::AuxStoreInternal::getData (auxid);
+  if (!ret) {
+    if (const_cast<AuxStoreRoot*>(this)->readData(auxid))
+      ret = SG::AuxStoreInternal::getData (auxid);
+  }
+  return ret;
+}
+
+
+/**
+ * @brief Return the data vector for one aux data item
+ * @param auxid The identifier of the desired aux data item.
+ * @param size The current size of the container (in case the data item
+ *             does not already exist).
+ * @param capacity The current capacity of the container (in case
+ *                 the data item does not already exist).
+ *
+ * Each aux data item is stored as a vector, with one entry
+ * per entry in the owning container.  This returns a pointer
+ * to the start of the vector.
+ *
+ * If the data item does not exist, it should be created and initialized
+ * to default values.  @c size and @c capacity give the size for the
+ * new aux data item vector.
+ *
+ * If the container is locked, throw an exception.
+ */
+void* AuxStoreRoot::getData(SG::auxid_t auxid,
+                            size_t /*size*/, size_t /*capacity*/)
+{
+  // MN:  how do we add new attributes to this store? A:for now we don't
+  return const_cast<void*>(getData(auxid));
+}
+
+
+
+
+/**
+ * @brief Return the data vector for one aux data decoration item.
+ * @param auxid The identifier of the desired aux data item.
+ * @param size The current size of the container (in case the data item
+ *             does not already exist).
+ * @param capacity The current capacity of the container (in case
+ *                 the data item does not already exist).
+ *
+ * Each aux data item is stored as a vector, with one entry
+ * per entry in the owning container.  This returns a pointer
+ * to the start of the vector.
+ *
+ * The base class implementation works except for the case where we have
+ * not yet created a vector for an item in the root file.  We need to 
+ * detect that case and raise an exception.
+ */
+void*
+AuxStoreRoot::getDecoration (SG::auxid_t auxid, size_t size, size_t capacity)
+{
+  guard_t guard (m_mutex);
+  if (SG::AuxStoreInternal::getIODataInternal (auxid, true) == 0 &&
+      SG::AuxStoreInternal::getAuxIDs().count (auxid) > 0)
+  {
+    throw SG::ExcStoreLocked (auxid);
+  }
+  return SG::AuxStoreInternal::getDecoration (auxid, size, capacity);
+}
+
+
+/**
+ * @brief Return a pointer to the data to be stored for one aux data item.
+ * @param auxid The identifier of the desired aux data item.
+ *
+ * This will usually be a pointer to a @c std::vector; however, it may
+ * be something different for a standalone object.
+ *
+ * Returns 0 and reports an error if the requested aux data item
+ * does not exist.
+ */
+const void* AuxStoreRoot::getIOData(SG::auxid_t auxid) const
+{
+  guard_t guard (m_mutex);
+  const void* ret = SG::AuxStoreInternal::getIODataInternal (auxid, true);
+  if (!ret) {
+    if (const_cast<AuxStoreRoot*>(this)->readData(auxid))
+      ret = SG::AuxStoreInternal::getIOData (auxid);
+  }
+  return ret;
+}
+
+
+/**
+ * @brief Derived classes should call this from their constructor
+ *        to complete initialization.
+ *
+ * Creates the auxid set from the list of branches.
+ * This cannot be done from the @c AuxStoreRoot constructor as it needs
+ * to call the @c resolveAuxID virtual method.
+ */  
+void AuxStoreRoot::fillAuxIDs()
+{
+   for( const auto& attr2branch: m_container.auxBranches() ) {
+     const std::string& attr = attr2branch.first;
+     std::string elemen_type_name;
+     std::string branch_type_name;
+     const std::type_info* ti = getElementType(attr2branch.second,
+                                               standalone(),
+                                               elemen_type_name,
+                                               branch_type_name);
+     SG::auxid_t auxid = resolveAuxID (m_container,
+                                       ti, attr,
+                                       elemen_type_name,
+                                       branch_type_name);
+
+     // add AuxID to the list
+     // May still be null if we don't have a dictionary for the branch.
+     if (auxid != SG::null_auxid)
+       addAuxID (auxid);
+   }
+
+   //lock();
+}
+
+
+/**
+ * @brief Change the TTree entry being read.
+ * @param entry New entry being read.
+ */
+void AuxStoreRoot::setEntry (long long entry)
+{
+  m_entry = entry;
+}
+
+
+/**
+ * @brief Read data from ROOT and store it in the internal vector.
+ *
+ * Returns true on success, false on failure.
+ */
+bool AuxStoreRoot::readData(SG::auxid_t auxid)
+{
+   TBranch* branch = m_container.findAuxBranch(auxid);
+   // check if there is a branch in the file
+   if( !branch ) return false; 
+
+   TClass*      cl = 0;
+   EDataType    typ;
+   if( branch->GetExpectedType(cl, typ) ) {
+     ATHCONTAINERS_ERROR("AuxStoreRoot::readData",
+                         std::string("Error getting branch type for ") + branch->GetName() );
+     return false;
+   }
+
+   // Make a 1-element vector.
+   SG::AuxStoreInternal::getDataInternal(auxid, 1, 1, true);
+   if (!standalone()) {
+     if (cl && strncmp (cl->GetName(), "SG::PackedContainer<", 20) == 0)
+       setOption (auxid, SG::AuxDataOption ("nbits", 32));
+   }
+
+   void* vector = const_cast<void*>(SG::AuxStoreInternal::getIOData (auxid)); // xxx
+
+   return doReadData (m_container, auxid, *branch, cl, vector, m_entry);
+}
+
+
+} // namespace SG
diff --git a/Control/AthContainersRoot/src/RootAuxVectorFactory.cxx b/Control/AthContainersRoot/src/RootAuxVectorFactory.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..0d9ff588ac8232d7e357d7c01a1be53300d58715
--- /dev/null
+++ b/Control/AthContainersRoot/src/RootAuxVectorFactory.cxx
@@ -0,0 +1,433 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file AthContainersRoot/src/RootAuxVectorFactory.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date May, 2014
+ * @brief Dynamic implementation of @c IAuxVectorFactory,
+ *        relying on root vector proxy.
+ */
+
+
+#include "AthContainersRoot/RootAuxVectorFactory.h"
+#include "AthContainers/tools/error.h"
+#include "TClass.h"
+#include "TVirtualCollectionProxy.h"
+#include "TROOT.h"
+#include <iostream>
+#include <stdexcept>
+
+
+namespace {
+
+
+/**
+ * @brief Find the vector type associated with @c CL by looking
+ *        up the @c vector_type typedef.
+ * @param cl The class for which to find the associated vector type.
+ *
+ * Given type CL, looks for a typedef CL::vector_type and returns the TClass
+ * for that if found.  Works for, eg, SG::PackedContainer.
+ */
+TClass* lookupVectorType (TClass *cl)
+{
+  std::string tname = cl->GetName();
+  tname += "::vector_type";
+  TDataType* typ = gROOT->GetType (tname.c_str());
+  if (typ)
+    return TClass::GetClass (typ->GetFullTypeName());
+  return nullptr;
+}
+
+
+} // anonymous namespace
+
+
+namespace SG {
+
+
+/**
+ * @brief Constructor.  Makes a new vector.
+ * @param factory The factory object for this type.
+ * @param size Initial size of the new vector.
+ * @param capacity Initial capacity of the new vector.
+ */
+RootAuxVector::RootAuxVector (const RootAuxVectorFactory* factory,
+                              size_t size, size_t /*capacity*/)
+  : m_factory (factory),
+    m_ownFlag (true)
+{
+  TClass* vecClass = factory->vecClass();
+  m_proxy = vecClass->GetCollectionProxy();
+  m_obj = factory->objClass()->New ();
+  m_vec = reinterpret_cast<char*> (m_obj) + factory->offset();
+  this->resize (size);
+}
+
+
+/**
+ * @brief Constructor, from a pointer to a vector object.
+ * @param data The vector object.
+ * @param isPacked If true, @c data is a @c PackedContainer.
+ * @param ownFlag If true, then take ownership of @c data.
+ *
+ * If the element type is T, then @c data should be a pointer
+ * to a std::vector<T> object, which was obtained with @c new.
+ *
+ * This version does not support packed containers, so @c isPacked
+ * must be false.
+ */
+RootAuxVector::RootAuxVector (const RootAuxVectorFactory* factory,
+                              void* data,
+                              bool isPacked,
+                              bool ownFlag)
+  : m_factory (factory),
+    m_ownFlag (ownFlag)
+{
+  if (isPacked) std::abort();
+  TClass* vecClass = factory->vecClass();
+  m_proxy = vecClass->GetCollectionProxy();
+  m_obj = data;
+  m_vec = reinterpret_cast<char*> (m_obj) + factory->offset();
+}
+
+
+/**
+ * @brief Copy constructor.
+ * @param other The vector to copy.
+ */
+RootAuxVector::RootAuxVector (const RootAuxVector& other)
+  : m_factory (other.m_factory),
+    m_proxy (other.m_proxy),
+    m_ownFlag (true)
+{
+  m_obj = m_factory->objClass()->New ();
+  m_vec = reinterpret_cast<char*> (m_obj) + m_factory->offset();
+  size_t sz = other.size();
+  this->resize (sz);
+
+  if (sz > 0) {
+    const RootUtils::Type& rootType = m_factory->rootType();
+
+    const void* otherPtr = 0;
+    {
+      TVirtualCollectionProxy::TPushPop bind (m_proxy, other.m_vec);
+      otherPtr = m_proxy->At(0);
+    }
+    
+    rootType.copyRange (this->toPtr(), otherPtr, sz);
+  }
+}
+
+
+/**
+ * @brief Destructor.
+ *
+ * This will free the vector data.
+ */
+RootAuxVector::~RootAuxVector()
+{
+  if (m_ownFlag)
+    m_factory->objClass()->Destructor (m_obj);
+}
+
+
+/**
+ * @brief Make a copy of this vector.
+ */
+SG::IAuxTypeVector* RootAuxVector::clone() const
+{
+  return new RootAuxVector (*this);
+}
+
+
+/**
+ * @brief Return a pointer to the start of the vector's data.
+ */
+void* RootAuxVector::toPtr ()
+{
+  TVirtualCollectionProxy::TPushPop bind (m_proxy, m_vec);
+  if (m_proxy->Size() == 0)
+    return 0;
+  return m_proxy->At(0);
+}
+
+
+/**
+ * @brief Return a pointer to the overall object.
+ */
+void* RootAuxVector::toVector ()
+{
+  return m_obj;
+}
+
+
+/**
+ * @brief Return the size of the vector.
+ */
+size_t RootAuxVector::size() const
+{
+  TVirtualCollectionProxy::TPushPop bind (m_proxy, m_vec);
+  return m_proxy->Size();
+}
+
+
+/**
+ * @brief Change the size of the vector.
+ * @param sz The new vector size.
+ */
+void RootAuxVector::resize (size_t sz)
+{
+  TVirtualCollectionProxy::TPushPop bind (m_proxy, m_vec);
+  m_proxy->Allocate(sz, false);
+}
+
+
+/**
+ * @brief Change the capacity of the vector.
+ * @param sz The new vector capacity.
+ */
+void RootAuxVector::reserve (size_t /*sz*/)
+{
+}
+
+
+/**
+ * @brief Shift the elements of the vector.
+ * @param pos The starting index for the shift.
+ * @param offs The (signed) amount of the shift.
+ *
+ * This operation shifts the elements in the vectors for all
+ * aux data items, to implement an insertion or deletion.
+ * @c offs may be either positive or negative.
+ *
+ * If @c offs is positive, then the container is growing.
+ * The container size should be increased by @c offs,
+ * the element at @c pos moved to @c pos + @c offs,
+ * and similarly for following elements.
+ * The elements between @c pos and @c pos + @c offs should
+ * be default-initialized.
+ *
+ * If @c offs is negative, then the container is shrinking.
+ * The element at @c pos should be moved to @c pos + @c offs,
+ * and similarly for following elements.
+ * The container should then be shrunk by @c -offs elements
+ * (running destructors as appropriate).
+ */
+void RootAuxVector::shift (size_t pos, ptrdiff_t offs)
+{
+  TVirtualCollectionProxy::TPushPop bind (m_proxy, m_vec);
+  size_t eltsz = m_proxy->GetIncrement();
+
+  const RootUtils::Type& rootType = m_factory->rootType();
+
+  if (offs < 0) {
+    if (-offs > static_cast<ptrdiff_t>(pos)) offs = -pos;
+    char* beg = reinterpret_cast<char*>(m_proxy->At(0));
+    rootType.copyRange (beg + eltsz*(pos+offs),
+                        beg + eltsz*pos,
+                        m_proxy->Size() - pos);
+    m_proxy->Allocate (m_proxy->Size() + offs, false);
+  }
+  else if (offs > 0) {
+    size_t oldsz = m_proxy->Size();
+    m_proxy->Allocate (oldsz + offs, false);
+    char* beg = reinterpret_cast<char*>(m_proxy->At(0));
+    rootType.copyRange (beg + eltsz*(pos+offs),
+                        beg + eltsz*pos,
+                        m_proxy->Size() - pos - offs);
+    rootType.clearRange (beg + eltsz*pos, offs);
+  }
+}
+
+
+/**
+ * @brief Return the type of the complete object to be saved.
+ *
+ * For example, if the object is a @c std::vector, then we return
+ * the @c type_info of the vector.  But if we're holding
+ * a @c PackedContainer, then we return the @c type_info of the
+ * @c PackedContainer.
+ *
+ * Can return null if the operation is not supported.  In that case,
+ * I/O will use the type found from the variable registry.
+ */
+const std::type_info* RootAuxVector::objType() const
+{
+  return m_factory->objClass()->GetTypeInfo();
+}
+
+
+//==================================================================
+
+
+/**
+ * @brief Constructor.
+ * @param vecClass The @c TClass for the vector object.
+ */
+RootAuxVectorFactory::RootAuxVectorFactory (TClass* objClass)
+  : m_objClass (objClass),
+    m_vecClass (objClass),
+    m_offset (0)
+{
+  TVirtualCollectionProxy* proxy = m_vecClass->GetCollectionProxy();
+
+  if (!proxy) {
+    TClass* vecClass = lookupVectorType (objClass);
+    if (vecClass) {
+      m_vecClass = vecClass;
+      Int_t offs = objClass->GetBaseClassOffset (vecClass);
+      if (offs >= 0) {
+        m_offset = offs;
+        proxy = vecClass->GetCollectionProxy();
+      }
+      else {
+        ATHCONTAINERS_ERROR("RootAuxVectorFactory::RootAuxVectorFactory",
+                            std::string("Can't find vector base class in ") +
+                            objClass->GetName());
+      }
+    }
+  }
+
+  if (!proxy) {
+    std::string err = "Can't find collection proxy for ";
+    err += m_vecClass->GetName();
+    throw std::runtime_error (err.c_str());
+  }
+
+  if (m_vecClass->GetTypeInfo() == 0) {
+    ATHCONTAINERS_ERROR("RootAuxVectorFactory::RootAuxVectorFactory",
+                        std::string("No type_info available for class ") +
+                        m_vecClass->GetName() +
+                        std::string(".  There is probably a missing dictionary.  We will likely crash further on."));
+  }
+
+  TClass* eltClass = proxy->GetValueClass();
+  if (eltClass)
+    m_type.init (eltClass);
+  else
+    m_type.init (proxy->GetType());
+}
+
+
+/**
+ * @brief Destructor.
+ */
+RootAuxVectorFactory::~RootAuxVectorFactory()
+{
+}
+
+
+/**
+ * @brief Create a vector object of this type.
+ * @param size Initial size of the new vector.
+ * @param capacity Initial capacity of the new vector.
+ */
+SG::IAuxTypeVector*
+RootAuxVectorFactory::create (size_t size, size_t capacity) const
+{
+  return new RootAuxVector (this, size, capacity);
+}
+
+
+/**
+ * @brief Create a vector object of this type from a data blob.
+ * @param data The vector object.
+ * @param isPacked If true, @c data is a @c PackedContainer.
+ * @param ownFlag If true, the newly-created IAuxTypeVector object
+ *                will take ownership of @c data.
+ *
+ * If the element type is T, then @c data should be a pointer
+ * to a std::vector<T> object, which was obtained with @c new.
+ *
+ * This version does not support packed containers, so @c isPacked
+ * must be false.
+ *
+ * Returns a newly-allocated object.
+ * FIXME: Should return a unique_ptr.
+ */
+SG::IAuxTypeVector*
+RootAuxVectorFactory::createFromData (void* data,
+                                      bool isPacked,
+                                      bool ownFlag) const
+{
+  return new RootAuxVector (this, data, isPacked, ownFlag);
+}
+
+
+/**
+ * @brief Copy an element between vectors.
+ * @param dst Pointer to the start of the destination vector's data.
+ * @param dst_index Index of destination element in the vector.
+ * @param src Pointer to the start of the source vector's data.
+ * @param src_index Index of source element in the vector.
+ *
+ * @c dst and @ src can be either the same or different.
+ */
+void RootAuxVectorFactory::copy (void* dst,        size_t dst_index,
+                                 const void* src,  size_t src_index) const
+{
+  m_type.assign (dst, dst_index, src, src_index);
+}
+
+
+/**
+ * @brief Swap an element between vectors.
+ * @param a Pointer to the start of the first vector's data.
+ * @param aindex Index of the element in the first vector.
+ * @param b Pointer to the start of the second vector's data.
+ * @param bindex Index of the element in the second vector.
+ *
+ * @c a and @ b can be either the same or different.
+ */
+void RootAuxVectorFactory::swap (void* a, size_t aindex,
+                                 void* b, size_t bindex) const
+{
+  m_type.swap (a, aindex, b, bindex);
+}
+
+
+/**
+ * @brief Clear an element within a vector (static method).
+ * @param dst Pointer to the start of the vector's data.
+ * @param dst_index Index of the element in the vector.
+ */
+void RootAuxVectorFactory::clear (void* dst, size_t dst_index) const
+{
+  m_type.clear (dst, dst_index);
+}
+
+
+/**
+ * @brief Return the size of an element of this vector type.
+ */
+size_t RootAuxVectorFactory::getEltSize() const
+{
+  return m_type.getSize();
+}
+
+
+/**
+ * @brief Return the @c type_info of the overall object.
+ */
+const std::type_info* RootAuxVectorFactory::tiVec() const
+{
+  return m_objClass->GetTypeInfo();
+}
+
+
+/**
+ * @brief True if the vectors created by this factory work by dynamic
+ *        emulation (via @c TVirtualCollectionProxy or similar); false
+ *        if the std::vector code is used directly.
+ */
+bool RootAuxVectorFactory::isDynamic() const
+{
+  return true;
+}
+
+
+} // namespace SG
diff --git a/Control/AthContainersRoot/src/getDynamicAuxID.cxx b/Control/AthContainersRoot/src/getDynamicAuxID.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..f25bbccb4940a480287a727cdcb57ac27d0a2d4c
--- /dev/null
+++ b/Control/AthContainersRoot/src/getDynamicAuxID.cxx
@@ -0,0 +1,111 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file AthContainersRoot/src/getDynamicAuxID.h
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Oct, 2016
+ * @brief Find the auxid for a dynamic branch.
+ */
+
+
+#include "AthContainersRoot/getDynamicAuxID.h"
+#include "AthContainersRoot/RootAuxVectorFactory.h"
+#include "AthContainers/AuxTypeRegistry.h"
+#include "TClass.h"
+#include "TROOT.h"
+
+
+namespace SG {
+
+
+/**
+ * @brief Look up a @c TClass given a name.  Try to avoid autoparsing.
+ * @param cname Name of the class to find.
+ */
+TClass* getClassIfDictionaryExists (const std::string& cname)
+{
+  if (TClass* cl = (TClass*)gROOT->GetListOfClasses()->FindObject(cname.c_str())) {
+    if (cl->IsLoaded() && cl->HasDictionary()) return cl;
+    return nullptr;
+  }
+
+  if (gInterpreter->GetClassSharedLibs (cname.c_str())) {
+    TClass* cl = TClass::GetClass (cname.c_str());
+    if (cl->HasDictionary())
+      return cl;
+  }
+  return nullptr;
+}
+
+
+/**
+ * @brief Find the auxid for a dynamic branch.
+ * @param ti Type of the auxiliary variable.
+ *           Usually the type of the vector payload, but if @c standalone
+ *           is true, then this is the type of the stored object.
+ * @param name Auxiliary variable name.
+ * @param elementTypeName Name of the type for one aux data element.
+ *                        Should be the samr as @c branchTypeName
+ *                        if @c standalone is true.
+ * @param branchTypeName Name of the type for this branch.
+ * @param standalone True if this is a standalone object.
+ */
+SG::auxid_t getDynamicAuxID (const std::type_info& ti,
+                             const std::string& name,
+                             const std::string& elementTypeName,
+                             const std::string& branchTypeName,
+                             bool standalone)
+{
+  SG::AuxTypeRegistry& r = SG::AuxTypeRegistry::instance();
+  SG::auxid_t auxid = SG::null_auxid;
+
+  auxid = r.getAuxID (ti, name);
+  if (auxid != SG::null_auxid) return auxid;
+
+  std::string fac_class_name = "SG::AuxTypeVectorFactory<" +
+    elementTypeName;
+  if (fac_class_name[fac_class_name.size()-1] == '>')
+    fac_class_name += ' ';
+  fac_class_name += '>';
+  TClass* fac_class = getClassIfDictionaryExists (fac_class_name);
+  if (fac_class)
+  {
+    TClass* base_class = getClassIfDictionaryExists ("SG::IAuxTypeVectorFactory");
+    if (base_class) {
+      int offs = fac_class->GetBaseClassOffset (base_class);
+      if (offs >= 0) {
+        void* fac_vp = fac_class->New();
+        if (fac_vp) {
+          SG::IAuxTypeVectorFactory* fac = reinterpret_cast<SG::IAuxTypeVectorFactory*> (reinterpret_cast<unsigned long>(fac_vp) + offs);
+          r.addFactory (ti, fac);
+          auxid = r.getAuxID(ti, name);
+        }
+      }
+    }
+  }
+
+  if (auxid == SG::null_auxid) {
+    std::string vec_name = branchTypeName;
+    if (standalone) {
+      vec_name = "std::vector<" + branchTypeName;
+      if (vec_name[vec_name.size()-1] == '>')
+        vec_name += " ";
+      vec_name += ">";
+    }
+    TClass* vec_class = TClass::GetClass (vec_name.c_str());
+
+    if (vec_class) {
+      SG::IAuxTypeVectorFactory* fac = new SG::RootAuxVectorFactory (vec_class);
+      r.addFactory (ti, fac);
+      auxid = r.getAuxID(ti, name);
+    }
+  }
+
+  return auxid;
+}
+
+
+} // namespace SG
diff --git a/Control/AthContainersRoot/test/AthContainersRoot.xml b/Control/AthContainersRoot/test/AthContainersRoot.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5a8c28aa94b8255506b1e89114a3f515bcf18b79
--- /dev/null
+++ b/Control/AthContainersRoot/test/AthContainersRoot.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<atn>
+   <TEST name="AthContainersRootTest" type="makecheck" suite="Examples">
+      <package>Control/AthContainersRoot</package>
+      <timelimit>40</timelimit>
+      <author> scott snyder </author>
+      <mailto> snyder@bnl.gov </mailto>
+      <expectations>
+         <errorMessage>Athena exited abnormally</errorMessage>
+         <errorMessage>differ</errorMessage>
+         <warningMessage> # WARNING_MESSAGE : post.sh> ERROR</warningMessage>
+         <successMessage>check ok</successMessage>
+         <returnValue>0</returnValue>
+      </expectations>
+   </TEST>
+</atn>
diff --git a/Control/AthContainersRoot/test/AuxStoreRoot_test.cxx b/Control/AthContainersRoot/test/AuxStoreRoot_test.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..a29ea4385e2eb8e92e8e2eeabc96152864af533e
--- /dev/null
+++ b/Control/AthContainersRoot/test/AuxStoreRoot_test.cxx
@@ -0,0 +1,345 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file AthContainersRoot/test/AuxStoreRoot_test.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Oct, 2016
+ * @brief Regression test for AuxStoreRoot.
+ */
+
+
+#undef NDEBUG
+#include "AthContainersRoot/AuxStoreRoot.h"
+#include "AthContainersRoot/AthContainersRootTestDict.h"
+#include "AthContainers/AuxElement.h"
+#include "TestTools/expect_exception.h"
+#include "TTree.h"
+#include "TBranch.h"
+#include <iostream>
+#include <cassert>
+
+
+class TestBranches
+  : public SG::IAuxBranches
+{
+public:
+  TestBranches (bool standalone);
+  virtual const std::string& getName() const override;
+  virtual std::vector<auxpair_t> auxBranches() const override;
+  virtual TBranch* findAuxBranch (SG::auxid_t auxid) override;
+  virtual StatusCode readAuxBranch (TBranch& br, void* p, long long entry) override;
+  virtual StatusCode readAuxBranch (TBranch& br, void* p,
+                                    const std::type_info& ti, long long entry) override;
+
+
+  std::string m_name;
+  TTree m_tree;
+  TBranch* m_br_foo;
+  TBranch* m_br_bar;
+  TBranch* m_br_baz;
+
+  SG::auxid_t m_foo_id;
+  SG::auxid_t m_bar_id;
+  SG::auxid_t m_baz_id;
+  SG::auxid_t m_fee_id;
+};
+
+
+TestBranches::TestBranches (bool standalone)
+  : m_name("TestBranches"),
+    m_tree (m_name.c_str(), m_name.c_str())
+{
+  if (standalone) {
+    m_br_foo =
+      m_tree.Branch ("foo", "AthContainersRootTest::Foo", nullptr);
+    m_br_bar =
+      m_tree.Branch ("bar", "AthContainersRootTest::Bar", nullptr);
+    m_br_baz =
+      m_tree.Branch ("baz", static_cast<void*>(nullptr), "baz/I");
+  }
+  else {
+    m_br_foo =
+      m_tree.Branch ("foo", "std::vector<AthContainersRootTest::Foo>", nullptr);
+    m_br_bar =
+      m_tree.Branch ("bar", "std::vector<AthContainersRootTest::Bar>", nullptr);
+    m_br_baz =
+      m_tree.Branch ("baz", "SG::PackedContainer<int>", nullptr);
+  }
+    
+  SG::AuxTypeRegistry& r = SG::AuxTypeRegistry::instance();
+  m_foo_id = r.getAuxID<AthContainersRootTest::Foo> ("foo");
+  m_bar_id = r.getAuxID<AthContainersRootTest::Bar> ("bar");
+  m_baz_id = r.getAuxID<int> ("baz");
+  m_fee_id = r.getAuxID<float> ("fee");
+}
+
+
+const std::string& TestBranches::getName() const
+{
+  return m_name;
+}
+
+
+std::vector<SG::IAuxBranches::auxpair_t> TestBranches::auxBranches() const
+{
+  std::vector<SG::IAuxBranches::auxpair_t> v;
+  v.emplace_back ("foo", m_br_foo);
+  v.emplace_back ("bar", m_br_bar);
+  v.emplace_back ("baz", m_br_baz);
+  return v;
+}
+
+
+TBranch* TestBranches::findAuxBranch (SG::auxid_t auxid)
+{
+  if (auxid == m_foo_id)
+    return m_br_foo;
+  if (auxid == m_bar_id)
+    return m_br_bar;
+  if (auxid == m_baz_id)
+    return m_br_baz;
+  return nullptr;
+}
+
+
+StatusCode
+TestBranches::readAuxBranch (TBranch& /*br*/, void* /*p*/, long long /*entry*/)
+{
+  std::abort();
+}
+
+
+StatusCode
+TestBranches::readAuxBranch (TBranch& /*br*/, void* /*p*/,
+                             const std::type_info& /*ti*/,
+                             long long /*entry*/)
+{
+  std::abort();
+}
+
+
+class AuxStoreRootTest
+  : public SG::AuxStoreRoot
+{
+public:
+  AuxStoreRootTest (SG::IAuxBranches& container,
+                    long long entry,
+                    bool standalone);
+
+  using SG::AuxStoreRoot::setEntry;
+
+  virtual SG::auxid_t resolveAuxID (SG::IAuxBranches& container,
+                                    const std::type_info* ti,
+                                    const std::string& name,
+                                    const std::string& elem_type_name,
+                                    const std::string& branch_type_name) override;
+
+  virtual bool doReadData (SG::IAuxBranches& container,
+                           SG::auxid_t auxid,
+                           TBranch& branch,
+                           TClass* cl,
+                           void* vector,
+                           long long entry) override;
+
+  struct DRDLog
+  {
+    SG::IAuxBranches& m_container;
+    SG::auxid_t m_auxid;
+    TBranch& m_branch;
+    TClass* m_cl;
+    void* m_vector;
+    long long m_entry;
+
+    DRDLog (SG::IAuxBranches& container,
+            SG::auxid_t auxid,
+            TBranch& branch,
+            TClass* cl,
+            void* vector,
+            long long entry)
+      : m_container (container),
+        m_auxid (auxid),
+        m_branch (branch),
+        m_cl (cl),
+        m_vector (vector),
+        m_entry (entry)
+    {
+    }
+  };
+
+  std::vector<DRDLog> m_log;
+};
+
+
+AuxStoreRootTest::AuxStoreRootTest (SG::IAuxBranches& container,
+                                    long long entry,
+                                    bool standalone)
+  : SG::AuxStoreRoot (container, entry, standalone)
+{
+  fillAuxIDs();
+}
+
+
+SG::auxid_t
+AuxStoreRootTest::resolveAuxID (SG::IAuxBranches& /*container*/,
+                                const std::type_info* ti,
+                                const std::string& name,
+                                const std::string& elem_type_name,
+                                const std::string& branch_type_name)
+{
+  if (name == "foo") {
+    SG::AuxElement::Accessor<AthContainersRootTest::Foo> a ("foo");
+    assert (elem_type_name == "AthContainersRootTest::Foo");
+    if (standalone()) {
+      assert (branch_type_name == "AthContainersRootTest::Foo");
+    }
+    else {
+      assert (branch_type_name == "vector<AthContainersRootTest::Foo>");
+    }
+    assert  (*ti == typeid (AthContainersRootTest::Foo));
+    return a.auxid();
+  }
+  else if (name == "bar") {
+    SG::AuxElement::Accessor<AthContainersRootTest::Bar> a ("bar");
+    assert (elem_type_name == "AthContainersRootTest::Bar");
+    if (standalone()) {
+      assert (branch_type_name == "AthContainersRootTest::Bar");
+    }
+    else {
+      assert (branch_type_name == "vector<AthContainersRootTest::Bar>");
+    }
+    assert  (*ti == typeid (AthContainersRootTest::Bar));
+    return a.auxid();
+  }
+  else if (name == "baz") {
+    SG::AuxElement::Accessor<int> a ("baz");
+    if (standalone()) {
+      assert (elem_type_name == "Int_t");
+      assert (branch_type_name == "Int_t");
+    }
+    else {
+      assert (elem_type_name == "int");
+      assert (branch_type_name == "SG::PackedContainer<int>");
+    }
+    assert  (*ti == typeid (int));
+    return a.auxid();
+  }
+  return SG::null_auxid;
+}
+
+
+bool AuxStoreRootTest::doReadData (SG::IAuxBranches& container,
+                                   SG::auxid_t auxid,
+                                   TBranch& branch,
+                                   TClass* cl,
+                                   void* vector,
+                                   long long entry)
+{
+  m_log.emplace_back (container, auxid, branch,
+                      cl, vector, entry);
+
+  if ((entry&1) == 0)
+    return true;
+  return false;
+}
+
+
+void test1()
+{
+  std::cout << "test1\n";
+
+  TestBranches branches (false);
+  AuxStoreRootTest store (branches, 122, false);
+  std::set<SG::auxid_t> aset { branches.m_foo_id, branches.m_bar_id, branches.m_baz_id };
+  assert (std::set<SG::auxid_t> (store.getAuxIDs().begin(),
+                                 store.getAuxIDs().end()) == aset);
+  store.m_log.clear();
+
+  const void* d = store.getData (branches.m_foo_id);
+  assert (d != nullptr);
+  assert (store.m_log.size() == 1);
+  assert (&store.m_log[0].m_container == &branches);
+  assert (store.m_log[0].m_auxid == branches.m_foo_id);
+  assert (&store.m_log[0].m_branch == branches.m_br_foo);
+  assert (std::string(store.m_log[0].m_cl->GetName()) == "vector<AthContainersRootTest::Foo>");
+  assert (store.m_log[0].m_entry == 122);
+  auto foo_vec = reinterpret_cast<std::vector<AthContainersRootTest::Foo>* > (store.m_log[0].m_vector);
+  assert (foo_vec->size() == 1);
+  assert (foo_vec->data() == d);
+
+  d = store.getData (branches.m_foo_id);
+  assert (foo_vec->data() == d);
+  assert (store.m_log.size() == 1);
+
+  d = store.getIOData (branches.m_foo_id);
+  assert (foo_vec == d);
+  assert (store.m_log.size() == 1);
+
+  d = store.getDecoration (branches.m_foo_id, 1, 1);
+  assert (foo_vec->data() == d);
+  assert (store.m_log.size() == 1);
+
+  d = store.getDecoration (branches.m_fee_id, 1, 1);
+  assert (d != nullptr);
+  assert (store.m_log.size() == 1);
+
+  EXPECT_EXCEPTION (SG::ExcStoreLocked,
+                    store.getDecoration (branches.m_bar_id, 1, 1));
+
+  d = store.getData (branches.m_baz_id);
+  assert (store.m_log.size() == 2);
+  assert (&store.m_log[1].m_container == &branches);
+  assert (store.m_log[1].m_auxid == branches.m_baz_id);
+  assert (&store.m_log[1].m_branch == branches.m_br_baz);
+  assert (std::string(store.m_log[1].m_cl->GetName()) == "SG::PackedContainer<int>");
+  assert (store.m_log[1].m_entry == 122);
+  auto baz_vec = reinterpret_cast<SG::PackedContainer<int>* > (store.m_log[1].m_vector);
+  assert (baz_vec->size() == 1);
+  assert (baz_vec->data() == d);
+  assert (baz_vec->parms().nbits() == 32);
+
+  store.setEntry (123);
+  d = store.getData (branches.m_bar_id);
+  assert (d == nullptr);
+  assert (store.m_log.size() == 3);
+  assert (&store.m_log[2].m_container == &branches);
+  assert (store.m_log[2].m_auxid == branches.m_bar_id);
+  assert (&store.m_log[2].m_branch == branches.m_br_bar);
+  assert (std::string(store.m_log[2].m_cl->GetName()) == "vector<AthContainersRootTest::Bar>");
+  assert (store.m_log[2].m_entry == 123);
+}
+
+
+// Standalone case
+void test2()
+{
+  std::cout << "test2\n";
+
+  TestBranches branches (true);
+  AuxStoreRootTest store (branches, 122, true);
+  std::set<SG::auxid_t> aset { branches.m_foo_id, branches.m_bar_id, branches.m_baz_id };
+  assert (std::set<SG::auxid_t> (store.getAuxIDs().begin(),
+                                 store.getAuxIDs().end()) == aset);
+  store.m_log.clear();
+
+  const void* d = store.getData (branches.m_foo_id);
+  assert (d != nullptr);
+  assert (store.m_log.size() == 1);
+  assert (&store.m_log[0].m_container == &branches);
+  assert (store.m_log[0].m_auxid == branches.m_foo_id);
+  assert (&store.m_log[0].m_branch == branches.m_br_foo);
+  assert (std::string(store.m_log[0].m_cl->GetName()) == "AthContainersRootTest::Foo");
+  assert (store.m_log[0].m_entry == 122);
+  assert (store.m_log[0].m_vector == d);
+}
+
+
+int main()
+{
+  test1();
+  test2();
+  return 0;
+}
+
diff --git a/Control/AthContainersRoot/test/RootAuxVectorFactory_test.cxx b/Control/AthContainersRoot/test/RootAuxVectorFactory_test.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..8847097923dec9f5017842955c686b5518f4de76
--- /dev/null
+++ b/Control/AthContainersRoot/test/RootAuxVectorFactory_test.cxx
@@ -0,0 +1,251 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file AthContainersRoot/test/RootAuxVectorFactory_test.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date May, 2014
+ * @brief Regression test for RootAuxVectorFactory.
+ */
+
+
+#undef NDEBUG
+#include "AthContainersRoot/RootAuxVectorFactory.h"
+#include "CxxUtils/StrFormat.h"
+#include "TClass.h"
+#include <iostream>
+#include <cassert>
+
+
+std::string str (int x)
+{
+  return CxxUtils::strformat ("%d", x);
+}
+
+
+void test1()
+{
+  std::cout << "test1\n";
+  TClass* cl = TClass::GetClass ("vector<int>");
+  SG::RootAuxVectorFactory fac (cl);
+  SG::IAuxTypeVector* vec = new SG::RootAuxVector (&fac, 10, 10);
+  assert (vec->size() == 10);
+  int* ptr = reinterpret_cast<int*> (vec->toPtr());
+  for (int i=0; i < 10; i++)
+    ptr[i] = i+1;
+  vec->resize (100);
+  vec->reserve (100);
+  ptr = reinterpret_cast<int*> (vec->toPtr());
+  for (int i=0; i < 10; i++)
+    assert (ptr[i] == i+1);
+  std::vector<int>* pvec = reinterpret_cast<std::vector<int>*> (vec->toVector());
+  assert (pvec->size() == 100);
+  for (int i=0; i < 10; i++)
+    assert ((*pvec)[i] == i+1);
+
+  // 1 2 3 4 5 6 7 8 9 10
+
+  vec->resize (10);
+  vec->shift (7, -3);
+  assert (vec->size() == 7);
+  // 1 2 3 4 8 9 10
+  ptr = reinterpret_cast<int*> (vec->toPtr());
+  assert (ptr[0] == 1);
+  assert (ptr[1] == 2);
+  assert (ptr[2] == 3);
+  assert (ptr[3] == 4);
+  assert (ptr[4] == 8);
+  assert (ptr[5] == 9);
+  assert (ptr[6] == 10);
+
+  vec->shift (3, 2);
+  assert (vec->size() == 9);
+  // 1 2 3 0 0 4 8 9 10
+  ptr = reinterpret_cast<int*> (vec->toPtr());
+  assert (ptr[0] == 1);
+  assert (ptr[1] == 2);
+  assert (ptr[2] == 3);
+  assert (ptr[3] == 0);
+  assert (ptr[4] == 0);
+  assert (ptr[5] == 4);
+  assert (ptr[6] == 8);
+  assert (ptr[7] == 9);
+  assert (ptr[8] == 10);
+
+  SG::IAuxTypeVector* vec2 = vec->clone();
+  int* ptr2 = reinterpret_cast<int*> (vec2->toPtr());
+  assert (ptr != ptr2);
+  assert (ptr2[0] == 1);
+  assert (ptr2[1] == 2);
+  assert (ptr2[2] == 3);
+  assert (ptr2[3] == 0);
+  assert (ptr2[4] == 0);
+  assert (ptr2[5] == 4);
+  assert (ptr2[6] == 8);
+  assert (ptr2[7] == 9);
+  assert (ptr2[8] == 10);
+  
+
+  vec->resize (0);
+  assert (vec->toPtr() == 0);
+
+  delete vec;
+}
+
+
+void test2()
+{
+  std::cout << "test2\n";
+  TClass* cl = TClass::GetClass ("vector<std::string>");
+  SG::RootAuxVectorFactory fac (cl);
+  SG::IAuxTypeVector* vec = new SG::RootAuxVector (&fac, 10, 10);
+  assert (vec->size() == 10);
+  std::string* ptr = reinterpret_cast<std::string*> (vec->toPtr());
+  for (int i=0; i < 10; i++)
+    ptr[i] = str(i+1);
+  vec->resize (100);
+  vec->reserve (100);
+  ptr = reinterpret_cast<std::string*> (vec->toPtr());
+  for (int i=0; i < 10; i++)
+    assert (ptr[i] == str(i+1));
+  std::vector<std::string>* pvec = reinterpret_cast<std::vector<std::string>*> (vec->toVector());
+  assert (pvec->size() == 100);
+  for (int i=0; i < 10; i++)
+    assert ((*pvec)[i] == str(i+1));
+
+  // 1 2 3 4 5 6 7 8 9 10
+
+  vec->resize (10);
+  vec->shift (7, -3);
+  assert (vec->size() == 7);
+  // 1 2 3 4 8 9 10
+  ptr = reinterpret_cast<std::string*> (vec->toPtr());
+  assert (ptr[0] == str(1));
+  assert (ptr[1] == str(2));
+  assert (ptr[2] == str(3));
+  assert (ptr[3] == str(4));
+  assert (ptr[4] == str(8));
+  assert (ptr[5] == str(9));
+  assert (ptr[6] == str(10));
+
+  vec->shift (3, 2);
+  assert (vec->size() == 9);
+  // 1 2 3 "" "" 4 8 9 10
+  ptr = reinterpret_cast<std::string*> (vec->toPtr());
+  assert (ptr[0] == str(1));
+  assert (ptr[1] == str(2));
+  assert (ptr[2] == str(3));
+  assert (ptr[3] == "");
+  assert (ptr[4] == "");
+  assert (ptr[5] == str(4));
+  assert (ptr[6] == str(8));
+  assert (ptr[7] == str(9));
+  assert (ptr[8] == str(10));
+
+  delete vec;
+}
+
+
+void test3()
+{
+  std::cout << "test3\n";
+  TClass* cl = TClass::GetClass ("vector<int>");
+  SG::RootAuxVectorFactory fac (cl);
+  assert (fac.vecClass() == cl);
+  assert (fac.getEltSize() == sizeof(int));
+  assert (fac.tiVec() == &typeid(std::vector<int>));
+  assert (fac.isDynamic());
+  SG::IAuxTypeVector* vec = fac.create (10, 10);
+  assert (vec->size() == 10);
+
+  int* ptr = reinterpret_cast<int*> (vec->toPtr());
+  ptr[0] = 1;
+  ptr[1] = 2;
+  fac.copy (ptr, 5, ptr, 1);
+  assert (ptr[1] == 2);
+  assert (ptr[5] == 2);
+
+  fac.clear (ptr, 1);
+  assert (ptr[1] == 0);
+
+  fac.swap (ptr, 0, ptr, 5);
+  assert (ptr[0] == 2);
+  assert (ptr[5] == 1);
+
+  delete vec;
+}
+
+
+void test4()
+{
+  std::cout << "test4\n";
+  TClass* cl = TClass::GetClass ("vector<std::string>");
+  SG::RootAuxVectorFactory fac (cl);
+  assert (fac.vecClass() == cl);
+  assert (fac.getEltSize() == sizeof(std::string));
+  assert (fac.tiVec() == &typeid(std::vector<std::string>));
+  assert (fac.isDynamic());
+  SG::IAuxTypeVector* vec = fac.create (10, 10);
+  assert (vec->size() == 10);
+
+  std::string* ptr = reinterpret_cast<std::string*> (vec->toPtr());
+  ptr[0] = "1";
+  ptr[1] = "2";
+  fac.copy (ptr, 5, ptr, 1);
+  assert (ptr[1] == "2");
+  assert (ptr[5] == "2");
+
+  fac.clear (ptr, 1);
+  assert (ptr[1] == "");
+
+  fac.swap (ptr, 0, ptr, 5);
+  assert (ptr[0] == "2");
+  assert (ptr[5] == "1");
+
+  delete vec;
+}
+
+
+void test5()
+{
+  std::cout << "test5\n";
+
+  TClass* cl = TClass::GetClass ("vector<int>");
+  SG::RootAuxVectorFactory fac (cl);
+
+  std::vector<int>* vec1 = new std::vector<int>;
+  vec1->push_back(3);
+  vec1->push_back(2);
+  vec1->push_back(1);
+  SG::IAuxTypeVector* v1 = fac.createFromData (vec1, false, true);
+  assert (v1->size() == 3);
+  int* ptr1 = reinterpret_cast<int*> (v1->toPtr());
+  assert (ptr1[0] == 3);
+  assert (ptr1[1] == 2);
+  assert (ptr1[2] == 1);
+  delete v1;
+
+  std::vector<int>* vec2 = new std::vector<int>;
+  vec2->push_back(4);
+  vec2->push_back(5);
+  SG::IAuxTypeVector* v2 = fac.createFromData (vec2, false, false);
+  assert (v2->size() == 2);
+  int* ptr2 = reinterpret_cast<int*> (v2->toPtr());
+  assert (ptr2[0] == 4);
+  assert (ptr2[1] == 5);
+  delete v2;
+  delete vec2;
+}
+
+
+int main()
+{
+  test1();
+  test2();
+  test3();
+  test4();
+  test5();
+  return 0;
+}
diff --git a/Control/AthContainersRoot/test/getDynamicAuxID_test.cxx b/Control/AthContainersRoot/test/getDynamicAuxID_test.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..bc9c3b32adc1a8606a6fc77b625955817974a1b9
--- /dev/null
+++ b/Control/AthContainersRoot/test/getDynamicAuxID_test.cxx
@@ -0,0 +1,98 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file AthContainersRoot/test/getDynamicAuxID_test.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Oct, 2016
+ * @brief Regression test for getDynamicAuxID.
+ */
+
+
+#undef NDEBUG
+#include "AthContainersRoot/getDynamicAuxID.h"
+#include "AthContainersRoot/AthContainersRootTestDict.h"
+#include "AthContainersRoot/RootAuxVectorFactory.h"
+#include "AthContainers/AuxElement.h"
+#include "AthContainers/AuxTypeRegistry.h"
+#include "TInterpreter.h"
+#include "TROOT.h"
+#include "TClass.h"
+#include <iostream>
+#include <cassert>
+
+
+void test1 (SG::auxid_t a1_id)
+{
+  std::cout << "test1\n";
+  SG::AuxTypeRegistry& r = SG::AuxTypeRegistry::instance();
+
+  assert (SG::getDynamicAuxID (typeid(int),
+                               "a1",
+                               "int",
+                               "std::vector<int>",
+                               false) == a1_id);
+
+  const SG::IAuxTypeVectorFactory* fac;
+  fac = r.getFactory (typeid(AthContainersRootTest::Foo));
+  assert  (fac == nullptr);
+  SG::auxid_t foo_id = SG::getDynamicAuxID (typeid(AthContainersRootTest::Foo),
+                                            "foo",
+                                            "AthContainersRootTest::Foo",
+                                            "std::vector<AthContainersRootTest::Foo>",
+                                            false);
+  assert (foo_id != SG::null_auxid);
+  fac = r.getFactory (typeid(AthContainersRootTest::Foo));
+  assert  (fac != nullptr);
+  assert (dynamic_cast<const SG::AuxTypeVectorFactory<AthContainersRootTest::Foo>*>(fac) != nullptr);
+  assert (r.getName(foo_id) == "foo");
+  assert (r.getTypeName(foo_id) == "AthContainersRootTest::Foo");
+  assert (r.getVecTypeName(foo_id) == "std::vector<AthContainersRootTest::Foo>");
+
+  fac = r.getFactory (typeid(AthContainersRootTest::Bar));
+  assert  (fac == nullptr);
+  SG::auxid_t bar_id = SG::getDynamicAuxID (typeid(AthContainersRootTest::Bar),
+                                            "bar",
+                                            "AthContainersRootTest::Bar",
+                                            "std::vector<AthContainersRootTest::Bar>",
+                                            false);
+  assert (bar_id != SG::null_auxid);
+  fac = r.getFactory (typeid(AthContainersRootTest::Bar));
+  assert  (fac != nullptr);
+  assert (dynamic_cast<const SG::RootAuxVectorFactory*>(fac) != nullptr);
+  assert (r.getName(bar_id) == "bar");
+  assert (r.getTypeName(bar_id) == "AthContainersRootTest::Bar");
+  assert (r.getVecTypeName(bar_id) == "std::vector<AthContainersRootTest::Bar>");
+
+  fac = r.getFactory (typeid(AthContainersRootTest::Baz));
+  assert  (fac == nullptr);
+  SG::auxid_t baz_id = SG::getDynamicAuxID (typeid(AthContainersRootTest::Baz),
+                                            "baz",
+                                            "AthContainersRootTest::Baz",
+                                            "AthContainersRootTest::Baz",
+                                            true);
+  assert (baz_id != SG::null_auxid);
+  fac = r.getFactory (typeid(AthContainersRootTest::Baz));
+  assert  (fac != nullptr);
+  assert (dynamic_cast<const SG::RootAuxVectorFactory*>(fac) != nullptr);
+  assert (r.getName(baz_id) == "baz");
+  assert (r.getTypeName(baz_id) == "AthContainersRootTest::Baz");
+  assert (r.getVecTypeName(baz_id) == "std::vector<AthContainersRootTest::Baz>");
+}
+
+
+SG::auxid_t init()
+{
+  static SG::AuxElement::Accessor<int> a1 ("a1");
+  return a1.auxid();
+}
+
+
+int main()
+{
+  SG::auxid_t a1_auxid = init();
+  test1(a1_auxid);
+  return 0;
+}