Index: kernel/include/IMP/decorators/HierarchyDecorator.h
===================================================================
--- kernel/include/IMP/decorators/HierarchyDecorator.h	(revision 589)
+++ kernel/include/IMP/decorators/HierarchyDecorator.h	(working copy)
@@ -16,12 +16,33 @@
 #include "../Particle.h"
 #include "../Model.h"
 #include "../DecoratorBase.h"
+#include "../internal/ArrayOnAttributesHelper.h"
 #include "utility.h"
 
 namespace IMP
 {
 
+class HierarchyDecorator;
 
+namespace internal
+{
+// needs to be external to keep swig happy
+struct IMPDLLEXPORT ChildArrayTraits {
+  static ParticleKey parent_key_;
+  static IntKey parent_index_key_;
+
+  typedef ParticleKey Key;
+  typedef Particle* Value;
+  typedef HierarchyDecorator ExternalType;
+  static void on_add(Particle * p, HierarchyDecorator d, unsigned int i) ;
+  static void on_change(Particle *, HierarchyDecorator d, unsigned int oi,
+                        unsigned int ni) ;
+  static void on_remove(Particle *, HierarchyDecorator d) ;
+  static Particle *get_value(HierarchyDecorator d) ;
+  static unsigned int get_index(Particle *, HierarchyDecorator d);
+};
+}
+
 /** \defgroup hierarchy Hierarchies of particles
     These functions and classes aid in manipulating particles representing
     molecules at multiple levels.
@@ -49,12 +70,14 @@
  */
 class IMPDLLEXPORT HierarchyDecorator: public DecoratorBase
 {
-  IMP_DECORATOR(HierarchyDecorator, DecoratorBase, return true || p,  ++p);
-  IMP_DECORATOR_ARRAY_DECL(child, Particle, Particle*, NULL)
-protected:
-  static ParticleKey parent_key_;
-  static IntKey parent_index_key_;
 
+  friend class internal::ChildArrayTraits;
+
+  IMP_DECORATOR_ARRAY_DECL(public, child, children, internal::ChildArrayTraits)
+
+  IMP_DECORATOR(HierarchyDecorator, DecoratorBase,
+                return has_required_attributes_for_child(p),
+                add_required_attributes_for_child(p));
 public:
 
   //! Get a HierarchyDecorator wrapping the parent particle
@@ -62,48 +85,33 @@
       if it has no parent.
    */
   This get_parent() const {
-    IMP_DECORATOR_GET(parent_key_, Particle*,
+    IMP_DECORATOR_GET(internal::ChildArrayTraits::parent_key_, Particle*,
                       return VALUE,
                       return This());
   }
 
-  //! Get the number of children.
-  unsigned int get_number_of_children() const {
-    // defined by the array macro
-    return internal_get_number_of_child();
-  }
-
-  //! Get a HierarchyDecorator of the ith child
-  /** \return decorator of the ith child, or throw an IndexException if it
-      does not have this child
-   */
-  This get_child(unsigned int i) const {
-    // defined by the array macro
-    return cast(internal_get_child(i));
-
-  }
-
   //! Get the index of this particle in the list of children
   /** \return index in the list of children of the parent, or -1 if
       it does not have a parent.
    */
   int get_parent_index() const {
-    IMP_DECORATOR_GET(parent_index_key_, Int, return VALUE, return -1);
+    IMP_DECORATOR_GET(internal::ChildArrayTraits::parent_index_key_,
+                      Int, return VALUE, return -1);
   }
 
   //! Return true if it has a parent.
   bool has_parent() const {
-    return get_particle()->has_attribute(parent_key_);
+    return get_particle()->has_attribute(
+                   internal::ChildArrayTraits::parent_key_);
   }
 
-  //! Add the particle as the last child.
-  unsigned int add_child(HierarchyDecorator hd);
-
   //! Get the index of a specific child in this particle.
   /** This takes linear time.
+      \note This is mostly useful for debugging as you can always call 
+      get_parent_index() on the child.
       \return the index, or -1 if there is no such child.
    */
-  int get_child_index(Particle *c) const;
+  int get_child_index(HierarchyDecorator c) const;
 
   //! Do some simple validity checks on this node in the hierarchy
   void validate_node() const;
@@ -314,6 +322,67 @@
   return gather.get_out();
 }
 
+
+//! Find the first node which matches some criteria
+/** \ingroup hierarchy
+ */
+template <class HD, class F>
+HD hierarchy_find(HD h, F f)
+{
+  if (f(h.get_particle())) return h;
+  std::vector<HD> stack;
+  stack.push_back(h);
+  //d.show(std::cerr);
+  do {
+    HD cur= stack.back();
+    stack.pop_back();
+
+    for (int i=cur.get_number_of_children()-1; i>=0; --i) {
+      HD hd= cur.get_child(i);
+      if (f(hd.get_particle())) {
+        return hd;
+      } else {
+        stack.push_back(hd);
+      }
+    }
+  } while (!stack.empty());
+  return HD();
+}
+
+namespace internal
+{
+
+inline void ChildArrayTraits::on_add(Particle * p,
+                                     HierarchyDecorator d,
+                                     unsigned int i) {
+  d.get_particle()->add_attribute(parent_key_, p);
+  d.get_particle()->add_attribute(parent_index_key_, i);
+}
+
+inline void ChildArrayTraits::on_change(Particle *,
+                                        HierarchyDecorator d,
+                                        unsigned int oi,
+                                        unsigned int ni) {
+  d.get_particle()->set_value(parent_index_key_, ni);
+}
+
+inline void ChildArrayTraits::on_remove(Particle *,
+                                        HierarchyDecorator d) {
+  d.get_particle()->remove_attribute(parent_index_key_); 
+  d.get_particle()->remove_attribute(parent_key_);
+}
+
+inline Particle *ChildArrayTraits::get_value(HierarchyDecorator d) {
+  return d.get_particle();
+}
+
+inline unsigned int ChildArrayTraits::get_index(Particle *,
+                                                HierarchyDecorator d) {
+  return d.get_parent_index();
+}
+}
+
+
 } // namespace IMP
 
 #endif  /* __IMP_HIERARCHY_DECORATOR_H */
Index: kernel/include/IMP/decorators/macros.h
===================================================================
--- kernel/include/IMP/decorators/macros.h	(revision 589)
+++ kernel/include/IMP/decorators/macros.h	(working copy)
@@ -7,8 +7,9 @@
  */
 
 #ifndef __IMP_DECORATOR_MACROS_H
-#define __IMP_DECORATOR_MACROS_H           
+#define __IMP_DECORATOR_MACROS_H
 
+#include <sstream>
 
 //! Define the basic things needed by a Decorator.
 /** The key things this defines are a default constructor, a static create
@@ -66,6 +67,9 @@
  static Name cast(::IMP::Particle *p) {                                 \
    return IMP::DecoratorBase::cast<Name>(p);                            \
  }                                                                      \
+ static bool is_instance_of(::IMP::Particle *p) {                       \
+ return has_required_attributes(p);                                     \
+ }                                                                      \
  /** Write information about this decorator to out. Each line should    \
      prefixed by prefix*/                                               \
  void show(std::ostream &out=std::cout,                                 \
@@ -177,57 +181,84 @@
    This macro should go in the header and IMP_DECORATOR_ARRAY_CPP into the .cpp
    and IMP_DECORATOR_ARRAY_INIT in the initialize_static_data function
 
-   To use the array, use functions 
+   The macro defines a set of functions for using the array:
+   - get_name(unsigned int)
 
-   - Type internal_get_name(unsigned int i) 
+   - get_number_of_name()
 
-   - void internal_add_name(Type) 
+   - add_name(Traits::ExternalType)
 
-   - unsigned int internal_get_number_of_name() const 
+   - add_name_at(Traits::ExternalType, unsigned int)
+
+   - remove_name(unsigned int)
+
+   in addition it defines the private methods
+   - has_required_attributes_for_name(Particle *)
+
+   - add_required_attributes_for_name(Particle *)
  */
-#define IMP_DECORATOR_ARRAY_DECL(name, TypeName, Type, Default)         \
-  protected:                                                            \
-  static IntKey number_of_##name##_key_;                                \
-  static std::vector<TypeName##Key> name##_keys_;                       \
-  static void generate_##name##_keys(unsigned int i);                   \
-  static const TypeName##Key get_##name##_key(unsigned int i) {         \
-    if (i >= name##_keys_.size()) generate_##name##_keys(i);            \
-    return name##_keys_[i];                                             \
-  }                                                                     \
-  Type internal_get_##name(unsigned int i) const{                       \
-    IMP_DECORATOR_GET(get_##name##_key(i), Type,                        \
-                      return VALUE,                                     \
-                      throw IndexException("Particle missing attribute"); \
-                      return Default);                                 \
-  }                                                                     \
-  int internal_add_##name(Type t);                                      \
-  unsigned int internal_get_number_of_##name() const {                  \
-    IMP_DECORATOR_GET(number_of_##name##_key_,                          \
-                      Int, return VALUE, return 0);                     \
-  }                                                                     \
+#define IMP_DECORATOR_ARRAY_DECL(protection, name, plural, Traits)      \
+private:                                                                \
+ static internal::ArrayOnAttributesHelper<Traits::Key,                  \
+                                          Traits::Value> name##_data_;  \
+ static bool has_required_attributes_for_##name(Particle *p) {          \
+   return name##_data_.has_required_attributes(p);                      \
+ }                                                                      \
+ static void add_required_attributes_for_##name(Particle *p) {          \
+   return name##_data_.add_required_attributes(p);                      \
+ }                                                                      \
+protection:                                                             \
+ /** \brief Get the ith member*/                                        \
+ Traits::ExternalType get_##name(unsigned int i) const {                \
+   return Traits::ExternalType(name##_data_.get_value(get_particle(), i)); \
+ }                                                                      \
+ /** \brief Get the total number of them*/                              \
+ unsigned int get_number_of_##plural() const {                          \
+   return name##_data_.get_size(get_particle());                        \
+ }                                                                      \
+ /** \brief Add t at the end */                                         \
+ unsigned int add_##name(Traits::ExternalType t) {                      \
+   unsigned int i= name##_data_.push_back(get_particle(),               \
+                                          Traits::get_value(t));        \
+   Traits::on_add(get_particle(), t, i);                                \
+   return i;                                                            \
+ }                                                                      \
+ /** Add t at a certain position */                                     \
+ void add_##name##_at(Traits::ExternalType t, unsigned int idx) {       \
+   name##_data_.insert(get_particle(),                                  \
+                       idx,                                             \
+                       Traits::get_value(t));                           \
+   Traits::on_add(get_particle(), t, idx);                              \
+   for (unsigned int i= idx+1; i < get_number_of_##plural(); ++i) {     \
+     Traits::on_change(get_particle(),                                  \
+                       name##_data_.get_value( get_particle(), i),      \
+                       i-1, i);                                         \
+   }                                                                    \
+ }                                                                      \
+ /** Remove t from the array */                                         \
+ void remove_##name(Traits::ExternalType t) {                           \
+   unsigned int idx= Traits::get_index(get_particle(), t);               \
+   Traits::on_remove(get_particle(), t);                                \
+   name##_data_.erase(get_particle(),                                   \
+                      idx);                                             \
+   for (unsigned int i= idx; i < get_number_of_##plural(); ++i) {       \
+     Traits::on_change(get_particle(),                                  \
+                       name##_data_.get_value(get_particle(), i),       \
+                       i+1, i);                                         \
+   }                                                                    \
+ }
 
 //! See IMP_DECORATOR_ARRAY_DECL
