[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[IMP-dev] various patches



Which are all grouped together since they can't be easily disentangled at this point.
API changes:
- some new methods have been added to hierarchies and molecular hierarchies and the names have been made slightly more consistent - a new score state ManualBondDecoratorListScoreState which does not rescan the particles to search for bonds. The old BondDecoratorList inherits from this. - the bond cover particle refiner now takes an optional intkey whose value will be propagated to the created particles (so that the typedpairscore can be used)
- vector3d now can be put in std::maps
- vrmllog now looks up colors in a map off of an index field and had some function names changed to make them make more since. And it takes particles refiners. - there is now code to read and write particles to YAML streams (as that makes way more sense for this sort of thing than xml). Individual particles can be written, but only the whole model must be read at once. - a few of the functions which used to be in the python class IMP.Test are now in the module IMP.test

minor changes:
- various cleanups to header inclusions, and other sorts of things
- verbose no longer logs every reference increment and decrement

The SConscript files are not included in the patch.


Index: kernel/doc/examples/chain.py
===================================================================
--- kernel/doc/examples/chain.py	(revision 623)
+++ kernel/doc/examples/chain.py	(working copy)
@@ -74,7 +74,7 @@
 # Write the progression of states as the system is optimized to
 # the files state.000.vrml, state.001.vrml etc.
 vrml= IMP.VRMLLogOptimizerState("state.%03d.vrml", chain)
-vrml.set_radius(rk)
+vrml.set_radius_key(rk)
 vrml.update()
 vrml.set_skip_steps(100)
 o.add_optimizer_state(vrml)
Index: kernel/src/particle_refiners/BondCoverParticleRefiner.cpp
===================================================================
--- kernel/src/particle_refiners/BondCoverParticleRefiner.cpp	(revision 623)
+++ kernel/src/particle_refiners/BondCoverParticleRefiner.cpp	(working copy)
@@ -16,12 +16,11 @@
 {
 
 BondCoverParticleRefiner::BondCoverParticleRefiner(FloatKey rk,
-                                                   FloatKey vk): rk_(rk),
-                                                                 vk_(vk)
+                                                   FloatKey vk,
+                                                   IntKey tk): rk_(rk),
+                                                               vk_(vk),
+                                                               tk_(tk)
 {
-  if (0) {
-    BondCoverParticleRefiner t(rk, vk);
-  }
 }
 
 
@@ -98,6 +97,10 @@
     XYZDecorator d= XYZDecorator::create(np);
     d.set_coordinates(vb+ (1+2*i)*r* ud);
     np->add_attribute(rk_, r, false);
+    if (tk_ != IntKey() && p->has_attribute(tk_)) {
+      np->add_attribute(tk_,
+                        p->get_value(tk_));
+    }
     ret.push_back(np);
   }
   return ret;
Index: kernel/src/decorators/MolecularHierarchyDecorator.cpp
===================================================================
--- kernel/src/decorators/MolecularHierarchyDecorator.cpp	(revision 623)
+++ kernel/src/decorators/MolecularHierarchyDecorator.cpp	(working copy)
@@ -6,13 +6,14 @@
  *
  */
 
-#include <sstream>
-
 #include "IMP/decorators/MolecularHierarchyDecorator.h"
 #include "IMP/decorators/NameDecorator.h"
 #include "IMP/decorators/AtomDecorator.h"
 #include "IMP/decorators/ResidueDecorator.h"
 
+#include <sstream>
+#include <set>
+
 namespace IMP
 {
 
@@ -72,10 +73,10 @@
   MolecularHierarchyDecorator::Type t_;
 };
 
-} // namespace internal
+} // namespace
 
-Particles get_particles(MolecularHierarchyDecorator mhd, 
-                        MolecularHierarchyDecorator::Type t)
+Particles molecular_hierarchy_get_by_type(MolecularHierarchyDecorator mhd, 
+                      MolecularHierarchyDecorator::Type t)
 {
   Particles out;
   hierarchy_gather(mhd, MHDMatchingType(t),
@@ -106,8 +107,9 @@
 } // namespace
 
 
-ResidueDecorator get_residue(MolecularHierarchyDecorator mhd,
-                                        unsigned int index)
+ResidueDecorator
+molecular_hierarchy_get_residue(MolecularHierarchyDecorator mhd,
+                                unsigned int index)
 {
   IMP_check(mhd.get_type() == MolecularHierarchyDecorator::PROTEIN
             || mhd.get_type() == MolecularHierarchyDecorator::CHAIN
@@ -154,5 +156,4 @@
   return fd;
 }
 
-
 } // namespace IMP
Index: kernel/src/decorators/yaml.cpp
===================================================================
--- kernel/src/decorators/yaml.cpp	(revision 0)
+++ kernel/src/decorators/yaml.cpp	(revision 0)
@@ -0,0 +1,273 @@
+#include <IMP/decorators/yaml.h>
+
+namespace IMP
+{
+
+  namespace {
+    struct DefaultWrite {
+      template <class T>
+      std::ostream & operator()(const T t,
+                                std::ostream &out) const {
+        return out << t;
+      }
+    };
+    struct ParticleWrite {
+      std::ostream & operator()(Particle *p,
+                                std::ostream &out) const {
+        return out << p->get_index();
+      }
+    };
+    struct FloatWrite {
+      std::ostream & operator()(Float t,
+                                std::ostream &out) const {
+        // set format better
+        return out << t;
+      }
+    };
+
+    template <class It, class Write>
+    void write_attributes(std::string indent,
+                          Particle *p,
+                          It b, It e, Write w,
+                          std::ostream &out) {
+      for (It c= b; c != e; ++c) {
+        /** \todo should escape things properly */
+        out << indent << c->get_string() << ": ";
+        w(p->get_value(*c), out) << "\n";
+      }
+    }
+
+    // skips empty lines
+    struct LineStream{
+      std::istream &in;
+      std::vector<std::string> line;
+      bool has_indent(std::string str, unsigned int indent) {
+        for (unsigned int i=0; i< indent; ++i) {
+          if (i== str.size()) return false;
+          if (str[i] != ' ') return false;
+        }
+        return true;
+      }
+      bool not_white(char buf[]) const {
+        for (int i=0; buf[i] != '\0'; ++i) {
+          if (buf[i] != ' ') return true;
+        }
+        return false;
+      }
+
+      LineStream(std::istream &init): in(init){}
+      operator bool() const {return !line.empty() || static_cast<bool>(in);}
+      std::string get_line(unsigned int min_indent) {
+        while (line.empty()) {
+          char buf[3000];
+          in.getline(buf, 3000);
+          if (!in) return std::string();
+          if (buf[0] == '#') continue;
+          if (not_white(buf)) {
+            line.push_back(buf);
+          }
+        }
+        if (has_indent(line.back(), min_indent)) {
+          std::string ret(line.back(), min_indent);
+          line.pop_back();
+          return ret;
+        } else {
+          IMP_LOG(VERBOSE, "Line \"" << line.back() << "\" lacks "
+                  << min_indent << " spaces" << std::endl);
+          return std::string();
+        }
+      }
+      void push_line(std::string s) {
+        if (s.empty()) return;
+        for (unsigned int i=0; i< s.size(); ++i) {
+          if (s[i] != ' ') {
+            line.push_back(s);
+            return;
+          }
+        }
+      }
+    };
+
+    template <class K, class V>
+    struct DefaultRead {
+      void operator()(Particle *p, std::string key, std::string value) const {
+        IMP_LOG(VERBOSE,
+                "Reading values from pair " << key << " "
+                << value << std::endl);
+        K k(key.c_str());
+        std::istringstream iss(value.c_str());
+        V v;
+        iss >> v;
+        IMP_check(iss, "Error reading value. Got " << v , ValueException);
+        p->set_value(k, v);
+      }
+    };
+
+    struct ParticleRead {
+      void operator()(Particle *p, std::string key, std::string value) const {
+        IMP_LOG(VERBOSE,
+                "Reading values from pair " << key << " "
+                << value << std::endl);
+        ParticleKey k(key.c_str());
+        std::istringstream iss(value.c_str());
+        int i;
+        iss >> i;
+        IMP_check(iss, "Error reading value" , ValueException);
+        Particle *op= p->get_model()->get_particle(ParticleIndex(i));
+        p->set_value(k, op);
+      }
+    };
+
+    int get_next_indent(LineStream &in) {
+      std::string buf= in.get_line(0);
+      if (buf.empty()) return 0;
+      unsigned int i=0;
+      for (; i < buf.size() && buf[i] == ' '; ++i) {
+      }
+      in.push_line(buf);
+      return i;
+    }
+
+
+    template <class Read>
+    void read_attributes(Particle *p, LineStream &in,
+                         int indent,
+                         Read read) {
+      IMP_LOG(VERBOSE, "Reading attributes " << indent << std::endl);
+      int nindent= get_next_indent(in);
+      if (nindent <= indent) return;
+      indent=nindent;
+      IMP_LOG(VERBOSE, "Required indent is " << indent<< std::endl);
+      do {
+        std::string buf = in.get_line(indent);
+        if (buf.empty()) {
+          IMP_LOG(VERBOSE, "Done reading attributes" << std::endl);
+          return;
+        }
+        IMP_check(buf[0] != ' ', "Extra white space on line "
+                  << buf, InvalidStateException);
+        std::istringstream iss(buf.c_str());
+        char key[2000];
+        iss.get(key, 2000, ':');
+        IMP_check(iss, "no : found in line " << buf,
+                  ValueException);
+        char colon;
+        iss >> colon;
+        IMP_check(colon == ':', "No colon found" << buf,
+                  ValueException);
+
+        char value[2000];
+        iss.getline(value, 2000);
+        read(p, key, value);
+
+      } while (true);
+    }
+
+
+    void read_yaml(Model *m,
+                   LineStream &in,
+                   unsigned int indent) {
+      std::string buf=in.get_line(indent);
+      if (buf.empty()) return;
+      //IMP_LOG(VERBOSE, "Got line " << buf << std::endl);
+      //IMP_check(in, "Error reading particle line from yaml", ValueException);
+      int id;
+      int nread=sscanf(buf.c_str(), "particle: %d", &id);
+      IMP_check(nread==1, "Couldn't read id", InvalidStateException);
+      Particle *p= m->get_particle(id);
+      IMP_LOG(VERBOSE, "Reading particle " << id << std::endl);
+      unsigned int nindent= get_next_indent(in);
+      if (nindent <= indent) return;
+      indent=nindent;
+      while (in) {
+        std::string buf=in.get_line(indent);
+        if (buf.empty()) break;
+        IMP_check(buf[0] != ' ', "Indent error" << buf, InvalidStateException);
+
+        IMP_LOG(VERBOSE, "Looking for attributes in line " << buf << std::endl);
+        std::istringstream iss(buf);
+        std::string type;
+        iss >> type;
+        if (type.compare("float-attributes:")==0) {
+          read_attributes(p, in, indent, DefaultRead<FloatKey, Float>());
+        } else if (type.compare("int-attributes:")==0) {
+          read_attributes(p, in, indent, DefaultRead<IntKey, Int>());
+        } else if (type.compare("string-attributes:")==0) {
+          read_attributes(p, in, indent, DefaultRead<StringKey, String>());
+        } else if (type.compare("particle-attributes:")==0) {
+          read_attributes(p, in, indent, ParticleRead());
+        } else {
+          break;
+        }
+      }
+      IMP_LOG(VERBOSE, "Done reading particle " << id << std::endl);
+    }
+
+
+  }
+
+  static std::string indent_level="  ";
+
+  void write_yaml(Particle *p,
+                  std::ostream &out,
+                  std::string indent) {
+    out << indent << "particle: " << p->get_index().get_index() << "\n";
+    out << indent << indent_level << "float-attributes:\n";
+    write_attributes(indent+indent_level+"  ",
+                     p,
+                     p->float_keys_begin(),
+                     p->float_keys_end(),
+                     FloatWrite(),
+                     out);
+    out << indent << indent_level << "int-attributes:\n";
+    write_attributes(indent+indent_level+"  ",
+                     p,
+                     p->int_keys_begin(),
+                     p->int_keys_end(),
+                     DefaultWrite(),
+                     out);
+    out << indent << indent_level << "string-attributes:\n";
+    write_attributes(indent+indent_level+"  ",
+                     p,
+                     p->string_keys_begin(),
+                     p->string_keys_end(),
+                     DefaultWrite(),
+                     out);
+    out << indent << indent_level << "particle-attributes:\n";
+    write_attributes(indent+indent_level+"  ",
+                     p,
+                     p->particle_keys_begin(),
+                     p->particle_keys_end(),
+                     ParticleWrite(),
+                     out);
+  }
+
+  void write_yaml(Model *m,
+                  std::ostream &out,
+                  std::string indent) {
+    for (Model::ParticleIterator pit= m->particles_begin();
+         pit != m->particles_end(); ++pit) {
+      write_yaml(*pit, out, indent);
+    }
+  }
+
+  void read_yaml(std::istream &in,
+                 Model *m) {
+    LineStream r(in);
+    unsigned int nread=0;
+    do {
+      read_yaml(m, r, get_next_indent(r));
+      ++nread;
+    } while (r);
+    IMP_check(nread== m->get_number_of_particles(),
+              "Read wrong number of particles. Model is corrupted. Bye.",
+              ErrorException);
+  }
+
+  void read_yaml(std::string contents,
+                 Model *m) {
+    std::istringstream iss(contents.c_str());
+    IMP_LOG(VERBOSE, "Got string:\n" << contents << std::endl);
+    read_yaml(iss, m);
+  }
+}
Index: kernel/src/decorators/HierarchyDecorator.cpp
===================================================================
--- kernel/src/decorators/HierarchyDecorator.cpp	(revision 623)
+++ kernel/src/decorators/HierarchyDecorator.cpp	(working copy)
@@ -128,4 +128,70 @@
 }
 
 
