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 + +namespace IMP +{ + +AnglesRestraint::AnglesRestraint(UnaryFunction* score_func) +{ + score_func_ = std::auto_ptr(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 + +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 score_func_; + std::vector 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()