-#define IMP_DECORATOR_ARRAY_DEF(DecoratorType, name, TypeName, Type)   \
-  IntKey DecoratorType##Decorator::number_of_##name##_key_;             \
-  std::vector<TypeName##Key> DecoratorType##Decorator::name##_keys_;    \
-  void DecoratorType##Decorator::generate_##name##_keys(unsigned int i) \
-  {                                                                     \
-    while (!(i < name##_keys_.size())) {                                \
-      std::ostringstream oss;                                           \
-      oss << #DecoratorType " " #name " " << name##_keys_.size();       \
-      name##_keys_.push_back(TypeName##Key(oss.str().c_str()));         \
-    }                                                                   \
-  }                                                                     \
-  int DecoratorType##Decorator::internal_add_##name(Type t) {           \
-    int nc= internal_get_number_of_##name();                            \
-    get_particle()->add_attribute(get_##name##_key(nc), t);             \
-    IMP_DECORATOR_SET(number_of_##name##_key_, nc+1);                   \
-    return nc;                                                          \
-  }
+#define IMP_DECORATOR_ARRAY_DEF(DecoratorType, name, Traits)            \
+  internal::ArrayOnAttributesHelper<Traits::Key,                        \
+                                    Traits::Value>                      \
+  DecoratorType::name##_data_(std::string(#name)+ " " #DecoratorType);
 
+
+
 //! See IMP_DECORATOR_ARRAY_DECL
-#define IMP_DECORATOR_ARRAY_INIT(DecoratorType, name, TypeName, Type)   \
-  number_of_##name##_key_= IntKey(#DecoratorType " num " #name);
+#define IMP_DECORATOR_ARRAY_INIT(DecoratorType, name)   \
+  name##_data_.initialize();
 
 
 #endif  /* __IMP_DECORATOR_MACROS_H */
Index: kernel/include/IMP/decorators/MolecularHierarchyDecorator.h
===================================================================
--- kernel/include/IMP/decorators/MolecularHierarchyDecorator.h	(revision 589)
+++ kernel/include/IMP/decorators/MolecularHierarchyDecorator.h	(working copy)
@@ -29,9 +29,7 @@
                 HierarchyDecorator,
                 return P::has_required_attributes(p)
                        && p->has_attribute(type_key_),
-                { P::add_required_attributes(p);
-                  p->add_attribute(type_key_, UNKNOWN);
-                });
+                {p->add_attribute(type_key_, UNKNOWN);});
 protected:
   typedef HierarchyDecorator P;
   static IntKey type_key_;
