Index: kernel/test/modeller/test_pdb_read.py =================================================================== --- kernel/test/modeller/test_pdb_read.py (revision 319) +++ kernel/test/modeller/test_pdb_read.py (working copy) @@ -36,9 +36,6 @@ IMP.MolecularHierarchyDecorator.ATOM); self.assertEqual(1221, all_atoms.size(), "Wrong number of atoms found in protein") - cc= IMP.get_bonded(IMP.BondedDecorator.cast(all_atoms[0])) - self.assertEqual(cc.size(), all_atoms.size(), - "All atoms in protein are not bonded") if __name__ == '__main__': Index: kernel/test/decorators/test_hierarchy.py =================================================================== --- kernel/test/decorators/test_hierarchy.py (revision 319) +++ kernel/test/decorators/test_hierarchy.py (working copy) @@ -8,7 +8,6 @@ m = IMP.Model() pp=IMP.Particle() m.add_particle(pp) - pp.thisown=0 ppd= IMP.HierarchyDecorator.cast(pp) ppnd= IMP.NameDecorator.create(pp) ppnd.set_name("root"); Index: kernel/test/decorators/test_bonds.py =================================================================== --- kernel/test/decorators/test_bonds.py (revision 0) +++ kernel/test/decorators/test_bonds.py (revision 0) @@ -0,0 +1,35 @@ +import unittest +import IMP +import IMP.test + +class DecoratorTests(IMP.test.TestCase): + def test_bonded(self): + """Check bonds """ + m = IMP.Model() + pa=IMP.Particle() + m.add_particle(pa) + pb=IMP.Particle() + m.add_particle(pb) + da= IMP.BondedDecorator.create(pa) + db= IMP.BondedDecorator.create(pb) + self.assertEqual(da.get_number_of_bonds(), 0, + "Wrong number of bonds on initialization") + IMP.bond(da, db, IMP.BondDecorator.COVALENT) + self.assertEqual(da.get_number_of_bonds(), 1, + "Expected to find a bond") + self.assertEqual(da.get_number_of_bonds(), 1, + "Expected to find a bond") + b= da.get_bond(0) + self.assertEqual(b, db.get_bond(0), "Not same bond object") + self.assertEqual(b.get_type(), IMP.BondDecorator.COVALENT, + "Wrong bond type") + IMP.unbond(b) + self.assertEqual(da.get_number_of_bonds(), 0, + "Expected not to find a bond") + self.assertEqual(da.get_number_of_bonds(), 0, + "Expected not to find a bond") + + + +if __name__ == '__main__': + unittest.main() Index: kernel/include/IMP/utility.h =================================================================== --- kernel/include/IMP/utility.h (revision 319) +++ kernel/include/IMP/utility.h (working copy) @@ -92,7 +92,29 @@ virtual std::string last_modified_by() const {return std::string(lmb_string);} +//! Define the basics needed for an OptimizerState +/** + This macro declares the required functions + - void update() + - void show(std::ostream &out) const + and defines the functions + - version + - last_modified_by + \param[in] version_string The version. + \param[in] lmb_string The person who last modified it. +*/ +#define IMP_OPTIMIZER_STATE(version_string, lmb_string) \ + /** update the state*/ \ + virtual void update(); \ + /** write information about the state to the stream*/ \ + virtual void show(std::ostream &out=std::cout) const; \ + /** \return the current version*/ \ + virtual std::string version() const {return std::string(version_string);} \ + /** \return the last person to modify this restraint */ \ + virtual std::string last_modified_by() const {return std::string(lmb_string);} + + //! Use the swap_with member function to swap two objects #define IMP_SWAP(name) \ inline void swap(name &a, name &b) { \ Index: kernel/include/IMP/decorators/graph_base.h =================================================================== --- kernel/include/IMP/decorators/graph_base.h (revision 319) +++ kernel/include/IMP/decorators/graph_base.h (working copy) @@ -39,6 +39,9 @@ IMPDLLEXPORT Particle* graph_connect(Particle* a, Particle* b, const GraphData &d); +IMPDLLEXPORT void graph_disconnect(Particle* bond, + const GraphData &d); + IMPDLLEXPORT Particle* graph_get_edge(Particle* a, int i, const GraphData &d); Index: kernel/include/IMP/decorators/bond_decorators.h =================================================================== --- kernel/include/IMP/decorators/bond_decorators.h (revision 319) +++ kernel/include/IMP/decorators/bond_decorators.h (working copy) @@ -28,7 +28,6 @@ extern IMPDLLEXPORT GraphData bond_graph_data_; extern IMPDLLEXPORT bool bond_keys_initialized_; -extern IMPDLLEXPORT FloatKey bond_length_key_; extern IMPDLLEXPORT IntKey bond_type_key_; extern IMPDLLEXPORT IntKey bond_order_key_; @@ -49,25 +48,19 @@ public: //! The types a bond can have right now enum Type {UNKNOWN=-1, - COVALENT, HYDROGEN, DISULPHINE, SALT, PEPTIDE + COVALENT, HYDROGEN, DISULPHIDE, SALT, PEPTIDE }; //! Get the atom i of the bond /** \param[in] i 0 or 1 \return BondedDecorator for the atom in question */ - BondedDecorator get_atom(unsigned int i) const ; + BondedDecorator get_bonded(unsigned int i) const ; - - IMP_DECORATOR_GET_SET_OPT(length, internal::bond_length_key_, Float, - Float, -1); - IMP_DECORATOR_GET_SET_OPT(type, internal::bond_type_key_, Int, Int, UNKNOWN); IMP_DECORATOR_GET_SET_OPT(order, internal::bond_order_key_, Int, Int, 1); - - }; IMP_OUTPUT_OPERATOR(BondDecorator); @@ -82,7 +75,7 @@ public: - int get_number_of_bonds() const { + unsigned int get_number_of_bonds() const { return graph_get_number_of_edges(get_particle(), internal::bond_graph_data_); } @@ -102,7 +95,7 @@ IMP_OUTPUT_OPERATOR(BondedDecorator); -BondedDecorator BondDecorator::get_atom(unsigned int i) const +BondedDecorator BondDecorator::get_bonded(unsigned int i) const { Particle *p= graph_get_node(get_particle(), i, internal::bond_graph_data_); @@ -118,10 +111,18 @@ IMPDLLEXPORT BondDecorator bond(BondedDecorator a, BondedDecorator b, Int t); +//! Destroy the bond connecting to particles. +/** \param[in] b The bond. + */ +IMPDLLEXPORT +void unbond(BondDecorator b); -//! Get all the particles connected to the current one via a path of bonds. +//! Get the bond between two particles. +/** + BondDecorator() is returned if the particles are not bonded. + */ IMPDLLEXPORT -Particles get_bonded(BondedDecorator a); +BondDecorator get_bond(BondedDecorator a, BondedDecorator b); } // namespace IMP Index: kernel/src/decorators/bond_decorators.cpp =================================================================== --- kernel/src/decorators/bond_decorators.cpp (revision 319) +++ kernel/src/decorators/bond_decorators.cpp (working copy) @@ -23,14 +23,28 @@ } // namespace internal -void BondDecorator::show(std::ostream &, std::string) const +void BondDecorator::show(std::ostream &out, std::string) const { - + out << "Bond between " + << get_bonded(0).get_particle()->get_index() << " and " + << get_bonded(1).get_particle()->get_index() + << " of type " << get_type() << " and order " << get_order() + << std::endl; } -void BondedDecorator::show(std::ostream &, std::string) const +void BondedDecorator::show(std::ostream &out, std::string) const { - + out << "Particle " << get_particle()->get_index() + << " is bonded to "; + for (unsigned int i=0; i< get_number_of_bonds(); ++i){ + BondDecorator b= get_bond(i); + if (b.get_bonded(0) == *this) { + out << b.get_bonded(1).get_particle()->get_index(); + } else { + out << b.get_bonded(0).get_particle()->get_index(); + } + out << " "; + } } static void bond_initialize_static_data() @@ -38,7 +52,6 @@ if (internal::bond_keys_initialized_) { } else { internal::bond_graph_data_= internal::GraphData("bond"); - internal::bond_length_key_=FloatKey("bond length"); internal::bond_type_key_= IntKey("bond type"); internal::bond_order_key_=IntKey("bond order"); internal::bond_keys_initialized_=true; @@ -62,13 +75,18 @@ return bd; } -Particles get_bonded(BondedDecorator a) -{ - Particles out; - internal::graph_connected_component(a.get_particle(), - internal::bond_graph_data_, - std::back_inserter(out)); - return out; +void unbond(BondDecorator b) { + graph_disconnect(b.get_particle(), internal::bond_graph_data_); } +BondDecorator get_bond(BondedDecorator a, BondedDecorator b) { + for (unsigned int i=0; i < a.get_number_of_bonds(); ++i) { + BondDecorator bd= a.get_bond(i); + if (bd.get_bonded(0) == b || bd.get_bonded(1) == b) { + return bd; + } + } + return BondDecorator(); +} + } // namespace IMP Index: kernel/src/decorators/graph_base.cpp =================================================================== --- kernel/src/decorators/graph_base.cpp (revision 319) +++ kernel/src/decorators/graph_base.cpp (working copy) @@ -37,30 +37,53 @@ ParticleIndex pi=m->add_particle(p); p->add_attribute(d.node_keys_[0], a->get_index().get_index()); p->add_attribute(d.node_keys_[1], b->get_index().get_index()); - { - int nc= graph_get_number_of_edges(a, d); + for (int i=0; i< 2; ++i) { + Particle *cp=((i==0)?a:b); + int nc= graph_get_number_of_edges(cp, d); IntKey nm=graph_get_edge_key(nc, d); - a->add_attribute(nm, p->get_index().get_index()); - if (a->has_attribute(d.num_edges_key_)) { - a->set_value(d.num_edges_key_, nc+1); + if (!cp->has_attribute(nm)) { + cp->add_attribute(nm, p->get_index().get_index()); } else { - a->add_attribute(d.num_edges_key_, nc+1); + cp->set_value(nm, p->get_index().get_index()); } - } - { - int nc= graph_get_number_of_edges(b, d); - IntKey nm=graph_get_edge_key(nc, d); - b->add_attribute(nm, p->get_index().get_index()); - if (b->has_attribute(d.num_edges_key_)) { - b->set_value(d.num_edges_key_, nc+1); + if (cp->has_attribute(d.num_edges_key_)) { + cp->set_value(d.num_edges_key_, nc+1); } else { - b->add_attribute(d.num_edges_key_, nc+1); + cp->add_attribute(d.num_edges_key_, nc+1); } } return a->get_model()->get_particle(pi); } +void graph_disconnect(Particle* e, const GraphData &d) +{ + ParticleIndex pi=e->get_index(); + Particle *p[2]; + 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 { + Int v = p[i]->get_value(graph_get_edge_key(j, d)); + p[i]->set_value(graph_get_edge_key(j+shift, d), v); + } + } + p[i]->set_value(graph_get_edge_key(nc-1, d), -1); + 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); +} + + + Particle* graph_get_edge(Particle* a, int i, const GraphData &d) { IntKey nm= graph_get_edge_key(i, d);