Index: kernel/include/IMP/decorators/XYZDecorator.h
===================================================================
--- kernel/include/IMP/decorators/XYZDecorator.h	(revision 441)
+++ kernel/include/IMP/decorators/XYZDecorator.h	(working copy)
@@ -41,7 +41,7 @@
                 });
 
 protected:
-  static FloatKey key_[3];
+  static FloatKeys key_;
 
 public:
   IMP_DECORATOR_GET_SET(x, key_[0], Float, Float);
@@ -81,6 +81,21 @@
                     b.get_coordinate(1) - get_coordinate(1),
                     b.get_coordinate(2) - get_coordinate(2));
   }
+
+  //! Get a vector containing the keys for x,y,z
+  /** This is quite handy for initializing movers and things.
+   */
+  const FloatKeys get_xyz_keys() const {
+    decorator_initialize_static_data();
+    return key_;
+  }
+
+  //! Generate random coordinates in a sphere centered at the vector
+  void randomize_in_sphere(const Vector3D &center, float radius);
+
+  //! Generate random coordinates in a box defined by the vectors
+  void randomize_in_box(const Vector3D &lower_corner,
+                        const Vector3D &upper_corner);
 protected:
   static FloatKey get_coordinate_key(unsigned int i) {
     IMP_check(i <3, "Out of range coordinate",
Index: kernel/src/decorators/XYZDecorator.cpp
===================================================================
--- kernel/src/decorators/XYZDecorator.cpp	(revision 441)
+++ kernel/src/decorators/XYZDecorator.cpp	(working copy)
@@ -5,17 +5,19 @@
  *
  */
 
-#include <sstream>
+#include "IMP/decorators/XYZDecorator.h"
+#include "IMP/random.h"
+
+#include <boost/random/uniform_real.hpp>
+
 #include <cmath>
 
-#include "IMP/decorators/XYZDecorator.h"
-
 namespace IMP
 {
 
 // These aren't statically initialized, as that way they may be initialized
 // before the table that caches them
-FloatKey XYZDecorator::key_[3];
+FloatKeys XYZDecorator::key_(3);
 
 void XYZDecorator::show(std::ostream &out, std::string prefix) const
 {
@@ -24,7 +26,32 @@
 
 }
 
+void XYZDecorator::randomize_in_sphere(const Vector3D &center,
+                                       float radius) {
+  IMP_check(radius > 0, "Radius in randomize must be postive",
+            ValueException("Radius must be positive"));
+  Vector3D min(center[0]-radius, center[1]-radius, center[2]-radius);
+  Vector3D max(center[0]+radius, center[1]+radius, center[2]+radius);
+  float norm;
+  do {
+    randomize_in_box(min, max);
+    norm=0;
+    for (int i=0; i< 3; ++i) {
+      norm+= square(center[i]-get_coordinate(i));
+    }
+    norm = std::sqrt(norm);
+  } while (norm > radius);
+}
 
+void XYZDecorator::randomize_in_box(const Vector3D &min,
+                                    const Vector3D &max) {
+  for (unsigned int i=0; i< 3; ++i) {
+    IMP_check(min[i] < max[i], "Box for randomize must be non-empty",
+              ValueException("Box must be non-empty"));
+    ::boost::uniform_real<> rand(min[i], max[i]);
+    set_coordinate(i, rand(random_number_generator));
+  }
+}
 
 IMP_DECORATOR_INITIALIZE(XYZDecorator, DecoratorBase,
                          {
Index: kernel/test/states/test_nonbonded_list.py
===================================================================
--- kernel/test/states/test_nonbonded_list.py	(revision 441)
+++ kernel/test/states/test_nonbonded_list.py	(working copy)
@@ -31,9 +31,8 @@
             p= IMP.Particle()
             m.add_particle(p)
             d=IMP.XYZDecorator.create(p)
-            d.set_x(random.uniform(0,10))
-            d.set_y(random.uniform(0,10))
-            d.set_z(random.uniform(0,10))
+            d.randomize_in_box(IMP.Vector3D(0,0,0),
+                               IMP.Vector3D(10,10,10));
         s= IMP.AllNonbondedListScoreState(m.get_particles())
         m.add_score_state(s)
         o= OnePair()
@@ -83,13 +82,11 @@
             d=IMP.XYZDecorator.create(p)
             ps.append(p)
             if (i < 25):
-                d.set_x(random.uniform(0,10))
-                d.set_y(random.uniform(0,10))
-                d.set_z(random.uniform(0,10))
+                d.randomize_in_box(IMP.Vector3D(0,0,0),
+                                   IMP.Vector3D(10,10,10));
             else:
-                d.set_x(random.uniform(60,70))
-                d.set_y(random.uniform(60,70))
-                d.set_z(random.uniform(60,70))
+                d.randomize_in_box(IMP.Vector3D(60,60,60),
+                                   IMP.Vector3D(70,70,70));
         s= IMP.AllNonbondedListScoreState(ps)
         m.add_score_state(s)
         o= OnePair()
@@ -106,9 +103,8 @@
             p= IMP.Particle()
             m.add_particle(p)
             d=IMP.XYZDecorator.create(p)
-            d.set_x(random.uniform(0,10))
-            d.set_y(random.uniform(0,10))
-            d.set_z(random.uniform(0,10))
+            d.randomize_in_box(IMP.Vector3D(0,0,0),
+                               IMP.Vector3D(10,10,10));
             if (i < 5):
                 ps0.append(p)
             else:
@@ -128,9 +124,8 @@
             p= IMP.Particle()
             m.add_particle(p)
             d=IMP.XYZDecorator.create(p)
-            d.set_x(random.uniform(0,10))
-            d.set_y(random.uniform(0,10))
-            d.set_z(random.uniform(0,10))
+            d.randomize_in_box(IMP.Vector3D(0,0,0),
+                               IMP.Vector3D(10,10,10));
             p.add_attribute(rk, i, False)
             d.set_coordinates_are_optimized(True)
         s= IMP.AllSphereNonbondedListScoreState(m.get_particles(), rk)
@@ -148,9 +143,8 @@
             p= IMP.Particle()
             m.add_particle(p)
             d=IMP.XYZDecorator.create(p)
-            d.set_x(random.uniform(0,10))
-            d.set_y(random.uniform(0,10))
-            d.set_z(random.uniform(0,10))
+            d.randomize_in_box(IMP.Vector3D(0,0,0),
+                               IMP.Vector3D(10,10,10));
             p.add_attribute(rk, random.uniform(0,1000), False)
             d.set_coordinates_are_optimized(True)
         s= IMP.AllSphereNonbondedListScoreState(m.get_particles(), rk)