@@ -70,6 +68,8 @@
       return "nucleic acid";
     case CHAIN:
       return "chain";
+    case FRAGMENT:
+      return "fragment";
     case PROTEIN:
       return "protein";
     case NUCLEOTIDE:
@@ -102,6 +102,21 @@
     return P::add_child(o);
   }
 
+  //! Add a child and check that the types are appropriate
+  /** A child must have a type that is listed before the parent in the
+      Type enum list.
+   */
+  void add_child_at(This o, unsigned int i) {
+    IMP_check(get_type() > o.get_type(),
+              "Parent type must subsume child type",
+              InvalidStateException(""));
+    IMP_check(get_type() != UNKNOWN, "Parent must have known type",
+              InvalidStateException(""));
+    IMP_check(o.get_type() != UNKNOWN, "Child must have known type",
+              InvalidStateException(""));
+    P::add_child_at(o, i);
+  }
+
   //! Get a child
   MolecularHierarchyDecorator get_child(unsigned int i) const {
     HierarchyDecorator hd= P::get_child(i);
@@ -120,7 +135,9 @@
 
 };
 
+typedef std::vector<MolecularHierarchyDecorator> MolecularHierarchyDecorators;
 
+
 /**
    Gather all the molecular particles of a certain level 
    in the molecular hierarchy
@@ -129,6 +146,37 @@
 IMPDLLEXPORT Particles get_particles(MolecularHierarchyDecorator mhd, 
                                      MolecularHierarchyDecorator::Type t);
 
+class ResidueDecorator;
+
+//! Get the residue with the specified index
+/** Fine the residue with the appropriate index. This is the PDB index,
+    not the offset in the chain (if they are different).
+
+    \throw ValueException if mhd's type is not one of CHAIN, PROTEIN, NUCLEOTIDE
+    \return MolecularHierarchyDecorator() if that residue is not found.
+
+    \todo We can make this method much more clever in its search since
+    most proteins consist of a few contiguous blocks of indices.
+
+    \ingroup hierarchy
+ */
+IMPDLLEXPORT ResidueDecorator
+get_residue(MolecularHierarchyDecorator mhd,
+            unsigned int index);
+
+
+//! Create a fragment containing the specified nodes
+/** A particle representing the frament is created and initialized.
+
+    The Fragment is inserted as a child of the parent (and the particles are
+    removed). The particles become children of the frament.
+
+    \throw ValueException If all the particles do not have the same parent.
+ */
+IMPDLLEXPORT MolecularHierarchyDecorator
+create_fragment(const MolecularHierarchyDecorators &ps);
+
+
 } // namespace IMP
 
 #endif  /* __IMP_MOLECULAR_HIERARCHY_DECORATOR_H */