+
+namespace
+{
+
+struct MHDMatchingLeaves
+{
+  bool operator()(Particle *p) const {
+    HierarchyDecorator mhd(p);
+    return mhd.get_number_of_children()==0;
+  }
+};
+
+} // namespace
+
+
+Particles
+hierarchy_get_leaves(HierarchyDecorator mhd) {
+    Particles out;
+  hierarchy_gather(mhd, MHDMatchingLeaves(),
+                   std::back_inserter(out));
+  return out;
+}
+
+BondDecorators hierarchy_get_internal_bonds(HierarchyDecorator mhd) {
+  Particles ps= hierarchy_get_all_descendants(mhd);
+  std::set<Particle*> sps(ps.begin(), ps.end());
+  BondDecorators ret;
+  for (unsigned int i=0; i< ps.size(); ++i) {
+    if (IMP::BondedDecorator::is_instance_of(ps[i])){
+      IMP::BondedDecorator b(ps[i]);
+      for (unsigned int i=0; i< b.get_number_of_bonds(); ++i) {
+        Particle *op= b.get_bonded(i).get_particle();
+        if (op < ps[i] 
+            && sps.find(op) != sps.end()) {
+          ret.push_back(b.get_bond(i));
+        }
+      }
+    }
+  }
+  return ret;
+}
+
+
+namespace
+{
+
+struct MHDMatchingAll
+{
+  bool operator()(Particle *) const {
+    return true;
+  }
+};
+
+}
+
+Particles
+hierarchy_get_all_descendants(HierarchyDecorator mhd) {
+  Particles out;
+  hierarchy_gather(mhd, MHDMatchingAll(),
+                   std::back_inserter(out));
+  return out;
+}
+
+
+
+
 } // namespace IMP
