Index: kernel/src/restraints/AnglesRestraint.cpp
===================================================================
--- kernel/src/restraints/AnglesRestraint.cpp	(revision 0)
+++ kernel/src/restraints/AnglesRestraint.cpp	(revision 0)
@@ -0,0 +1,91 @@
+/**
+ *  \file AnglesRestraint.cpp \brief Angles restraint.
+ *
+ *  Copyright 2007-8 Sali Lab. All rights reserved.
+ *
+ */
+
+#include "IMP/restraints/AnglesRestraint.h"
+#include "IMP/decorators/XYZDecorator.h"
+#include "IMP/Particle.h"
+#include "IMP/Model.h"
+#include "IMP/log.h"
+#include "IMP/Vector3D.h"
+#include "IMP/UnaryFunction.h"
+
+#include <cmath>
+
+namespace IMP
+{
+
+AnglesRestraint::AnglesRestraint(UnaryFunction* score_func)
+{
+  score_func_ = std::auto_ptr<UnaryFunction>(score_func);
+  clear_chains();
+}
+
+void AnglesRestraint::add_chain(const Particles &ps)
+{
+  if (ps.size() <3) {
+    IMP_WARN("Adding a chain of length 2 or less to the AnglesRestraint"
+             << " doesn't accomplish anything."<< std::endl);
+  } else {
+    Restraint::add_particles(ps);
+    chain_splits_.back()= Restraint::number_of_particles();
+    chain_splits_.push_back(Restraint::number_of_particles());
+  }
+}
+
+Float AnglesRestraint::evaluate(DerivativeAccumulator *accum)
+{
+  int cur_break=0;
+  unsigned int i=2;
+  float score=0;
+  while (i < Restraint::number_of_particles()) {
+    /*IMP_LOG(VERBOSE, "Chain eval on " 
+            << Restraint::get_particle(i-2)->get_index()
+            << Restraint::get_particle(i-1)->get_index()
+            << Restraint::get_particle(i)->get_index()
+            << " split is " << chain_splits_[cur_break]
+            << std::endl);*/
+    score += internal::evaluate_angle_restraint(Restraint::get_particle(i-2),
+                                                Restraint::get_particle(i-1),
+                                                Restraint::get_particle(i),
+                                                score_func_.get(),
+                                                accum);
+    if (chain_splits_[cur_break] == i) {
+      i+=3;
+      ++cur_break;
+    } else {
+      ++i;
+    }
+  } 
+  return score;
+}
+
+void AnglesRestraint::clear_chains() {
+  Restraint::clear_particles();
+  chain_splits_.clear();
+  chain_splits_.push_back(0);
+}
+
+
+//! Show the current restraint.
+/** \param[in] out Stream to send restraint description to.
+ */
+void AnglesRestraint::show(std::ostream& out) const
+{
+  if (get_is_active()) {
+    out << "angles restraint (active):" << std::endl;
+  } else {
+    out << "angles restraint (inactive):" << std::endl;
+  }
+
+  out << "  version: " << version() << "  ";
+  out << "  last_modified_by: " << last_modified_by() << std::endl;
+  out << "  " << chain_splits_.size()-1 << " chains" << std::endl;
+  score_func_->show(out);
+  out << std::endl;
+}
+
+}  // namespace IMP
Index: kernel/include/IMP/restraints/AnglesRestraint.h
===================================================================
--- kernel/include/IMP/restraints/AnglesRestraint.h	(revision 0)
+++ kernel/include/IMP/restraints/AnglesRestraint.h	(revision 0)
@@ -0,0 +1,51 @@
+/**
+ *  \file AnglesRestraint.h   \brief Restraint the angles between particles.
+ *
+ *  Copyright 2007-8 Sali Lab. All rights reserved.
+ *
+ */
+
+#ifndef __IMP_ANGLES_RESTRAINT_H
+#define __IMP_ANGLES_RESTRAINT_H
+
+#include "../IMP_config.h"
+#include "../Restraint.h"
+#include "AngleRestraint.h"
+#include <vector>
+
+namespace IMP
+{
+
+class UnaryFunction;
+
+//! Restraint the angles between particles
+/** Currently the particles can be added as chains and the angle
+    of each three successive particles in the chain is restrained.
+    \ingroup restraint
+ */
+class IMPDLLEXPORT AnglesRestraint : public Restraint
+{
+public:
+  //! Create the angle restraint.
+  /** \param[in] score_func Scoring function for the restraint.
+   */
+  AnglesRestraint(UnaryFunction* score_func);
+  virtual ~AnglesRestraint(){}
+
+  IMP_RESTRAINT("0.5", "Daniel Russel");
+
+  //! Add a chain of particles
+  /** Each three successive particles are restrained*/
+  void add_chain(const Particles &ps);
+
+  //! Clear all the stored chains
+  void clear_chains();
+
+protected:
+    std::auto_ptr<UnaryFunction> score_func_;
+    std::vector<unsigned int> chain_splits_;
+};
+
+} // namespace IMP
+
+#endif  /* __IMP_ANGLES_RESTRAINT_H */
Index: kernel/test/restraints/test_angles.py
===================================================================
--- kernel/test/restraints/test_angles.py	(revision 0)
+++ kernel/test/restraints/test_angles.py	(revision 0)
@@ -0,0 +1,76 @@
+import unittest
+import IMP
+import IMP.test
+import IMP.utils
+import math
+
+class One(IMP.UnaryFunction):
+    def __init__(self):
+        IMP.UnaryFunction.__init__(self)
+    def __call__(self, *args):
+        return 1
+    def show(self, *args):
+        print "identity"
+
+
+class AngleRestraintTests(IMP.test.TestCase):
+    """Tests for angle restraints"""
+    def setUp(self):
+        # for some reason objects get destroyed even though
+        # python doesn't own them
+        self.stupid_hack=[]
+
+    def create_particles(self, m, n):
+        l0=IMP.Particles()
+        for i in range(0,n):
+            p= IMP.Particle()
+            m.add_particle(p)
+            d= IMP.XYZDecorator.create(p)
+            l0.append(p)
+        self.randomize_particles(l0, 20)
+        return l0
+
+    def create_angle_r(self, s, ps):
+        print s.thisown
+        for i in range(2, len(ps)):
+            print str(i)
+            l= One()
+            self.stupid_hack.append(l)
+            r= IMP.AngleRestraint(ps[i-2],ps[i-1], ps[i], l)
+            s.add_restraint(r)
+            #print r.evaluate(None)
+            #print r.thisown
+            #print l.thisown
+            #print s.evaluate(None)
+        print s.evaluate(None)
+
+    def test_score(self):
+        """Check score of angles restraints"""
+        IMP.set_log_level(IMP.VERBOSE)
+        m=IMP.Model()
+        l0= self.create_particles(m, 3)
+        l1= self.create_particles(m, 10)
+        l2= self.create_particles(m, 2)
+        l= One()
+        r= IMP.AnglesRestraint(l)
+        r.add_chain(l0)
+        r.add_chain(l1)
+        r.add_chain(l2)
+        m.add_restraint(r)
+        s= IMP.RestraintSet("angle restraints")
+        m.add_restraint(s)
+        print "creating angle restraints"
+        self.create_angle_r(s, l0)
+        self.create_angle_r(s, l1)
+        self.create_angle_r(s, l2)
+        ss= s.evaluate(None)
+        rs= r.evaluate(None)
+        diff = ss-rs
+        print ss
+        print rs
+        if (diff <0): diff=-diff
+        self.assert_(diff < .001, "The restraints are not equal")
+
+
+if __name__ == '__main__':
+    unittest.main()