Index: kernel/include/IMP/decorators/bond_decorators.h
===================================================================
--- kernel/include/IMP/decorators/bond_decorators.h	(revision 589)
+++ kernel/include/IMP/decorators/bond_decorators.h	(working copy)
@@ -84,7 +84,9 @@
  */
 class IMPDLLEXPORT BondedDecorator: public DecoratorBase
 {
-  IMP_DECORATOR(BondedDecorator, DecoratorBase, return true, );
+  IMP_DECORATOR(BondedDecorator, DecoratorBase,
+                return internal::graph_is_node(p, internal::bond_graph_data_), 
+                graph_initialize_node(p, internal::bond_graph_data_));
 
 
 public:
Index: kernel/include/IMP/internal/graph_base.h
===================================================================
--- kernel/include/IMP/internal/graph_base.h	(revision 589)
+++ kernel/include/IMP/internal/graph_base.h	(working copy)
@@ -13,6 +13,7 @@
 
 #include "../Particle.h"
 #include "../Model.h"
+#include "ArrayOnAttributesHelper.h"
 
 namespace IMP
 {
@@ -21,23 +22,32 @@
 {
 
 /** \internal */
-struct IMPDLLEXPORT GraphData
+struct IMPDLLEXPORT GraphData:
+    public ArrayOnAttributesHelper<ParticleKey, Particle*>
 {
-  GraphData() {}
-  GraphData(const char *prefix): prefix_(prefix) {
-    node_keys_[0]=ParticleKey((prefix_+" node 0").c_str());
-    node_keys_[1]=ParticleKey((prefix_+" node 1").c_str());
-    num_edges_key_= IntKey((prefix_+" num edges").c_str());
+  typedef ArrayOnAttributesHelper<ParticleKey, Particle*> P;
+  GraphData(): P("") {}
+  GraphData(std::string prefix): P(prefix) {
+    node_keys_[0]=ParticleKey((P::get_prefix()+" node 0").c_str());
+    node_keys_[1]=ParticleKey((P::get_prefix()+" node 1").c_str());
+    P::initialize();
   }
   ParticleKey node_keys_[2];
-  IntKey num_edges_key_;
-  mutable std::vector<ParticleKey> edge_keys_;
-  std::string prefix_;
 };
 
+
 /** \internal */
+IMPDLLEXPORT void graph_initialize_node(Particle* a,
+                                        const GraphData &d);
+
+/** \internal */
+IMPDLLEXPORT bool graph_is_node(Particle* a,
+                                const GraphData &d);
+
+
+/** \internal */
 IMPDLLEXPORT Particle* graph_connect(Particle* a, Particle* b,
-                                     const GraphData &d);
+                                     GraphData &d);
 
 /** \internal */
 IMPDLLEXPORT void graph_disconnect(Particle* bond,
Index: kernel/include/IMP/internal/ArrayOnAttributesHelper.h
===================================================================
--- kernel/include/IMP/internal/ArrayOnAttributesHelper.h	(revision 0)
+++ kernel/include/IMP/internal/ArrayOnAttributesHelper.h	(revision 0)
@@ -0,0 +1,134 @@
+/**
+ *  \file array_on_attributes.h   
+ *  \brief Various methods for managing an array of attributes
+ *
+ *  Copyright 2007-8 Sali Lab. All rights reserved.
+ *
+ */
+
+#ifndef __IMP_ARRAY_ON_ATTRIBUTES_H
+#define __IMP_ARRAY_ON_ATTRIBUTES_H
+
+#include "../base_types.h"
+
+#include <string>
+#include <sstream>
+
+namespace IMP
+{
+
+namespace internal
+{
+
+template <class KeyT, class ValueT>
+struct ArrayOnAttributesHelper {
+  ArrayOnAttributesHelper(std::string p): prefix_(p) {}
+  void initialize() {
+    num_key_= IntKey((prefix_ + " number").c_str());
+  }
+  typedef KeyT Key;
+  typedef ValueT Value;
+
+  unsigned int get_size(const Particle *p) const {
+    return p->get_value(num_key_);
+  }
+
+  void initialize_particle(Particle *p) {
+    p->add_attribute(num_key_, 0);
+  }
+
+  Value get_value(const Particle *p, unsigned int i) const {
+    IMP_check(keys_.size() > i, "Out of range attribute in array",
+              IndexException("out of range"));
+    IMP_check(static_cast<unsigned int>(p->get_value(num_key_)) > i,
+              "Out of range attribute in array",
+              IndexException("out of range"));
+    return p->get_value(keys_[i]);
+  }
+
+  void set_value(Particle *p,
+                 unsigned int i,
+                 Value v) const {
+    IMP_check(keys_.size() > i, "Out of range attribute in array",
+              IndexException("out of range"));
+    IMP_check(p->get_value(num_key_) > i, "Out of range attribute in array",
+              IndexException("out of range"));
+    p->set_value(keys_[i], v);
+  }
+
+  unsigned int push_back(Particle *p,
+                         Value v) {
+    unsigned int osz= p->get_value(num_key_);
+    Key k= get_key(osz);
+    p->add_attribute(k, v);
+    p->set_value(num_key_, osz+1);
+    return osz;
+  }
+
+  void insert(Particle *p,
+              unsigned int loc,
+              Value v) {
+    unsigned int osz= p->get_value(num_key_);
+    IMP_check(loc <= osz, "Attribute array must be contiguous",
+              IndexException("out of range"));
+    for (unsigned int i=loc; i < osz; ++i) {
+      Key k= get_key(i);
+      Value t= p->get_value(k);
+      p->set_value(k, v);
+      v=t;
+    }
+    Key k= get_key(osz);
+    p->add_attribute(k, v);
+    p->set_value(num_key_, osz+1);
+  }
+
+
+  void erase(Particle *p,
+             unsigned int loc) const {
+    unsigned int osz= p->get_value(num_key_);
+    IMP_check(loc <= osz, "Can only erase values in array",
+              IndexException("out of range"));
+    for (unsigned int i=loc+1; i < osz; ++i) {
+      Key k= keys_[i];
+      Key kl= keys_[i-1];
+      p->set_value(kl, p->get_value(k));
+    }
+    Key k= keys_[osz-1];
+    p->remove_attribute(k);
+    p->set_value(num_key_, osz-1);
+  }
+
+  std::string get_prefix() const {
+    return prefix_;
+  }
+
+
+  bool has_required_attributes(Particle *p) const {
+    return p->has_attribute(num_key_);
+  }
+
+  void add_required_attributes(Particle *p) const {
+    p->add_attribute(num_key_, 0);
+  }
+
+private:
+ Key get_key(unsigned int i) {
+    while (!(i < keys_.size())) {
+      std::ostringstream oss;
+      oss << prefix_ << keys_.size();
+      keys_.push_back(Key(oss.str().c_str()));
+    }   
+    return keys_[i];
+  }
+
+
+  std::vector<Key> keys_;
+  IntKey num_key_;
+  std::string prefix_;
+};
+
+}
+
+}
+
+#endif
Index: kernel/include/IMP/Particle.h
===================================================================
--- kernel/include/IMP/Particle.h	(revision 589)
+++ kernel/include/IMP/Particle.h	(working copy)
@@ -46,6 +46,8 @@
     optimization, mark all of its attributes as being non-optimizable
     (set_is_optimized method).
 
+    A particle may only belong to one model.
+
     \ingroup kernel
  */
 class IMPDLLEXPORT Particle : public internal::RefCountedObject
@@ -368,7 +370,6 @@
   // Set pointer to model particle data.
   void set_model(Model *md, ParticleIndex pi);
 
-  // all of the particle data
   internal::ObjectPointer<Model, false> model_;
 
   // true if particle is active
Index: kernel/src/decorators/HierarchyDecorator.cpp
===================================================================
--- kernel/src/decorators/HierarchyDecorator.cpp	(revision 589)
+++ kernel/src/decorators/HierarchyDecorator.cpp	(working copy)
@@ -6,19 +6,22 @@
  *
  */
 
-#include <sstream>
-
 #include "IMP/decorators/HierarchyDecorator.h"
 #include "IMP/decorators/NameDecorator.h"
 
+#include <sstream>
+
 namespace IMP
 {
 
-IMP_DECORATOR_ARRAY_DEF(Hierarchy, child, Particle, Particle*);
-ParticleKey HierarchyDecorator::parent_key_;
-IntKey HierarchyDecorator::parent_index_key_;
+IMP_DECORATOR_ARRAY_DEF(HierarchyDecorator, child,
+                        internal::ChildArrayTraits);
+namespace internal
+{
+ParticleKey ChildArrayTraits::parent_key_;
+IntKey ChildArrayTraits::parent_index_key_;
+}
 
-
 void HierarchyDecorator::validate_node() const
 {
   //get_particle()->get_model()->show(std::cerr);
@@ -32,15 +35,6 @@
                "Incorrect parent index in particle "
                << *get_particle());
   }
-  for (unsigned int i=0; i< get_number_of_children(); ++i) {
-    IMP_assert(get_particle()->has_attribute(get_child_key(i)),
-               "Recorded and actual number of children don't match -- "
-               "too few actual");
-  }
-  IMP_assert(!get_particle()->has_attribute(
-                 get_child_key(get_number_of_children())),
-             "Recorded and actual number of children don't match -- "
-             "too many actual");
 }
 
 void HierarchyDecorator::show(std::ostream &, std::string) const
@@ -81,42 +75,23 @@
 }
 
 
-int HierarchyDecorator::get_child_index(Particle *c) const
+int HierarchyDecorator::get_child_index(HierarchyDecorator c) const
 {
   for (unsigned int i=0; i< get_number_of_children(); ++i ) {
-    if (get_child(i) == HierarchyDecorator(c)) return i;
+    if (get_child(i) == c) return i;
   }
   return -1;
 }
 
 
-
-unsigned int HierarchyDecorator::add_child(HierarchyDecorator hd)
-{
-  IMP_assert(hd.get_particle() != get_particle(),
-             "A particle can't be its own child " << *this << std::endl 
-             << hd);
-  //std::cerr << *get_particle() << std::endl;
-  //std::cerr << *p << std::endl;
-  //std::cerr << "changing " << std::endl;
-  //std::cerr << "before\n";
-  //show_hierarchy<NameDecorator>(*this, std::cerr);
-  int nc= internal_add_child(hd.get_particle());
-
-  hd.get_particle()->add_attribute(parent_index_key_, nc);
-  hd.get_particle()->add_attribute(parent_key_, get_particle());
-  //std::cerr << "after\n";
-  //show_hierarchy<NameDecorator>(*this, std::cerr);
-  return nc;
-}
-
-
 IMP_DECORATOR_INITIALIZE(HierarchyDecorator, DecoratorBase,
                          {
-                           parent_key_ = ParticleKey("hierarchy_parent");
-                           parent_index_key_ = IntKey("hiearchy_parent_index");
+                           internal::ChildArrayTraits::parent_key_ 
+                             = ParticleKey("hierarchy_parent");
+                           internal::ChildArrayTraits::parent_index_key_ 
+                             = IntKey("hiearchy_parent_index");
                            IMP_DECORATOR_ARRAY_INIT(HierarchyDecorator,
-                                                    child, Particle, Particle*);
+                                                    child);
                          })
 
 
Index: kernel/src/decorators/MolecularHierarchyDecorator.cpp
===================================================================
--- kernel/src/decorators/MolecularHierarchyDecorator.cpp	(revision 589)
+++ kernel/src/decorators/MolecularHierarchyDecorator.cpp	(working copy)
@@ -53,7 +53,7 @@
                          })
 
 