Index: kernel/src/restraints/BondDecoratorRestraint.cpp
===================================================================
--- kernel/src/restraints/BondDecoratorRestraint.cpp	(revision 623)
+++ kernel/src/restraints/BondDecoratorRestraint.cpp	(working copy)
@@ -20,14 +20,15 @@
 
 BondDecoratorRestraint
 ::BondDecoratorRestraint(UnaryFunction *f,
-                         BondDecoratorListScoreState *s): bl_(s),
-                                                          f_(f){}
+                         ManualBondDecoratorListScoreState *s): bl_(s),
+                                                                f_(f){}
 
 Float BondDecoratorRestraint::evaluate(DerivativeAccumulator *accum)
 {
   Float sum=0;
-  for (BondDecoratorListScoreState::BondIterator bi= bl_->bonds_begin();
-       bi != bl_->bonds_end(); ++bi) {
+  for (BondDecoratorListScoreState::BondDecoratorIterator bi
+         = bl_->bond_decorators_begin();
+       bi != bl_->bond_decorators_end(); ++bi) {
     BondDecorator bd= *bi;
     Float l= bd.get_length();
     Float s= bd.get_stiffness();
@@ -64,7 +65,7 @@
 {
   out << "Bond decorator restraint with unary function ";
   f_->show(out);
-  out << " on " << bl_->get_number_of_bonds() << " bonds";
+  out << " on " << bl_->get_number_of_bond_decorators() << " bonds";
   out << std::endl;
 }
 
Index: kernel/src/score_states/CoverBondsScoreState.cpp
===================================================================
--- kernel/src/score_states/CoverBondsScoreState.cpp	(revision 623)
+++ kernel/src/score_states/CoverBondsScoreState.cpp	(working copy)
@@ -14,8 +14,9 @@
 {
 
 
-CoverBondsScoreState::CoverBondsScoreState(BondDecoratorListScoreState *bl,
-                                           FloatKey rk): bl_(bl), rk_(rk)
+CoverBondsScoreState
+::CoverBondsScoreState(ManualBondDecoratorListScoreState *bl,
+                       FloatKey rk): bl_(bl), rk_(rk)
 {
 }
 
@@ -25,8 +26,9 @@
 
 void CoverBondsScoreState::do_before_evaluate()
 {
-  for (BondDecoratorListScoreState::BondIterator it= bl_->bonds_begin();
-       it != bl_->bonds_end(); ++it) {
+  for (BondDecoratorListScoreState::BondDecoratorIterator it
+         = bl_->bond_decorators_begin();
+       it != bl_->bond_decorators_end(); ++it) {
     BondDecorator bd= *it;
     BondedDecorator pa= bd.get_bonded(0);
     BondedDecorator pb= bd.get_bonded(1);
@@ -62,8 +64,9 @@
 void CoverBondsScoreState::after_evaluate(DerivativeAccumulator *dva)
 {
   if (dva) {
-    for (BondDecoratorListScoreState::BondIterator it= bl_->bonds_begin();
-         it != bl_->bonds_end(); ++it) {
+    for (BondDecoratorListScoreState::BondDecoratorIterator it
+           = bl_->bond_decorators_begin();
+         it != bl_->bond_decorators_end(); ++it) {
       XYZDecorator d(it->get_particle());
       Vector3D deriv;
       // divide derivatives equally between endpoints
@@ -84,7 +87,7 @@
 
 void CoverBondsScoreState::show(std::ostream &out) const
 {
-  out << "CoverBondsScoreState on " << bl_->get_number_of_bonds()
+  out << "CoverBondsScoreState on " << bl_->get_number_of_bond_decorators()
       << " bonds " << std::endl;
 }
 
Index: kernel/src/score_states/AllNonbondedListScoreState.cpp
===================================================================
--- kernel/src/score_states/AllNonbondedListScoreState.cpp	(revision 623)
+++ kernel/src/score_states/AllNonbondedListScoreState.cpp	(working copy)
@@ -18,7 +18,7 @@
 {
 
 
-//! Turn the default into an actual algorithm and work around missing algorithms
+// Turn the default into an actual algorithm and work around missing algorithms
 static AllNonbondedListScoreState::Algorithm
 translate_algorithm(AllNonbondedListScoreState::Algorithm a)
 {
Index: kernel/src/score_states/BondDecoratorListScoreState.cpp
===================================================================
--- kernel/src/score_states/BondDecoratorListScoreState.cpp	(revision 623)
+++ kernel/src/score_states/BondDecoratorListScoreState.cpp	(working copy)
@@ -21,7 +21,7 @@
 {
   IMP_LOG(TERSE, "Updating BondDecoratorList for "
           << ps_.size() << " particles" << std::endl);
-  bonds_.clear();
+  std::vector<BondDecorator> bonds;
   for (unsigned int i=0; i< ps_.size(); ++i) {
     if (!ps_[i]->get_is_active()) continue;
     BondedDecorator di(ps_[i]);
@@ -36,31 +36,26 @@
       }
       if (di < dj) {
         IMP_LOG(VERBOSE, "Found bond " << di.get_bond(j) << std::endl);
-        bonds_.push_back(di.get_bond(j));
+        bonds.push_back(di.get_bond(j));
       }
     }
   }
-  IMP_LOG(TERSE, "Found " << bonds_.size() << " bonds"<< std::endl);
+  ManualBondDecoratorListScoreState::set_bond_decorators(bonds);
+  IMP_LOG(TERSE, "Found " << bonds.size() << " bonds"<< std::endl);
 }
 
 void BondDecoratorListScoreState::set_particles(const Particles &ps)
 {
   ps_=ps;
   std::sort(ps_.begin(), ps_.end());
-  bonds_.clear();
+  clear_bond_decorators();
 }
 
-
-bool BondDecoratorListScoreState::are_bonded(Particle *a, Particle *b) const
+void BondDecoratorListScoreState::add_particles(const Particles &ps)
 {
-  try {
-    BondedDecorator da= BondedDecorator::cast(a);
-    BondedDecorator db= BondedDecorator::cast(b);
-    return get_bond(da, db) != BondDecorator();
-  } catch (...) {
-    IMP_LOG(VERBOSE, "Exception thrown in are_bonded"<< std::endl);
-  }
-  return false;
+  ps_.insert(ps_.end(), ps.begin(), ps.end());
+  std::sort(ps_.begin(), ps_.end());
+  clear_bond_decorators();
 }
 
 } // namespace IMP
Index: kernel/src/score_states/ManualBondDecoratorListScoreState.cpp
===================================================================
--- kernel/src/score_states/ManualBondDecoratorListScoreState.cpp	(revision 0)
+++ kernel/src/score_states/ManualBondDecoratorListScoreState.cpp	(revision 0)
@@ -0,0 +1,41 @@
+#include "IMP/score_states/ManualBondDecoratorListScoreState.h"
+
+namespace IMP
+{
+  ManualBondDecoratorListScoreState
+  ::ManualBondDecoratorListScoreState(const BondDecorators &ps) {
+    set_bond_decorators(ps);
+  }
+
+  IMP_LIST_IMPL(ManualBondDecoratorListScoreState, BondDecorator,
+                bond_decorator, BondDecorator,
+                ,);
+
+  bool ManualBondDecoratorListScoreState::are_bonded(Particle *a,
+                                                     Particle *b) const
+  {
+    if (BondedDecorator::is_instance_of(a)
+        && BondedDecorator::is_instance_of(b)) {
+      BondedDecorator da(a);
+      BondedDecorator db(b);
+      return get_bond(da, db) != BondDecorator();
+    } else if (BondDecorator::is_instance_of(a)
+               && BondDecorator::is_instance_of(b)){
+      // check if they are bonds which share an endpoint
+      /**
+         \todo Decide if the check for adject bonds should go elsewhere
+       */
+      BondDecorator da(a);
+      BondDecorator db(b);
+      Particle *a0= da.get_bonded(0).get_particle();
+      Particle *a1= da.get_bonded(1).get_particle();
+      Particle *b0= db.get_bonded(0).get_particle();
+      Particle *b1= db.get_bonded(1).get_particle();
+
+      return (a0== b0 || a0 == b1 || a1== b0 || a1 == b1);
+    } else {
+      return false;
+    }
+  }
+
+}
Index: kernel/src/score_states/BipartiteNonbondedListScoreState.cpp
===================================================================
--- kernel/src/score_states/BipartiteNonbondedListScoreState.cpp	(revision 623)
+++ kernel/src/score_states/BipartiteNonbondedListScoreState.cpp	(working copy)
@@ -15,8 +15,10 @@
 namespace IMP
 {
 
-//! Turn the default into an actual algorithm and work around missing algorithms
-/** This cannot be shared with AllNBL because that one has grid and this does
+
+
+// Turn the default into an actual algorithm and work around missing algorithms
+/* This cannot be shared with AllNBL because that one has grid and this does
     not.
  */
 static BipartiteNonbondedListScoreState::Algorithm
Index: kernel/src/optimizers/states/VRMLLogOptimizerState.cpp
===================================================================
--- kernel/src/optimizers/states/VRMLLogOptimizerState.cpp	(revision 623)
+++ kernel/src/optimizers/states/VRMLLogOptimizerState.cpp	(working copy)
@@ -17,9 +17,10 @@
 
 VRMLLogOptimizerState::VRMLLogOptimizerState(std::string filename,
                                              const Particles &pis) :
-    pis_(pis), filename_(filename), file_number_(0), call_number_(0),
+    filename_(filename), file_number_(0), call_number_(0),
     skip_steps_(0)
 {
+  set_particles(pis);
 }
 
 void VRMLLogOptimizerState::update()
@@ -44,13 +45,17 @@
   if (!out) {
     IMP_WARN("Error opening VRML log file " << buf);
   } else {
-    IMP_LOG(VERBOSE, "Writing " << pis_.size()
+    IMP_LOG(VERBOSE, "Writing " << get_number_of_particles()
             << " particles to file " << buf << "..." << std::flush);
-    write(pis_, radius_, r_, g_, b_, out);
+    write(out, get_particles());
     //IMP_LOG(TERSE, "done" << std::endl);
   }
 }
 
+IMP_LIST_IMPL(VRMLLogOptimizerState, Particle, particle, Particle*, ,);
+IMP_CONTAINER_IMPL(VRMLLogOptimizerState, ParticleRefiner, particle_refiner,
+                   ParticleRefinerIndex ,,,);
+
 static Float snap(Float f)
 {
   if (f < 0) return 0;
@@ -58,32 +63,50 @@
   return f;
 }
 
-void VRMLLogOptimizerState::write(const Particles &pis, FloatKey rk,
-                                  FloatKey r, FloatKey g, FloatKey b,
-                                  std::ostream &out)
+void VRMLLogOptimizerState::set_color(int c, Vector3D v) {
+  colors_[c]= Vector3D(snap(v[0]),
+                       snap(v[1]),
+                       snap(v[2]));
+}
+
+void VRMLLogOptimizerState::write(std::ostream &out, const Particles &ps) const
 {
   out << "#VRML V2.0 utf8\n";
   out << "Group {\n";
   out << "children [\n";
 
-  for (unsigned int i = 0; i < pis.size(); ++i) {
+  for (Particles::const_iterator it = ps.begin(); it != ps.end(); ++it) {
+    Particle *p = *it;
+    bool wasrefined=false;
+    for (ParticleRefinerConstIterator prit= particle_refiners_begin(); 
+         prit != particle_refiners_end(); ++prit) {
+      if ((*prit)->get_can_refine(p)) {
+        Particles refined= (*prit)->get_refined(p);
+        write(out, refined);
+        (*prit)->cleanup_refined(p, refined, NULL);
+        wasrefined=true;
+        break;
+      }
+    }
+    if (wasrefined) continue;
     try {
-      Particle *p = pis[i];
       XYZDecorator xyz = XYZDecorator::cast(p);
       float x = xyz.get_x();
       float y = xyz.get_y();
       float z = xyz.get_z();
       Float rv = -1, gv = -1, bv = -1;
-      if (r != FloatKey() && b != FloatKey() && g != FloatKey()
-          && p->has_attribute(r) && p->has_attribute(g)
-          && p->has_attribute(b)) {
-        rv = snap(p->get_value(r));
-        gv = snap(p->get_value(g));
-        bv = snap(p->get_value(b));
+      if (color_ != IntKey()
+          && p->has_attribute(color_)) {
+        int cv = p->get_value(color_);
+        if (colors_.find(cv) != colors_.end()) {
+          rv= colors_.find(cv)->second[0];
+          gv= colors_.find(cv)->second[1];
+          bv= colors_.find(cv)->second[2];
+        }
       }
       Float radius = .1;
-      if (rk != FloatKey() && p->has_attribute(rk)) {
-        radius = p->get_value(rk);
+      if (radius_ != FloatKey() && p->has_attribute(radius_)) {
+        radius = p->get_value(radius_);
         //oss << ".sphere " << x << " " << y << " " << z << " " << r << "\n";
       }
 
@@ -111,7 +134,7 @@
       out << "}\n";
 
     } catch (InvalidStateException &e) {
-      IMP_WARN("Particle " << pis[i] << " does not have "
+      IMP_WARN("Particle " << p << " does not have "
                << " cartesian coordinates");
     }
   }
Index: kernel/pyext/IMP/test.py
===================================================================
--- kernel/pyext/IMP/test.py	(revision 623)
+++ kernel/pyext/IMP/test.py	(working copy)
@@ -3,6 +3,40 @@
 import IMP
 
 
+def create_particles_in_box( model, num=10,
+                            lb= [0,0,0],
+                            ub= [10,10,10]):
+    """Create a bunch of particles in a box"""
+    lbv=IMP.Vector3D(lb[0],lb[1],lb[2])
+    ubv=IMP.Vector3D(ub[0],ub[1],ub[2])
+    ps= IMP.Particles()
+    for i in range(0,num):
+        p= IMP.Particle()
+        model.add_particle(p)
+        d= IMP.XYZDecorator.create(p)
+        d.randomize_in_box(lbv, ubv)
+        ps.append(p)
+        d.set_coordinates_are_optimized(True)
+    return ps
+
+def randomize_particles(particles, deviation):
+    """Randomize the xyz coordinates of a list of particles"""
+    for p in particles:
+        d= IMP.XYZDecorator.cast(p)
+        d.set_x(random.uniform(-deviation, deviation))
+        d.set_y(random.uniform(-deviation, deviation))
+        d.set_z(random.uniform(-deviation, deviation))
+
+def create_chain(ps, length=1, stiffness=1):
+    bds= []
+    IMP.BondedDecorator.create(ps[0])
+    for i in range(1,len(ps)):
+        ba= IMP.BondedDecorator.cast(ps[i-1])
+        bb= IMP.BondedDecorator.create(ps[i])
+        bds.append(IMP.custom_bond(ba, bb, length, stiffness))
+    return bds
+
+
 class TestCase(unittest.TestCase):
     """Super class for IMP test cases"""
 
@@ -33,14 +67,6 @@
         p.add_attribute(IMP.FloatKey("z"), z, True)
         return p
 
-    def randomize_particles(self, particles, deviation):
-        """Randomize the xyz coordinates of a list of particles"""
-        for p in particles:
-            d= IMP.XYZDecorator.cast(p)
-            d.set_x(random.uniform(-deviation, deviation))
-            d.set_y(random.uniform(-deviation, deviation))
-            d.set_z(random.uniform(-deviation, deviation))
-
     def particle_distance(self, p1, p2):
         """Return distance between two given particles"""
         xkey = IMP.FloatKey("x")
@@ -73,30 +99,7 @@
                 fmin, vmin = f, v
         self.assertInTolerance(fmin, expected_fmin, step)
 
-    def create_particles_in_box(self, model, num=10,
-                                lb= [0,0,0],
-                                ub= [10,10,10]):
-        """Create a bunch of particles in a box"""
-        lbv=IMP.Vector3D(lb[0],lb[1],lb[2])
-        ubv=IMP.Vector3D(ub[0],ub[1],ub[2])
-        ps= IMP.Particles()
-        for i in range(0,num):
-            p= IMP.Particle()
-            model.add_particle(p)
-            d= IMP.XYZDecorator.create(p)
-            d.randomize_in_box(lbv, ubv)
-            ps.append(p)
-            d.set_coordinates_are_optimized(True)
-        return ps
 
-    def create_chain(self, ps, length=1, stiffness=1):
-        bds= []
-        IMP.BondedDecorator.create(ps[0])
-        for i in range(1,len(ps)):
-            ba= IMP.BondedDecorator.cast(ps[i-1])
-            bb= IMP.BondedDecorator.create(ps[i])
-            bds.append(IMP.custom_bond(ba, bb, length, stiffness))
-        return bds
 
 
 class ConstPairScore(IMP.PairScore):
Index: kernel/include/IMP.h
===================================================================
--- kernel/include/IMP.h	(revision 623)
+++ kernel/include/IMP.h	(working copy)
@@ -1,94 +1,114 @@
 /**
- *  \file IMP.h   \brief IMP, an Integrative Modeling Platform.
- *
- *  Copyright 2007-8 Sali Lab. All rights reserved.
- *
- */
-
+*  ile IMP.h   rief IMP, an Integrative Modeling Platform.
+*
+*  Copyright 2007-8 Sali Lab. All rights reserved.
+*
+*/
 #ifndef __IMP_H
 #define __IMP_H
-
-#include "IMP/IMP_config.h"
-#include "IMP/log.h"
-#include "IMP/random.h"
-#include "IMP/base_types.h"
-#include "IMP/Particle.h"
-#include "IMP/Optimizer.h"
-#include "IMP/Restraint.h"
-#include "IMP/exception.h"
-#include "IMP/Object.h"
-#include "IMP/RefCountedObject.h"
-#include "IMP/Pointer.h"
-#include "IMP/UnaryFunction.h"
-#include "IMP/unary_functions/Harmonic.h"
-#include "IMP/unary_functions/HarmonicLowerBound.h"
-#include "IMP/unary_functions/HarmonicUpperBound.h"
-#include "IMP/unary_functions/OpenCubicSpline.h"
-#include "IMP/unary_functions/ClosedCubicSpline.h"
-#include "IMP/unary_functions/Cosine.h"
-#include "IMP/unary_functions/Linear.h"
-#include "IMP/unary_functions/WormLikeChain.h"
-#include "IMP/Model.h"
-#include "IMP/PairScore.h"
-#include "IMP/SingletonScore.h"
-#include "IMP/TripletScore.h"
-#include "IMP/Vector3D.h"
-#include "IMP/VersionInfo.h"
-#include "IMP/ParticleRefiner.h"
-#include "IMP/particle_refiners/BondCoverParticleRefiner.h"
-#include "IMP/particle_refiners/ChildrenParticleRefiner.h"
-#include "IMP/decorators/HierarchyDecorator.h"
-#include "IMP/decorators/MolecularHierarchyDecorator.h"
-#include "IMP/decorators/NameDecorator.h"
-#include "IMP/decorators/AtomDecorator.h"
-#include "IMP/decorators/ResidueDecorator.h"
-#include "IMP/decorators/XYZDecorator.h"
-#include "IMP/decorators/bond_decorators.h"
-#include "IMP/optimizers/SteepestDescent.h"
-#include "IMP/optimizers/ConjugateGradients.h"
-#include "IMP/optimizers/MolecularDynamics.h"
-#include "IMP/optimizers/BrownianDynamics.h"
-#include "IMP/optimizers/MonteCarlo.h"
-#include "IMP/optimizers/Mover.h"
-#include "IMP/optimizers/MoverBase.h"
-#include "IMP/optimizers/movers/BallMover.h"
-#include "IMP/optimizers/movers/NormalMover.h"
-#include "IMP/optimizers/states/VRMLLogOptimizerState.h"
-#include "IMP/optimizers/states/CMMLogOptimizerState.h"
-#include "IMP/optimizers/states/VelocityScalingOptimizerState.h"
-#include "IMP/pair_scores/DistancePairScore.h"
-#include "IMP/pair_scores/SphereDistancePairScore.h"
-#include "IMP/pair_scores/RefineOncePairScore.h"
-#include "IMP/pair_scores/TypedPairScore.h"
-#include "IMP/pair_scores/TransformedDistancePairScore.h"
-#include "IMP/singleton_scores/DistanceToSingletonScore.h"
-#include "IMP/singleton_scores/AttributeSingletonScore.h"
-#include "IMP/triplet_scores/AngleTripletScore.h"
-#include "IMP/restraints/RestraintSet.h"
-#include "IMP/restraints/ConstantRestraint.h"
-#include "IMP/restraints/DistanceRestraint.h"
-#include "IMP/restraints/AngleRestraint.h"
-#include "IMP/restraints/DihedralRestraint.h"
-#include "IMP/restraints/ConnectivityRestraint.h"
-#include "IMP/restraints/NonbondedRestraint.h"
-#include "IMP/restraints/BondDecoratorRestraint.h"
-#include "IMP/restraints/SingletonListRestraint.h"
-#include "IMP/restraints/PairListRestraint.h"
-#include "IMP/restraints/TripletChainRestraint.h"
-#include "IMP/restraints/PairChainRestraint.h"
-#include "IMP/restraints/TunnelRestraint.h"
-#include "IMP/score_states/BipartiteNonbondedListScoreState.h"
-#include "IMP/score_states/MaxChangeScoreState.h"
-#include "IMP/score_states/NonbondedListScoreState.h"
-#include "IMP/score_states/BondedListScoreState.h"
-#include "IMP/score_states/BondDecoratorListScoreState.h"
-#include "IMP/score_states/AllNonbondedListScoreState.h"
-#include "IMP/score_states/GravityCenterScoreState.h"
-#include "IMP/score_states/CoverBondsScoreState.h"
-
-
-/**
-   \namespace IMP The IMP namespace.
- */
-
+#include <IMP/base_types.h>
+#include <IMP/DecoratorBase.h>
+#include <IMP/DerivativeAccumulator.h>
+#include <IMP/exception.h>
+#include <IMP/IMP_config.h>
+#include <IMP/Index.h>
+#include <IMP/Key.h>
+#include <IMP/log.h>
+#include <IMP/macros.h>
+#include <IMP/Model.h>
+#include <IMP/Object.h>
+#include <IMP/Optimizer.h>
+#include <IMP/OptimizerState.h>
+#include <IMP/PairScore.h>
+#include <IMP/Particle.h>
+#include <IMP/ParticleRefiner.h>
+#include <IMP/Pointer.h>
+#include <IMP/random.h>
+#include <IMP/RefCountedObject.h>
+#include <IMP/Restraint.h>
+#include <IMP/ScoreState.h>
+#include <IMP/SingletonScore.h>
+#include <IMP/TripletScore.h>
+#include <IMP/UnaryFunction.h>
+#include <IMP/utility.h>
+#include <IMP/Vector3D.h>
+#include <IMP/VersionInfo.h>
+#include <IMP/decorators/AtomDecorator.h>
+#include <IMP/decorators/bond_decorators.h>
+#include <IMP/decorators/HierarchyDecorator.h>
+#include <IMP/decorators/macros.h>
+#include <IMP/decorators/MolecularHierarchyDecorator.h>
+#include <IMP/decorators/NameDecorator.h>
+#include <IMP/decorators/ResidueDecorator.h>
+#include <IMP/decorators/utility.h>
+#include <IMP/decorators/XYZDecorator.h>
+#include <IMP/decorators/yaml.h>
+#include <IMP/internal/ArrayOnAttributesHelper.h>
+#include <IMP/internal/AttributeTable.h>
+#include <IMP/internal/bbox_nbl_helpers.h>
+#include <IMP/internal/constants.h>
+#include <IMP/internal/evaluate_distance_pair_score.h>
+#include <IMP/internal/ExponentialNumber.h>
+#include <IMP/internal/graph_base.h>
+#include <IMP/internal/Grid3D.h>
+#include <IMP/internal/kernel_version_info.h>
+#include <IMP/internal/ObjectContainer.h>
+#include <IMP/internal/ParticleGrid.h>
+#include <IMP/internal/ref_counting.h>
+#include <IMP/internal/Unit.h>
+#include <IMP/internal/units.h>
+#include <IMP/internal/utility.h>
+#include <IMP/internal/Vector.h>
+#include <IMP/optimizers/BrownianDynamics.h>
+#include <IMP/optimizers/ConjugateGradients.h>
+#include <IMP/optimizers/MolecularDynamics.h>
+#include <IMP/optimizers/MonteCarlo.h>
+#include <IMP/optimizers/MoverBase.h>
+#include <IMP/optimizers/Mover.h>
+#include <IMP/optimizers/SteepestDescent.h>
+#include <IMP/pair_scores/DistancePairScore.h>
+#include <IMP/pair_scores/RefineOncePairScore.h>
+#include <IMP/pair_scores/SphereDistancePairScore.h>
+#include <IMP/pair_scores/TransformedDistancePairScore.h>
+#include <IMP/pair_scores/TypedPairScore.h>
+#include <IMP/particle_refiners/BondCoverParticleRefiner.h>
+#include <IMP/particle_refiners/ChildrenParticleRefiner.h>
+#include <IMP/restraints/AngleRestraint.h>
+#include <IMP/restraints/BondDecoratorRestraint.h>
+#include <IMP/restraints/ConnectivityRestraint.h>
+#include <IMP/restraints/ConstantRestraint.h>
+#include <IMP/restraints/DihedralRestraint.h>
+#include <IMP/restraints/DistanceRestraint.h>
+#include <IMP/restraints/NonbondedRestraint.h>
+#include <IMP/restraints/PairChainRestraint.h>
+#include <IMP/restraints/PairListRestraint.h>
+#include <IMP/restraints/RestraintSet.h>
+#include <IMP/restraints/SingletonListRestraint.h>
+#include <IMP/restraints/TripletChainRestraint.h>
+#include <IMP/restraints/TunnelRestraint.h>
+#include <IMP/score_states/AllNonbondedListScoreState.h>
+#include <IMP/score_states/BipartiteNonbondedListScoreState.h>
+#include <IMP/score_states/BondDecoratorListScoreState.h>
+#include <IMP/score_states/BondedListScoreState.h>
+#include <IMP/score_states/CoverBondsScoreState.h>
+#include <IMP/score_states/GravityCenterScoreState.h>
+#include <IMP/score_states/ManualBondDecoratorListScoreState.h>
+#include <IMP/score_states/MaxChangeScoreState.h>
+#include <IMP/score_states/NonbondedListScoreState.h>
+#include <IMP/singleton_scores/AttributeSingletonScore.h>
+#include <IMP/singleton_scores/DistanceToSingletonScore.h>
+#include <IMP/triplet_scores/AngleTripletScore.h>
+#include <IMP/unary_functions/ClosedCubicSpline.h>
+#include <IMP/unary_functions/Cosine.h>
+#include <IMP/unary_functions/Harmonic.h>
+#include <IMP/unary_functions/HarmonicLowerBound.h>
+#include <IMP/unary_functions/HarmonicUpperBound.h>
+#include <IMP/unary_functions/Linear.h>
+#include <IMP/unary_functions/OpenCubicSpline.h>
+#include <IMP/unary_functions/WormLikeChain.h>
+#include <IMP/optimizers/movers/BallMover.h>
+#include <IMP/optimizers/movers/NormalMover.h>
+#include <IMP/optimizers/states/CMMLogOptimizerState.h>
+#include <IMP/optimizers/states/VelocityScalingOptimizerState.h>
+#include <IMP/optimizers/states/VRMLLogOptimizerState.h>
 #endif  /* __IMP_H */
Index: kernel/include/IMP/internal/ref_counting.h
===================================================================
--- kernel/include/IMP/internal/ref_counting.h	(revision 623)
+++ kernel/include/IMP/internal/ref_counting.h	(working copy)
@@ -27,7 +27,6 @@
   template <class O>
   static void eval(O* o) {
     BOOST_STATIC_ASSERT((!boost::is_base_of<RefCountedObject, O >::value));
-    IMP_LOG(VERBOSE, "Not refing particle " << o << std::endl);
   }
 };
 
@@ -36,8 +35,6 @@
 {
   template <class O>
   static void eval(O* o) {
-    IMP_LOG(VERBOSE, "Refing particle " << o->get_index() 
-            << o->get_ref_count() << std::endl);
     o->assert_is_valid();
     o->ref();
   }
@@ -49,7 +46,6 @@
   template <class O>
   static void eval(O* o) {
     BOOST_STATIC_ASSERT((!boost::is_base_of<RefCountedObject, O >::value));
-    IMP_LOG(VERBOSE, "Not Unrefing object " << o << std::endl);
   }
 };
 
@@ -58,8 +54,6 @@
 {
   template <class O>
   static void eval(O *o) {
-    IMP_LOG(VERBOSE, "Unrefing particle " << o->get_index()
-            << " " << o->get_ref_count() << std::endl);
     o->assert_is_valid();
     o->unref();
     if (!o->get_has_ref()) {
@@ -104,9 +98,6 @@
 template <class O>
 void disown(O* o)
 {
-  /*IMP_LOG(VERBOSE, "Disown called with " 
-          << (boost::is_base_of<RefCountedObject, O >::value)
-          << " for " << o << " " << o->get_ref_count() << std::endl);*/
   o->unref();
   if (!o->get_has_ref()) {
     delete o;
@@ -118,10 +109,6 @@
 template <class O>
 void own(O* o)
 {
-  /*IMP_LOG(VERBOSE, "Own called with "
-          << (boost::is_base_of<RefCountedObject, O >::value)
-          << " for " << o
-          << " " << o->get_ref_count() << std::endl);*/
   if (boost::is_base_of<RefCountedObject, O >::value) {
     // no checks
   } else {
@@ -133,6 +120,9 @@
 }
 
 
+
+
+
 } // namespace internal
 
 } // namespace IMP
Index: kernel/include/IMP/internal/units.h
===================================================================
--- kernel/include/IMP/internal/units.h	(revision 623)
+++ kernel/include/IMP/internal/units.h	(working copy)
@@ -119,6 +119,12 @@
 typedef Multiply<Multiply<Centimeter, Centimeter>::type,
                       Centimeter>::type CubicCentimeter;
 typedef Divide<Gram, CubicCentimeter>::type GramPerCubicCentimeter;
+typedef Shift<Second, -9>::type Nanosecond;
+typedef Shift<Meter, -9>::type Nanometer;
+typedef Multiply<Multiply<Nanometer, Nanometer>::type,
+                      Nanometer>::type CubicNanometer;
+typedef Shift<Second, -15>::type Femtosecond;
+typedef Divide<Piconewton, Nanometer>::type PiconewtonPerNanometer;
 
 
 
Index: kernel/include/IMP/internal/Grid3D.h
===================================================================
--- kernel/include/IMP/internal/Grid3D.h	(revision 623)
+++ kernel/include/IMP/internal/Grid3D.h	(working copy)
@@ -139,6 +139,16 @@
   }
 };
 
+
+
+
+
+
+
+
+
+
+
 //! Represent a real cell in a grid
 /** These indexes represent an actual cell in the grid with no mapping.
     They can only be constructed by the grid.
@@ -160,6 +170,16 @@
   }
 };
 
+
+
+
+
+
+
+
+
+
+
 /** \brief A voxel grid in 3D space.
     VT can be any class.
     \internal
@@ -340,12 +360,12 @@
   }
 
   //! Get the data in a particular cell
-  VoxelData& get_voxel(Index gi) {
+  typename std::vector<VT>::reference get_voxel(Index gi) {
     return data_[index(gi)];
   }
 
   //! Get the data in a particular cell
-  const VoxelData& get_voxel(Index gi) const  {
+  typename std::vector<VT>::const_reference get_voxel(Index gi) const  {
     return data_[index(gi)];
   }
 
Index: kernel/include/IMP/particle_refiners/BondCoverParticleRefiner.h
===================================================================
--- kernel/include/IMP/particle_refiners/BondCoverParticleRefiner.h	(revision 623)
+++ kernel/include/IMP/particle_refiners/BondCoverParticleRefiner.h	(working copy)
@@ -8,12 +8,14 @@
 #ifndef __IMP_BOND_COVER_PARTICLE_REFINER_H
 #define __IMP_BOND_COVER_PARTICLE_REFINER_H
 
+#include "../ParticleRefiner.h"
 #include "../internal/kernel_version_info.h"
-#include "../ParticleRefiner.h"
 
 namespace IMP
 {
 
+class Particle;
+
 //! Cover a bond with a constant volume set of spheres.
 /** Perhaps I want to add various custom bond types so that 
     this will only expand some custom bonds. Currently any
@@ -23,9 +25,11 @@
 {
   FloatKey rk_;
   FloatKey vk_;
+  IntKey tk_;
 public:
   BondCoverParticleRefiner(FloatKey rk,
-                           FloatKey vk);
+                           FloatKey vk,
+                           IntKey tk=IntKey());
 
   virtual ~BondCoverParticleRefiner() {}
 
Index: kernel/include/IMP/decorators/MolecularHierarchyDecorator.h
===================================================================
--- kernel/include/IMP/decorators/MolecularHierarchyDecorator.h	(revision 623)
+++ kernel/include/IMP/decorators/MolecularHierarchyDecorator.h	(working copy)
@@ -16,6 +16,7 @@
 #include "../Model.h"
 #include "utility.h"
 #include "HierarchyDecorator.h"
+#include "bond_decorators.h"
 
 namespace IMP
 {
@@ -43,8 +44,8 @@
       - TRAJECTORY is an ordered set of UNIVERSES
    */
   enum Type {UNKNOWN=-1, ATOM, RESIDUE, NUCLEICACID, FRAGMENT,
-             CHAIN, PROTEIN, NUCLEOTIDE, MOLECULE,
-             UNIVERSE, UNIVERSES, TRAJECTORY
+             CHAIN, PROTEIN, NUCLEOTIDE, MOLECULE, ASSEMBLY,
+             COLLECTION, UNIVERSE, UNIVERSES, TRAJECTORY
             };
 
   Type get_type() const {
@@ -76,10 +77,16 @@
       return "nucleotide";
     case MOLECULE:
       return "molecule";
+    case ASSEMBLY:
+      return "assembly";
+    case COLLECTION:
+      return "collection";
     case UNIVERSE:
       return "universe";
     case UNIVERSES:
       return "universes";
+    case TRAJECTORY:
+      return "trajectory";
     default:
       IMP_assert(0, "Invalid MolecularHierarchyDecorator type");
       return std::string();
@@ -132,6 +139,12 @@
     }
   }
 
+
+  static IntKey get_type_key() {
+    decorator_initialize_static_data();
+    return type_key_;
+  }
+
 };
 
 typedef std::vector<MolecularHierarchyDecorator> MolecularHierarchyDecorators;
@@ -142,8 +155,9 @@
    in the molecular hierarchy
    \ingroup hierarchy
 */
-IMPDLLEXPORT Particles get_particles(MolecularHierarchyDecorator mhd, 
-                                     MolecularHierarchyDecorator::Type t);
+IMPDLLEXPORT Particles
+molecular_hierarchy_get_by_type(MolecularHierarchyDecorator mhd, 
+                                MolecularHierarchyDecorator::Type t);
 
 class ResidueDecorator;
 
@@ -160,8 +174,8 @@
     \ingroup hierarchy
  */
 IMPDLLEXPORT ResidueDecorator
-get_residue(MolecularHierarchyDecorator mhd,
-            unsigned int index);
+molecular_hierarchy_get_residue(MolecularHierarchyDecorator mhd,
+                                unsigned int index);
 
 
 //! Create a fragment containing the specified nodes
Index: kernel/include/IMP/decorators/bond_decorators.h
===================================================================
--- kernel/include/IMP/decorators/bond_decorators.h	(revision 623)
+++ kernel/include/IMP/decorators/bond_decorators.h	(working copy)
@@ -128,6 +128,8 @@
 IMP_OUTPUT_OPERATOR(BondedDecorator);
 
 
+typedef std::vector<BondDecorator> BondDecorators;
+
 inline BondedDecorator BondDecorator::get_bonded(unsigned int i) const
 {
   Particle *p= graph_get_node(get_particle(), i,
Index: kernel/include/IMP/decorators/yaml.h
===================================================================
--- kernel/include/IMP/decorators/yaml.h	(revision 0)
+++ kernel/include/IMP/decorators/yaml.h	(revision 0)
@@ -0,0 +1,49 @@
+#ifndef IMP_DECORATORS_YAML_H
+#define IMP_DECORATORS_YAML_H
+#include "../Particle.h"
+#include "../Model.h"
+
+namespace IMP
+{
+
+  //! Write the particle to a stream as a YAML stream
+  /** \param[in] p The particle to write
+      \param[in] out The stream to write to
+      \param[in] indent The base level of indentation
+   */
+  IMPDLLEXPORT void write_yaml(Particle *p,
+                               std::ostream &out= std::cout,
+                               std::string indent="");
+
+//! Write the model to a stream as a YAML stream
+  /** \param[in] m The model to write
+      \param[in] out The stream to write to
+      \param[in] indent The base level of indentation
+   */
+  IMPDLLEXPORT void write_yaml(Model *m,
+                               std::ostream &out= std::cout,
+                               std::string indent="");
+
+  //! Read the particle from a YAML stream
+  /** The model must already have particles matching all read particles.
+      Currently the particles must already have the same attributes
+      as are being read, but this probably should change due to lists
+      stored in attributes.
+
+      The intentended usage model is that the model (with restraints) is
+      initialized. Optimization is performed and then the model is written
+      out to a file. Some time later, when you want to reload the model, 
+      you can reuse the initialization code to set up the restraints,
+      and then read in the values for the attributes.
+      
+      \note The base indent is determined from the first line. */
+  IMPDLLEXPORT void read_yaml(std::istream &in,
+                              Model *m);
+
+  //! primarily for debuggin*/
+  IMPDLLEXPORT void read_yaml(std::string contents,
+                              Model *m);
+
+}
+
+#endif
Index: kernel/include/IMP/decorators/HierarchyDecorator.h
===================================================================
--- kernel/include/IMP/decorators/HierarchyDecorator.h	(revision 623)
+++ kernel/include/IMP/decorators/HierarchyDecorator.h	(working copy)
@@ -9,16 +9,17 @@
 #ifndef __IMP_HIERARCHY_DECORATOR_H
 #define __IMP_HIERARCHY_DECORATOR_H
 
-#include <limits>
-#include <vector>
-#include <deque>
-
 #include "../Particle.h"
 #include "../Model.h"
 #include "../DecoratorBase.h"
 #include "../internal/ArrayOnAttributesHelper.h"
 #include "utility.h"
+#include "bond_decorators.h"
 
+#include <limits>
+#include <vector>
+#include <deque>
+
 namespace IMP
 {
 
@@ -326,6 +327,71 @@
 }
 
 
+namespace internal
+{
+  template <class K, class V>
+  struct MatchAttribute {
+    K k_;
+    V v_;
+    MatchAttribute(K k, V v): k_(k), v_(v){}
+    bool operator()(Particle *o) {
+      if (!o->has_attribute(k_)) return false;
+      else return o->get_value(k_) == v_;
+    }
+  };
+}
+
+//! Gather all the Particle* in the hierarchy which match on an attribute
+/** \ingroup hierarchy
+ */
+template <class Out, class K, class V>
+Out hierarchy_gather_by_attribute(HierarchyDecorator h, K k,
+                                  V v, Out out)
+{
+  internal::Gather<internal::MatchAttribute<K, V>,Out>
+    gather(internal::MatchAttribute<K,V>(k,v),
+           out);
+  depth_first_traversal(h, gather);
+  return gather.get_out();
+}
+
+
+namespace internal
+{
+  template <class K0, class V0, class K1, class V1>
+  struct MatchAttributes {
+    K0 k0_;
+    V0 v0_;
+    K1 k1_;
+    V1 v1_;
+    MatchAttributes(K0 k0, V0 v0,
+                    K1 k1, V1 v1): k0_(k0), v0_(v0),
+                                   k1_(k1), v1_(v1){}
+    bool operator()(Particle *o) {
+      if (!o->has_attribute(k0_)) return false;
+      else if (o->get_value(k0_) != v0_) return false;
+      else if (!o->has_attribute(k1_)) return false;
+      else if (o->get_value(k1_) != v1_) return false;
+      return true;
+    }
+  };
+}
+
+//! Gather all the Particle* in the hierarchy which match on two attributes
+/** \ingroup hierarchy
+ */
+template <class Out, class K0, class V0, class K1, class V1>
+Out hierarchy_gather_by_attributes(HierarchyDecorator h, K0 k0,
+                                   V0 v0, K1 k1, V1 v1, Out out)
+{
+  internal::Gather<internal::MatchAttributes<K0, V0, K1, V1>,Out>
+    gather(internal::MatchAttributes<K0,V0, K1, V1>(k0,v0, k1, v1),
+           out);
+  depth_first_traversal(h, gather);
+  return gather.get_out();
+}
+
+
 //! Find the first node which matches some criteria
 /** \ingroup hierarchy
  */
@@ -352,6 +418,21 @@
   return HD();
 }
 
+
+
+//! Get all the leaves of the bit of hierarchy
+IMPDLLEXPORT Particles
+hierarchy_get_leaves(HierarchyDecorator mhd);
+
+//! Get the bonds internal to this tree
+IMPDLLEXPORT BondDecorators
+hierarchy_get_internal_bonds(HierarchyDecorator mhd);
+
+//! Get all the particles in the subtree
+IMPDLLEXPORT Particles
+hierarchy_get_all_descendants(HierarchyDecorator mhd);
+
+
 namespace internal
 {
 
Index: kernel/include/IMP/restraints/PairListRestraint.h
===================================================================
--- kernel/include/IMP/restraints/PairListRestraint.h	(revision 623)
+++ kernel/include/IMP/restraints/PairListRestraint.h	(working copy)
@@ -39,6 +39,10 @@
   void add_particle_pair(ParticlePair p);
   void clear_particle_pairs();
   void add_particle_pairs(const ParticlePairs &ps);
+  void set_particle_pairs(const ParticlePairs &ps) {
+    clear_particle_pairs();
+    add_particle_pairs(ps);
+  }
 
 protected:
   Pointer<PairScore> ss_;
Index: kernel/include/IMP/restraints/BondDecoratorRestraint.h
===================================================================
--- kernel/include/IMP/restraints/BondDecoratorRestraint.h	(revision 623)
+++ kernel/include/IMP/restraints/BondDecoratorRestraint.h	(working copy)
@@ -16,12 +16,11 @@
 #include "../internal/kernel_version_info.h"
 #include "../Pointer.h"
 #include "../UnaryFunction.h"
+#include "../score_states/ManualBondDecoratorListScoreState.h"
 
 namespace IMP
 {
 
-class BondDecoratorListScoreState;
-
 //! Restrain all pairs of non-bonded particles
 /** This restraint currently only works for bonds which have their 
     length set explicitly. Eventually we should add a table for standard
@@ -40,7 +39,8 @@
       \param[in] bl The BondDecoratorListScoreState to use to get the list
       of bonds.
    */
-  BondDecoratorRestraint(UnaryFunction *f, BondDecoratorListScoreState *bl);
+  BondDecoratorRestraint(UnaryFunction *f,
+                         ManualBondDecoratorListScoreState *bl);
   virtual ~BondDecoratorRestraint(){}
 
   IMP_RESTRAINT(internal::kernel_version_info)
@@ -48,7 +48,7 @@
   void set_function(UnaryFunction *f) {f_=f;}
 
 protected:
-  BondDecoratorListScoreState *bl_;
+  Pointer<ManualBondDecoratorListScoreState> bl_;
   Pointer<UnaryFunction> f_;
 };
 
Index: kernel/include/IMP/restraints/NonbondedRestraint.h
===================================================================
--- kernel/include/IMP/restraints/NonbondedRestraint.h	(revision 623)
+++ kernel/include/IMP/restraints/NonbondedRestraint.h	(working copy)
@@ -16,12 +16,11 @@
 #include "../internal/kernel_version_info.h"
 #include "../Pointer.h"
 #include "../score_states/NonbondedListScoreState.h"
+#include "../PairScore.h"
 
 namespace IMP
 {
 
-class PairScore;
-
 //! Apply a PairScore to all nonbonded pairs of particles
 /**
    \ingroup restraint
Index: kernel/include/IMP/score_states/CoverBondsScoreState.h
===================================================================
--- kernel/include/IMP/score_states/CoverBondsScoreState.h	(revision 623)
+++ kernel/include/IMP/score_states/CoverBondsScoreState.h	(working copy)
@@ -9,7 +9,7 @@
 #define __IMP_COVER_BONDS_SCORE_STATE_H
 
 #include "../ScoreState.h"
-#include "BondDecoratorListScoreState.h"
+#include "ManualBondDecoratorListScoreState.h"
 #include "../internal/kernel_version_info.h"
 #include "../Pointer.h"
 
@@ -30,13 +30,13 @@
  */
 class IMPDLLEXPORT CoverBondsScoreState: public ScoreState
 {
-  Pointer<BondDecoratorListScoreState> bl_;
+  Pointer<ManualBondDecoratorListScoreState> bl_;
   FloatKey rk_;
 public:
   /** Get the list of bonds from the BondDecoratorListScoreState. This list is
       not owned and update is not called on this list automatically.
    */
-  CoverBondsScoreState(BondDecoratorListScoreState *bl,
+  CoverBondsScoreState(ManualBondDecoratorListScoreState *bl,
                        FloatKey rk=FloatKey("radius"));
   ~CoverBondsScoreState();
 
Index: kernel/include/IMP/score_states/BondDecoratorListScoreState.h
===================================================================
--- kernel/include/IMP/score_states/BondDecoratorListScoreState.h	(revision 623)
+++ kernel/include/IMP/score_states/BondDecoratorListScoreState.h	(working copy)
@@ -8,25 +8,21 @@
 #ifndef __IMP_BOND_DECORATOR_LIST_SCORE_STATE_H
 #define __IMP_BOND_DECORATOR_LIST_SCORE_STATE_H
 
-#include "BondedListScoreState.h"
+#include "ManualBondDecoratorListScoreState.h"
 #include "../decorators/bond_decorators.h"
 
 #include <vector>
 
 namespace IMP
 {
-
-class BondDecoratorListScoreState;
-typedef Index<BondDecoratorListScoreState> BondDecoratorListIndex;
-
 //! Keep track of particles that are connected by BondDecorator bonds.
 /** We also may want to add lazy rescanning of bonds rather than doing
     it every update call and a faster lookup of bonds.
     \ingroup bond
  */
-class IMPDLLEXPORT BondDecoratorListScoreState: public BondedListScoreState
+class IMPDLLEXPORT BondDecoratorListScoreState:
+    public ManualBondDecoratorListScoreState
 {
-  std::vector<BondDecorator> bonds_;
   Particles ps_;
 public:
   //! Find bonds amongst the following points. 
@@ -36,24 +32,8 @@
   virtual ~BondDecoratorListScoreState(){}
 
   virtual void set_particles(const Particles &ps);
+  virtual void add_particles(const Particles &ps);
 
-  virtual bool are_bonded(Particle *a, Particle *b) const;
-
-  //! This iterates through the pairs of bonded particles
-  /** \note update() must be called first for this to be valid.
-   */
-  typedef std::vector<BondDecorator>::const_iterator BondIterator;
-  BondIterator bonds_begin() const {
-    return bonds_.begin();
-  }
-  BondIterator bonds_end() const {
-    return bonds_.end();
-  }
-
-  unsigned int get_number_of_bonds() const {
-    return bonds_.size();
-  }
-
 protected:
   virtual void do_before_evaluate();
 };
Index: kernel/include/IMP/score_states/MaxChangeScoreState.h
===================================================================
--- kernel/include/IMP/score_states/MaxChangeScoreState.h	(revision 623)
+++ kernel/include/IMP/score_states/MaxChangeScoreState.h	(working copy)
@@ -22,6 +22,9 @@
     float attribute keys and keeps track of the maximum amount
     any of these have changed since the last time reset was called.
 
+    \todo Move the stored bits back into this class out of the
+    attributes.
+
  */
 class IMPDLLEXPORT MaxChangeScoreState: public ScoreState
 {
Index: kernel/include/IMP/score_states/ManualBondDecoratorListScoreState.h
===================================================================
--- kernel/include/IMP/score_states/ManualBondDecoratorListScoreState.h	(revision 0)
+++ kernel/include/IMP/score_states/ManualBondDecoratorListScoreState.h	(revision 0)
@@ -0,0 +1,50 @@
+/**
+ *  \file BondDecoratorListScoreState.h
+ *  \brief Allow iteration through pairs of a set of atoms.
+ *
+ *  Copyright 2007-8 Sali Lab. All rights reserved.
+ */
+
+#ifndef __IMP_MANUAL_BOND_DECORATOR_LIST_SCORE_STATE_H
+#define __IMP_MANUAL_BOND_DECORATOR_LIST_SCORE_STATE_H
+
+#include "BondedListScoreState.h"
+#include "../decorators/bond_decorators.h"
+
+#include <vector>
+
+namespace IMP
+{
+
+class ManualBondDecoratorListScoreState;
+typedef Index<ManualBondDecoratorListScoreState> BondDecoratorListIndex;
+
+//! Keep track of particles that are connected by BondDecorator bonds.
+/** This class just keeps track of the bonds it has been told about.
+    Use the non-manual version if you want auto discovery of bonds.
+    \ingroup bond
+ */
+class IMPDLLEXPORT ManualBondDecoratorListScoreState: 
+    public BondedListScoreState
+{
+ public:
+  //! Find bonds amongst the following points. 
+  /** \param [in] ps The set of particles to use.
+   */
+  ManualBondDecoratorListScoreState(const BondDecorators &ps= BondDecorators());
+  virtual ~ManualBondDecoratorListScoreState(){}
+
+  virtual void set_particles(const Particles &ps) {}
+  virtual void add_particles(const Particles &ps) {}
+
+  IMP_LIST(public, BondDecorator, bond_decorator, BondDecorator);
+
+  virtual bool are_bonded(Particle *a, Particle *b) const;
+
+protected:
+  virtual void do_before_evaluate() {}
+};
+
+} // namespace IMP
+
+#endif  /* __IMP_BOND_DECORATOR_LIST_SCORE_STATE_H */
Index: kernel/include/IMP/optimizers/states/VRMLLogOptimizerState.h
===================================================================
--- kernel/include/IMP/optimizers/states/VRMLLogOptimizerState.h	(revision 623)
+++ kernel/include/IMP/optimizers/states/VRMLLogOptimizerState.h	(working copy)
@@ -14,8 +14,13 @@
 #include "../../IMP_config.h"
 #include "../../base_types.h"
 #include "../../OptimizerState.h"
+#include "../../ParticleRefiner.h"
 #include "../../internal/kernel_version_info.h"
+#include "../../Vector3D.h"
 
+#include <boost/tuple/tuple.hpp>
+#include <map>
+
 namespace IMP
 {
 
@@ -50,39 +55,38 @@
   //! The float key to use for the radius
   /** Particles without such an attribute are drawn as fixed sized markers.
    */
-  void set_radius(FloatKey k) {
+  void set_radius_key(FloatKey k) {
     radius_=k;
   }
+
   //! The three color components
   /** Color values should be between 0 and 1. They will be snapped if needed.
    */
-  void set_color(FloatKey r, FloatKey g, FloatKey b) {
-    r_=r; g_=g; b_=b;
+  void set_color_key(IntKey k) {
+    color_=k;
   }
 
-  //! Set the particles to use.
-  void set_particles(const Particles &pis) {
-    pis_=pis;
-  }
+  //! Add a value to the color mappre
+  void set_color(int c, Vector3D v);
+
+  IMP_LIST(public, Particle, particle, Particle*);
+  IMP_CONTAINER(ParticleRefiner, particle_refiner, ParticleRefinerIndex);
+
   //! Force it to write the next file
   void write_next_file();
 
   void write(std::string name) const;
 
+protected:
   //! A helper function to just write a list of particles to a file
-  static void write(const Particles &pis,
-                    FloatKey radius, FloatKey r,
-                    FloatKey g, FloatKey b,
-                    std::ostream &out);
-
-protected:
-  Particles pis_;
+  void write(std::ostream &out, const Particles &ps) const;
   std::string filename_;
   int file_number_;
   int call_number_;
   int skip_steps_;
   FloatKey radius_;
-  FloatKey r_, g_, b_;
+  IntKey color_;
+  std::map<int, Vector3D > colors_;
 };
 
 } // namespace IMP
Index: kernel/include/IMP/Vector3D.h
===================================================================
--- kernel/include/IMP/Vector3D.h	(revision 623)
+++ kernel/include/IMP/Vector3D.h	(working copy)
@@ -124,6 +124,15 @@
     out << "(" << operator[](0) << ", " << operator[](1) << ", "
         << operator[](2) << ")";
   }
+
+  bool operator<(const Vector3D &o) const {
+    for (unsigned int i=0; i< 3; ++i) {
+      if (operator[](i) < o[i]) return true;
+      else if (operator[](i) > o[i]) return false;
+    }
+    return false;
+  }
+
 private:
   Float vec_[3];
 };
Index: kernel/test/particle_refiners/test_bond_pr.py
===================================================================
--- kernel/test/particle_refiners/test_bond_pr.py	(revision 623)
+++ kernel/test/particle_refiners/test_bond_pr.py	(working copy)
@@ -10,8 +10,8 @@
     def _set_up_stuff(self, n):
         # return [model, particles, bonds]
         m= IMP.Model()
-        ps= self.create_particles_in_box(m)
-        bds= self.create_chain(ps, 10)
+        ps= IMP.test.create_particles_in_box(m)
+        bds= IMP.test.create_chain(ps, 10)
         bl= IMP.BondDecoratorListScoreState(ps)
         ss= IMP.CoverBondsScoreState(bl, rk)
         m.add_score_state(bl)
Index: kernel/test/decorators/test_yaml.py
===================================================================
--- kernel/test/decorators/test_yaml.py	(revision 0)
+++ kernel/test/decorators/test_yaml.py	(revision 0)
@@ -0,0 +1,47 @@
+import unittest
+import IMP
+import IMP.test
+
+class YamlTests(IMP.test.TestCase):
+    def _create_model(self):
+        IMP.set_log_level(IMP.VERBOSE)
+        m = IMP.Model()
+        p= IMP.Particle()
+        m.add_particle(p)
+        IMP.XYZDecorator.create(p)
+        p= IMP.Particle()
+        m.add_particle(p)
+        IMP.XYZDecorator.create(p)
+        return m
+    def test_yaml(self):
+        """Check writing to yaml """
+        m= self._create_model()
+        IMP.write_yaml(m)
+    def test_read(self):
+        """Check reading from yaml"""
+        m= self._create_model()
+        st="""particle: 0
+  float-attributes:
+    x: 0
+    y: 1
+    z: 2
+  int-attributes:
+  string-attributes:
+  particle-attributes:
+particle: 1
+  float-attributes:
+    x: 3
+    y: 4
+    z: 5
+  int-attributes:
+  string-attributes:
+  particle-attributes:
+"""
+        IMP.read_yaml(st, m)
+        IMP.write_yaml(m)
+
+
+
+
+if __name__ == '__main__':
+    unittest.main()
Index: kernel/test/restraints/test_angles.py
===================================================================
--- kernel/test/restraints/test_angles.py	(revision 623)
+++ kernel/test/restraints/test_angles.py	(working copy)
@@ -31,7 +31,7 @@
             m.add_particle(p)
             d= IMP.XYZDecorator.create(p)
             l0.append(p)
-        self.randomize_particles(l0, 20)
+        IMP.test.randomize_particles(l0, 20)
         return l0
 
     def create_angle_r(self, s, ps):
Index: kernel/test/connectivity/test_connectivity.py
===================================================================
--- kernel/test/connectivity/test_connectivity.py	(revision 623)
+++ kernel/test/connectivity/test_connectivity.py	(working copy)
@@ -56,7 +56,7 @@
         o = IMP.ConjugateGradients()
         o.set_threshold(1e-4)
         o.set_model(m)
-        self.randomize_particles(m.get_particles(), 50.0)
+        IMP.test.randomize_particles(m.get_particles(), 50.0)
 
         # add connectivity restraints
 
Index: kernel/test/modeller/test_pdb_read.py
===================================================================
--- kernel/test/modeller/test_pdb_read.py	(revision 623)
+++ kernel/test/modeller/test_pdb_read.py	(working copy)
@@ -33,7 +33,7 @@
         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)
+        rd= IMP.molecular_hierarchy_get_residue(mp, 29)
         self.assertEqual(rd.get_index(), 29);
 
     def test_bonds(self):
@@ -41,8 +41,8 @@
         m = IMP.Model()
         mp= IMP.pdb.read_pdb('modeller/single_protein.pdb', m)
         #mp= IMP.MolecularHierarchyDecorator.cast(p)
-        all_atoms= IMP.get_particles(mp,
-                                     IMP.MolecularHierarchyDecorator.ATOM);
+        all_atoms= IMP.molecular_hierarchy_get_by_type(mp,
+                                                       IMP.MolecularHierarchyDecorator.ATOM);
         self.assertEqual(1221, all_atoms.size(),
                          "Wrong number of atoms found in protein")
 
Index: kernel/test/states/test_vrml_log.py
===================================================================
--- kernel/test/states/test_vrml_log.py	(revision 623)
+++ kernel/test/states/test_vrml_log.py	(working copy)
@@ -7,7 +7,7 @@
         IMP.test.TestCase.setUp(self)
         IMP.set_log_level(IMP.TERSE)
 
-    def _testit(self, rk, r,g,b, pref):
+    def _testit(self, rk, pref):
         """Test logging to a VRML file"""
         m= IMP.Model()
         o= IMP.SteepestDescent()
@@ -24,15 +24,11 @@
         p1= IMP.Particle()
         m.add_particle(p1)
         d1= IMP.XYZDecorator.create(p1)
-        p1.add_attribute(r, 1.0, False)
-        p1.add_attribute(g, 0.0, False)
-        p1.add_attribute(b, 0.0, False)
         d1.set_x(1)
         d1.set_y(1)
         d1.set_z(1)
         a= IMP.VRMLLogOptimizerState(nm, IMP.Particles([p0,p1]))
-        a.set_radius(rk)
-        a.set_color(r, g, b)
+        a.set_radius_key(rk)
         o.add_optimizer_state(a)
         a.update()
 
@@ -41,16 +37,11 @@
     def test_1(self):
         """Testing the VRML log"""
         self._testit(IMP.FloatKey("radius"),
-                     IMP.FloatKey("red"),
-                     IMP.FloatKey("green"),
-                     IMP.FloatKey("blue"), "test1")
+                     "test1")
 
     def test_2(self):
         """Testing the VRML log with new attribute names"""
         self._testit(IMP.FloatKey("another_radius"),
-                     IMP.FloatKey("red5"),
-                     IMP.FloatKey("green5"),
-                     IMP.FloatKey("blue5"),
                      "test1")
     def test_skip(self):
         """Test skipping steps in the VRML log"""
Index: kernel/test/states/test_nonbonded_list.py
===================================================================
--- kernel/test/states/test_nonbonded_list.py	(revision 623)
+++ kernel/test/states/test_nonbonded_list.py	(working copy)
@@ -64,7 +64,7 @@
         self.do_test_bi_update(ss)
 
     def make_spheres(self, m, num, lbv, ubv, minr, maxr):
-        ps=self.create_particles_in_box(m, num, lbv, ubv)
+        ps=IMP.test.create_particles_in_box(m, num, lbv, ubv)
         for p in ps:
             p.add_attribute(self.rk, random.uniform(minr, maxr), False)
         return ps
@@ -119,8 +119,8 @@
         #IMP.set_log_level(IMP.TERSE)
         m= IMP.Model()
         ps=IMP.Particles()
-        ps= self.create_particles_in_box(m, 20, [0,0,0], [10,10,10])
-        pts= self.create_particles_in_box(m, 20, [160,160,160], [170,170,170])
+        ps= IMP.test.create_particles_in_box(m, 20, [0,0,0], [10,10,10])
+        pts= IMP.test.create_particles_in_box(m, 20, [160,160,160], [170,170,170])
         for p in pts:
             ps.append(p)
         md=15
Index: kernel/test/optimizers/test_sd_optimizer.py
===================================================================
--- kernel/test/optimizers/test_sd_optimizer.py	(revision 623)
+++ kernel/test/optimizers/test_sd_optimizer.py	(working copy)
@@ -70,7 +70,7 @@
 
         # Start off with all particles in close proximity (but not actually
         # colocated, as the derivative of zero distance is zero):
-        self.randomize_particles(self.particles, .01)
+        IMP.test.randomize_particles(self.particles, .01)
 
         self.steepest_descent.optimize(50)
 
Index: kernel/pyext/IMP.i
===================================================================
--- kernel/pyext/IMP.i	(revision 623)
+++ kernel/pyext/IMP.i	(working copy)
@@ -192,13 +192,14 @@
 %include "IMP/Particle.h"
 %include "Vector3D.i"
 %include "IMP/DecoratorBase.h"
+%include "IMP/decorators/bond_decorators.h"
 %include "IMP/decorators/HierarchyDecorator.h"
 %include "IMP/decorators/MolecularHierarchyDecorator.h"
 %include "IMP/decorators/NameDecorator.h"
 %include "IMP/decorators/ResidueDecorator.h"
 %include "IMP/decorators/XYZDecorator.h"
-%include "IMP/decorators/bond_decorators.h"
 %include "IMP/decorators/AtomDecorator.h"
+%include "IMP/decorators/yaml.h"
 %include "IMP/ParticleRefiner.h"
 %include "IMP/particle_refiners/BondCoverParticleRefiner.h"
 %include "IMP/particle_refiners/ChildrenParticleRefiner.h"
@@ -229,6 +230,7 @@
 %include "IMP/score_states/MaxChangeScoreState.h"
 %include "IMP/score_states/NonbondedListScoreState.h"
 %include "IMP/score_states/AllNonbondedListScoreState.h"
+%include "IMP/score_states/ManualBondDecoratorListScoreState.h"
 %include "IMP/score_states/BondDecoratorListScoreState.h"
 %include "IMP/score_states/BipartiteNonbondedListScoreState.h"
 %include "IMP/score_states/GravityCenterScoreState.h"
@@ -269,6 +271,8 @@
   %template(ScoreStates) ::std::vector<ScoreState*>;
   %template(OptimizerStates) ::std::vector<OptimizerState*>;
   %template(ParticleIndexes) ::std::vector<ParticleIndex>;
+  %template(BondDecorators) ::std::vector<BondDecorator>;
+  %template(MolecularHiearchyDecorators) ::std::vector<MolecularHierarchyDecorator>;
   %template(FloatKeys) ::std::vector<FloatKey>;
   %template(StringKeys) ::std::vector<StringKey>;
   %template(IntKeys) ::std::vector<IntKey>;