-namespace internal
+namespace
 {
 
 struct MHDMatchingType
@@ -78,9 +78,79 @@
                         MolecularHierarchyDecorator::Type t)
 {
   Particles out;
-  hierarchy_gather(mhd, internal::MHDMatchingType(t),
+  hierarchy_gather(mhd, MHDMatchingType(t),
                    std::back_inserter(out));
   return out;
 }
 
+
+namespace
+{
+
+struct MatchResidueIndex
+{
+  unsigned int index_;
+  MatchResidueIndex(unsigned int i): index_(i) {}
+  bool operator()(Particle *p) const {
+    MolecularHierarchyDecorator mhd(p);
+    if (mhd.get_type() == MolecularHierarchyDecorator::RESIDUE
+        || mhd.get_type() == MolecularHierarchyDecorator::NUCLEICACID) {
+      ResidueDecorator rd(p);
+      return (rd.get_index() == index_);
+    } else {
+      return false;
+    }
+  }
+};
+
+}
+
+
+ResidueDecorator get_residue(MolecularHierarchyDecorator mhd,
+                                        unsigned int index) {
+  IMP_check(mhd.get_type() == MolecularHierarchyDecorator::PROTEIN
+            || mhd.get_type() == MolecularHierarchyDecorator::CHAIN
+            || mhd.get_type() == MolecularHierarchyDecorator::NUCLEOTIDE,
+            "Invalid type of MolecularHierarchyDecorator passed to get_residue",
+            ValueException("Bad val"));
+  MatchResidueIndex mi(index);
+  HierarchyDecorator hd= hierarchy_find(mhd, mi);
+  if (hd== HierarchyDecorator()) {
+    return ResidueDecorator();
+  } else {
+    return ResidueDecorator(hd.get_particle());
+  }
+}
+
+
+
+MolecularHierarchyDecorator
+create_fragment(const MolecularHierarchyDecorators &ps) {
+  IMP_check(!ps.empty(), "Need some particles",
+            ValueException(""));
+  MolecularHierarchyDecorator parent= ps[0].get_parent();
+  unsigned int index= ps[0].get_parent_index();
+  IMP_IF_CHECK(CHEAP) {
+    for (unsigned int i=0; i< ps.size(); ++i) {
+      IMP_check(ps[i].get_parent() == parent,
+                "Parents don't match",
+                ValueException(""));
+    }
+  }
+
+  Particle *fp= new Particle();
+  parent.get_particle()->get_model()->add_particle(fp);
+  MolecularHierarchyDecorator fd= MolecularHierarchyDecorator::create(fp);
+  fd.set_type(MolecularHierarchyDecorator::FRAGMENT);
+
+  for (unsigned int i=0; i< ps.size(); ++i) {
+    parent.remove_child(ps[i]);
+    fd.add_child(ps[i]);
+  }
+
+  parent.add_child_at(fd, index);
+  return fd;
+}
+
+
 } // namespace IMP
Index: kernel/src/internal/graph_base.cpp
===================================================================
--- kernel/src/internal/graph_base.cpp	(revision 589)
+++ kernel/src/internal/graph_base.cpp	(working copy)
@@ -15,22 +15,19 @@
 namespace internal
 {
 
-static void graph_add_edge_key(unsigned int i, const GraphData &d)
-{
-  while (i >= d.edge_keys_.size()) {
-    std::ostringstream oss;
-    oss << d.prefix_ << " edge " << i;
-    d.edge_keys_.push_back(ParticleKey(oss.str().c_str()));
-  }
+IMPDLLEXPORT void graph_initialize_node(Particle* a,
+                                        const GraphData &d) {
+  d.add_required_attributes(a);
 }
 
-static ParticleKey graph_get_edge_key(unsigned int i, const GraphData &d)
-{
-  if (i >= d.edge_keys_.size()) graph_add_edge_key(i, d);
-  return d.edge_keys_[i];
+/** \internal */
+IMPDLLEXPORT bool graph_is_node(Particle* a,
+                                const GraphData &d) {
+  return d.has_required_attributes(a);
 }
 
-Particle* graph_connect(Particle* a, Particle* b, const GraphData &d)
+
+Particle* graph_connect(Particle* a, Particle* b, GraphData &d)
 {
   Model *m= a->get_model();
   Particle *p= new Particle();
@@ -39,18 +36,7 @@
   p->add_attribute(d.node_keys_[1], b);
   for (int i=0; i< 2; ++i) {
     Particle *cp=((i==0)?a:b);
-    int nc= graph_get_number_of_edges(cp, d);
-    ParticleKey nm=graph_get_edge_key(nc, d);
-    if (!cp->has_attribute(nm)) {
-      cp->add_attribute(nm, p);
-    } else {
-      cp->set_value(nm, p);
-    }
-    if (cp->has_attribute(d.num_edges_key_)) {
-      cp->set_value(d.num_edges_key_, nc+1);
-    } else {
-      cp->add_attribute(d.num_edges_key_, nc+1);
-    }
+    d.push_back(cp, p);
   }
 
   return a->get_model()->get_particle(pi);
@@ -63,21 +49,12 @@
   p[0]= graph_get_node(e, 0, d);
   p[1]= graph_get_node(e, 1, d);
   for (int i=0; i< 2; ++i) {
-    int shift=0;
-    Int nc= p[i]->get_value(d.num_edges_key_);
-    for (int j=0; j< nc; ++j) {
-      if (graph_get_edge(p[i], j, d) == e) {
-        IMP_assert(shift==0, "duplicate edges found in graph_base");
-        shift=-1;
-      } else {
-        Particle* v = p[i]->get_value(graph_get_edge_key(j, d));
-        p[i]->set_value(graph_get_edge_key(j+shift, d), v);
+    for (unsigned int j=0; j< d.get_size(p[i]); ++j) {
+      if (d.get_value(p[i], j) == e) {
+        d.erase(p[i], j);
+        break;
       }
     }
-    p[i]->remove_attribute(graph_get_edge_key(nc-1, d));
-    IMP_assert(shift==-1, "no edge found");
-    IMP_assert(nc > 0, "Too few edges");
-    p[i]->set_value(d.num_edges_key_, nc-1);
   }
   e->set_is_active(false);
   e->get_model()->remove_particle(e->get_index());
@@ -87,14 +64,12 @@
 
 Particle* graph_get_edge(Particle* a, int i, const GraphData &d)
 {
-  ParticleKey nm= graph_get_edge_key(i, d);
-  return a->get_value(nm);
+  return d.get_value(a,i);
 }
 
 Particle* graph_get_neighbor(Particle* a, int i, const GraphData &d)
 {
-  ParticleKey nm= graph_get_edge_key(i, d);
-  Particle *edge= a->get_value(nm);
+  Particle *edge= d.get_value(a,i);
   if (graph_get_node(edge, 0, d) == a) {
     return graph_get_node(edge, 1, d);
   } else {
@@ -106,11 +81,7 @@
 
 unsigned int graph_get_number_of_edges(Particle *a, const GraphData &d)
 {
-  if (a->has_attribute(d.num_edges_key_)) {
-    return a->get_value(d.num_edges_key_);
-  } else {
-    return 0;
-  }
+  return d.get_size(a);
 }
 
 Particle* graph_get_node(Particle *a, int i, const GraphData &d)
Index: kernel/pyext/IMP/pdb.py
===================================================================
--- kernel/pyext/IMP/pdb.py	(revision 589)
+++ kernel/pyext/IMP/pdb.py	(working copy)
@@ -43,8 +43,14 @@
         mab= b[1]
         pa=atoms[maa.index]
         pb=atoms[mab.index]
-        ba= IMP.BondedDecorator.create(pa);
-        bb= IMP.BondedDecorator.create(pb);
+        if IMP.BondedDecorator.is_instance_of(pa):
+            ba= IMP.BondedDecorator.cast(pa)
+        else:
+            ba= IMP.BondedDecorator.create(pa)
+        if IMP.BondedDecorator.is_instance_of(pb):
+            bb= IMP.BondedDecorator.cast(pb)
+        else:
+            bb= IMP.BondedDecorator.create(pb)
         bp= IMP.bond(ba, bb, IMP.BondDecorator.COVALENT)
 
 def read_pdb(name, model):
Index: kernel/test/modeller/test_pdb_read.py
===================================================================
--- kernel/test/modeller/test_pdb_read.py	(revision 589)
+++ kernel/test/modeller/test_pdb_read.py	(working copy)
@@ -33,6 +33,9 @@
         self.assertEqual(i_num_atom_type, f_num_atom_type, "too many atom types")
         self.assertEqual(1377, hc.get_count(),
                          "Wrong number of particles created")
+        rd= IMP.get_residue(mp, 29)
+        self.assertEqual(rd.get_index(), 29);
+
     def test_bonds(self):
         """Check that the file loader produces bonds"""
         m = IMP.Model()
Index: kernel/test/states/test_cover_bonds.py
===================================================================
--- kernel/test/states/test_cover_bonds.py	(revision 589)
+++ kernel/test/states/test_cover_bonds.py	(working copy)
@@ -19,8 +19,9 @@
                                IMP.Vector3D(10,10,10))
             ps.append(p)
         bds= []
+        bb= IMP.BondedDecorator.create(ps[0])
         for i in range(1,n):
-            ba= IMP.BondedDecorator.create(ps[i-1])
+            ba= IMP.BondedDecorator.cast(ps[i-1])
             bb= IMP.BondedDecorator.create(ps[i])
             bds.append(IMP.custom_bond(ba, bb, 10, 1))
         bl= IMP.BondDecoratorListScoreState(ps)
Index: kernel/test/decorators/test_hierarchy.py
===================================================================
--- kernel/test/decorators/test_hierarchy.py	(revision 589)
+++ kernel/test/decorators/test_hierarchy.py	(working copy)
@@ -8,13 +8,13 @@
         m = IMP.Model()
         pp=IMP.Particle()
         m.add_particle(pp)
-        ppd= IMP.HierarchyDecorator.cast(pp)
+        ppd= IMP.HierarchyDecorator.create(pp)
         ppnd= IMP.NameDecorator.create(pp)
         ppnd.set_name("root");
         for i in range(0,10):
             pc=IMP.Particle()
+            m.add_particle(pc)
             pcd= IMP.HierarchyDecorator.create(pc)
-            m.add_particle(pc)
             ppd.add_child(pcd)
             pcnd= IMP.NameDecorator.create(pc)
             pcnd.set_name(str("child "+str(i)));