Index: kernel/include/IMP/decorators/HierarchyDecorator.h =================================================================== --- kernel/include/IMP/decorators/HierarchyDecorator.h (revision 589) +++ kernel/include/IMP/decorators/HierarchyDecorator.h (working copy) @@ -16,12 +16,33 @@ #include "../Particle.h" #include "../Model.h" #include "../DecoratorBase.h" +#include "../internal/ArrayOnAttributesHelper.h" #include "utility.h" namespace IMP { +class HierarchyDecorator; +namespace internal +{ +// needs to be external to keep swig happy +struct IMPDLLEXPORT ChildArrayTraits { + static ParticleKey parent_key_; + static IntKey parent_index_key_; + + typedef ParticleKey Key; + typedef Particle* Value; + typedef HierarchyDecorator ExternalType; + static void on_add(Particle * p, HierarchyDecorator d, unsigned int i) ; + static void on_change(Particle *, HierarchyDecorator d, unsigned int oi, + unsigned int ni) ; + static void on_remove(Particle *, HierarchyDecorator d) ; + static Particle *get_value(HierarchyDecorator d) ; + static unsigned int get_index(Particle *, HierarchyDecorator d); +}; +} + /** \defgroup hierarchy Hierarchies of particles These functions and classes aid in manipulating particles representing molecules at multiple levels. @@ -49,12 +70,14 @@ */ class IMPDLLEXPORT HierarchyDecorator: public DecoratorBase { - IMP_DECORATOR(HierarchyDecorator, DecoratorBase, return true || p, ++p); - IMP_DECORATOR_ARRAY_DECL(child, Particle, Particle*, NULL) -protected: - static ParticleKey parent_key_; - static IntKey parent_index_key_; + friend class internal::ChildArrayTraits; + + IMP_DECORATOR_ARRAY_DECL(public, child, children, internal::ChildArrayTraits) + + IMP_DECORATOR(HierarchyDecorator, DecoratorBase, + return has_required_attributes_for_child(p), + add_required_attributes_for_child(p)); public: //! Get a HierarchyDecorator wrapping the parent particle @@ -62,48 +85,33 @@ if it has no parent. */ This get_parent() const { - IMP_DECORATOR_GET(parent_key_, Particle*, + IMP_DECORATOR_GET(internal::ChildArrayTraits::parent_key_, Particle*, return VALUE, return This()); } - //! Get the number of children. - unsigned int get_number_of_children() const { - // defined by the array macro - return internal_get_number_of_child(); - } - - //! Get a HierarchyDecorator of the ith child - /** \return decorator of the ith child, or throw an IndexException if it - does not have this child - */ - This get_child(unsigned int i) const { - // defined by the array macro - return cast(internal_get_child(i)); - - } - //! Get the index of this particle in the list of children /** \return index in the list of children of the parent, or -1 if it does not have a parent. */ int get_parent_index() const { - IMP_DECORATOR_GET(parent_index_key_, Int, return VALUE, return -1); + IMP_DECORATOR_GET(internal::ChildArrayTraits::parent_index_key_, + Int, return VALUE, return -1); } //! Return true if it has a parent. bool has_parent() const { - return get_particle()->has_attribute(parent_key_); + return get_particle()->has_attribute( + internal::ChildArrayTraits::parent_key_); } - //! Add the particle as the last child. - unsigned int add_child(HierarchyDecorator hd); - //! Get the index of a specific child in this particle. /** This takes linear time. + \note This is mostly useful for debugging as you can always call + get_parent_index() on the child. \return the index, or -1 if there is no such child. */ - int get_child_index(Particle *c) const; + int get_child_index(HierarchyDecorator c) const; //! Do some simple validity checks on this node in the hierarchy void validate_node() const; @@ -314,6 +322,67 @@ return gather.get_out(); } + +//! Find the first node which matches some criteria +/** \ingroup hierarchy + */ +template +HD hierarchy_find(HD h, F f) +{ + if (f(h.get_particle())) return h; + std::vector stack; + stack.push_back(h); + //d.show(std::cerr); + do { + HD cur= stack.back(); + stack.pop_back(); + + for (int i=cur.get_number_of_children()-1; i>=0; --i) { + HD hd= cur.get_child(i); + if (f(hd.get_particle())) { + return hd; + } else { + stack.push_back(hd); + } + } + } while (!stack.empty()); + return HD(); +} + +namespace internal +{ + +inline void ChildArrayTraits::on_add(Particle * p, + HierarchyDecorator d, + unsigned int i) { + d.get_particle()->add_attribute(parent_key_, p); + d.get_particle()->add_attribute(parent_index_key_, i); +} + +inline void ChildArrayTraits::on_change(Particle *, + HierarchyDecorator d, + unsigned int oi, + unsigned int ni) { + d.get_particle()->set_value(parent_index_key_, ni); +} + +inline void ChildArrayTraits::on_remove(Particle *, + HierarchyDecorator d) { + d.get_particle()->remove_attribute(parent_index_key_); + d.get_particle()->remove_attribute(parent_key_); +} + +inline Particle *ChildArrayTraits::get_value(HierarchyDecorator d) { + return d.get_particle(); +} + +inline unsigned int ChildArrayTraits::get_index(Particle *, + HierarchyDecorator d) { + return d.get_parent_index(); +} +} + + } // namespace IMP #endif /* __IMP_HIERARCHY_DECORATOR_H */ Index: kernel/include/IMP/decorators/macros.h =================================================================== --- kernel/include/IMP/decorators/macros.h (revision 589) +++ kernel/include/IMP/decorators/macros.h (working copy) @@ -7,8 +7,9 @@ */ #ifndef __IMP_DECORATOR_MACROS_H -#define __IMP_DECORATOR_MACROS_H +#define __IMP_DECORATOR_MACROS_H +#include //! Define the basic things needed by a Decorator. /** The key things this defines are a default constructor, a static create @@ -66,6 +67,9 @@ static Name cast(::IMP::Particle *p) { \ return IMP::DecoratorBase::cast(p); \ } \ + static bool is_instance_of(::IMP::Particle *p) { \ + return has_required_attributes(p); \ + } \ /** Write information about this decorator to out. Each line should \ prefixed by prefix*/ \ void show(std::ostream &out=std::cout, \ @@ -177,57 +181,84 @@ This macro should go in the header and IMP_DECORATOR_ARRAY_CPP into the .cpp and IMP_DECORATOR_ARRAY_INIT in the initialize_static_data function - To use the array, use functions + The macro defines a set of functions for using the array: + - get_name(unsigned int) - - Type internal_get_name(unsigned int i) + - get_number_of_name() - - void internal_add_name(Type) + - add_name(Traits::ExternalType) - - unsigned int internal_get_number_of_name() const + - add_name_at(Traits::ExternalType, unsigned int) + + - remove_name(unsigned int) + + in addition it defines the private methods + - has_required_attributes_for_name(Particle *) + + - add_required_attributes_for_name(Particle *) */ -#define IMP_DECORATOR_ARRAY_DECL(name, TypeName, Type, Default) \ - protected: \ - static IntKey number_of_##name##_key_; \ - static std::vector name##_keys_; \ - static void generate_##name##_keys(unsigned int i); \ - static const TypeName##Key get_##name##_key(unsigned int i) { \ - if (i >= name##_keys_.size()) generate_##name##_keys(i); \ - return name##_keys_[i]; \ - } \ - Type internal_get_##name(unsigned int i) const{ \ - IMP_DECORATOR_GET(get_##name##_key(i), Type, \ - return VALUE, \ - throw IndexException("Particle missing attribute"); \ - return Default); \ - } \ - int internal_add_##name(Type t); \ - unsigned int internal_get_number_of_##name() const { \ - IMP_DECORATOR_GET(number_of_##name##_key_, \ - Int, return VALUE, return 0); \ - } \ +#define IMP_DECORATOR_ARRAY_DECL(protection, name, plural, Traits) \ +private: \ + static internal::ArrayOnAttributesHelper name##_data_; \ + static bool has_required_attributes_for_##name(Particle *p) { \ + return name##_data_.has_required_attributes(p); \ + } \ + static void add_required_attributes_for_##name(Particle *p) { \ + return name##_data_.add_required_attributes(p); \ + } \ +protection: \ + /** \brief Get the ith member*/ \ + Traits::ExternalType get_##name(unsigned int i) const { \ + return Traits::ExternalType(name##_data_.get_value(get_particle(), i)); \ + } \ + /** \brief Get the total number of them*/ \ + unsigned int get_number_of_##plural() const { \ + return name##_data_.get_size(get_particle()); \ + } \ + /** \brief Add t at the end */ \ + unsigned int add_##name(Traits::ExternalType t) { \ + unsigned int i= name##_data_.push_back(get_particle(), \ + Traits::get_value(t)); \ + Traits::on_add(get_particle(), t, i); \ + return i; \ + } \ + /** Add t at a certain position */ \ + void add_##name##_at(Traits::ExternalType t, unsigned int idx) { \ + name##_data_.insert(get_particle(), \ + idx, \ + Traits::get_value(t)); \ + Traits::on_add(get_particle(), t, idx); \ + for (unsigned int i= idx+1; i < get_number_of_##plural(); ++i) { \ + Traits::on_change(get_particle(), \ + name##_data_.get_value( get_particle(), i), \ + i-1, i); \ + } \ + } \ + /** Remove t from the array */ \ + void remove_##name(Traits::ExternalType t) { \ + unsigned int idx= Traits::get_index(get_particle(), t); \ + Traits::on_remove(get_particle(), t); \ + name##_data_.erase(get_particle(), \ + idx); \ + for (unsigned int i= idx; i < get_number_of_##plural(); ++i) { \ + Traits::on_change(get_particle(), \ + name##_data_.get_value(get_particle(), i), \ + i+1, i); \ + } \ + } //! See IMP_DECORATOR_ARRAY_DECL -#define IMP_DECORATOR_ARRAY_DEF(DecoratorType, name, TypeName, Type) \ - IntKey DecoratorType##Decorator::number_of_##name##_key_; \ - std::vector DecoratorType##Decorator::name##_keys_; \ - void DecoratorType##Decorator::generate_##name##_keys(unsigned int i) \ - { \ - while (!(i < name##_keys_.size())) { \ - std::ostringstream oss; \ - oss << #DecoratorType " " #name " " << name##_keys_.size(); \ - name##_keys_.push_back(TypeName##Key(oss.str().c_str())); \ - } \ - } \ - int DecoratorType##Decorator::internal_add_##name(Type t) { \ - int nc= internal_get_number_of_##name(); \ - get_particle()->add_attribute(get_##name##_key(nc), t); \ - IMP_DECORATOR_SET(number_of_##name##_key_, nc+1); \ - return nc; \ - } +#define IMP_DECORATOR_ARRAY_DEF(DecoratorType, name, Traits) \ + internal::ArrayOnAttributesHelper \ + DecoratorType::name##_data_(std::string(#name)+ " " #DecoratorType); + + //! See IMP_DECORATOR_ARRAY_DECL -#define IMP_DECORATOR_ARRAY_INIT(DecoratorType, name, TypeName, Type) \ - number_of_##name##_key_= IntKey(#DecoratorType " num " #name); +#define IMP_DECORATOR_ARRAY_INIT(DecoratorType, name) \ + name##_data_.initialize(); #endif /* __IMP_DECORATOR_MACROS_H */ Index: kernel/include/IMP/decorators/MolecularHierarchyDecorator.h =================================================================== --- kernel/include/IMP/decorators/MolecularHierarchyDecorator.h (revision 589) +++ kernel/include/IMP/decorators/MolecularHierarchyDecorator.h (working copy) @@ -29,9 +29,7 @@ HierarchyDecorator, return P::has_required_attributes(p) && p->has_attribute(type_key_), - { P::add_required_attributes(p); - p->add_attribute(type_key_, UNKNOWN); - }); + {p->add_attribute(type_key_, UNKNOWN);}); protected: typedef HierarchyDecorator P; static IntKey type_key_; @@ -70,6 +68,8 @@ return "nucleic acid"; case CHAIN: return "chain"; + case FRAGMENT: + return "fragment"; case PROTEIN: return "protein"; case NUCLEOTIDE: @@ -102,6 +102,21 @@ return P::add_child(o); } + //! Add a child and check that the types are appropriate + /** A child must have a type that is listed before the parent in the + Type enum list. + */ + void add_child_at(This o, unsigned int i) { + IMP_check(get_type() > o.get_type(), + "Parent type must subsume child type", + InvalidStateException("")); + IMP_check(get_type() != UNKNOWN, "Parent must have known type", + InvalidStateException("")); + IMP_check(o.get_type() != UNKNOWN, "Child must have known type", + InvalidStateException("")); + P::add_child_at(o, i); + } + //! Get a child MolecularHierarchyDecorator get_child(unsigned int i) const { HierarchyDecorator hd= P::get_child(i); @@ -120,7 +135,9 @@ }; +typedef std::vector MolecularHierarchyDecorators; + /** Gather all the molecular particles of a certain level in the molecular hierarchy @@ -129,6 +146,37 @@ IMPDLLEXPORT Particles get_particles(MolecularHierarchyDecorator mhd, MolecularHierarchyDecorator::Type t); +class ResidueDecorator; + +//! Get the residue with the specified index +/** Fine the residue with the appropriate index. This is the PDB index, + not the offset in the chain (if they are different). + + \throw ValueException if mhd's type is not one of CHAIN, PROTEIN, NUCLEOTIDE + \return MolecularHierarchyDecorator() if that residue is not found. + + \todo We can make this method much more clever in its search since + most proteins consist of a few contiguous blocks of indices. + + \ingroup hierarchy + */ +IMPDLLEXPORT ResidueDecorator +get_residue(MolecularHierarchyDecorator mhd, + unsigned int index); + + +//! Create a fragment containing the specified nodes +/** A particle representing the frament is created and initialized. + + The Fragment is inserted as a child of the parent (and the particles are + removed). The particles become children of the frament. + + \throw ValueException If all the particles do not have the same parent. + */ +IMPDLLEXPORT MolecularHierarchyDecorator +create_fragment(const MolecularHierarchyDecorators &ps); + + } // namespace IMP #endif /* __IMP_MOLECULAR_HIERARCHY_DECORATOR_H */ Index: kernel/include/IMP/decorators/bond_decorators.h =================================================================== --- kernel/include/IMP/decorators/bond_decorators.h (revision 589) +++ kernel/include/IMP/decorators/bond_decorators.h (working copy) @@ -84,7 +84,9 @@ */ class IMPDLLEXPORT BondedDecorator: public DecoratorBase { - IMP_DECORATOR(BondedDecorator, DecoratorBase, return true, ); + IMP_DECORATOR(BondedDecorator, DecoratorBase, + return internal::graph_is_node(p, internal::bond_graph_data_), + graph_initialize_node(p, internal::bond_graph_data_)); public: Index: kernel/include/IMP/internal/graph_base.h =================================================================== --- kernel/include/IMP/internal/graph_base.h (revision 589) +++ kernel/include/IMP/internal/graph_base.h (working copy) @@ -13,6 +13,7 @@ #include "../Particle.h" #include "../Model.h" +#include "ArrayOnAttributesHelper.h" namespace IMP { @@ -21,23 +22,32 @@ { /** \internal */ -struct IMPDLLEXPORT GraphData +struct IMPDLLEXPORT GraphData: + public ArrayOnAttributesHelper { - GraphData() {} - GraphData(const char *prefix): prefix_(prefix) { - node_keys_[0]=ParticleKey((prefix_+" node 0").c_str()); - node_keys_[1]=ParticleKey((prefix_+" node 1").c_str()); - num_edges_key_= IntKey((prefix_+" num edges").c_str()); + typedef ArrayOnAttributesHelper P; + GraphData(): P("") {} + GraphData(std::string prefix): P(prefix) { + node_keys_[0]=ParticleKey((P::get_prefix()+" node 0").c_str()); + node_keys_[1]=ParticleKey((P::get_prefix()+" node 1").c_str()); + P::initialize(); } ParticleKey node_keys_[2]; - IntKey num_edges_key_; - mutable std::vector edge_keys_; - std::string prefix_; }; + /** \internal */ +IMPDLLEXPORT void graph_initialize_node(Particle* a, + const GraphData &d); + +/** \internal */ +IMPDLLEXPORT bool graph_is_node(Particle* a, + const GraphData &d); + + +/** \internal */ IMPDLLEXPORT Particle* graph_connect(Particle* a, Particle* b, - const GraphData &d); + GraphData &d); /** \internal */ IMPDLLEXPORT void graph_disconnect(Particle* bond, Index: kernel/include/IMP/internal/ArrayOnAttributesHelper.h =================================================================== --- kernel/include/IMP/internal/ArrayOnAttributesHelper.h (revision 0) +++ kernel/include/IMP/internal/ArrayOnAttributesHelper.h (revision 0) @@ -0,0 +1,134 @@ +/** + * \file array_on_attributes.h + * \brief Various methods for managing an array of attributes + * + * Copyright 2007-8 Sali Lab. All rights reserved. + * + */ + +#ifndef __IMP_ARRAY_ON_ATTRIBUTES_H +#define __IMP_ARRAY_ON_ATTRIBUTES_H + +#include "../base_types.h" + +#include +#include + +namespace IMP +{ + +namespace internal +{ + +template +struct ArrayOnAttributesHelper { + ArrayOnAttributesHelper(std::string p): prefix_(p) {} + void initialize() { + num_key_= IntKey((prefix_ + " number").c_str()); + } + typedef KeyT Key; + typedef ValueT Value; + + unsigned int get_size(const Particle *p) const { + return p->get_value(num_key_); + } + + void initialize_particle(Particle *p) { + p->add_attribute(num_key_, 0); + } + + Value get_value(const Particle *p, unsigned int i) const { + IMP_check(keys_.size() > i, "Out of range attribute in array", + IndexException("out of range")); + IMP_check(static_cast(p->get_value(num_key_)) > i, + "Out of range attribute in array", + IndexException("out of range")); + return p->get_value(keys_[i]); + } + + void set_value(Particle *p, + unsigned int i, + Value v) const { + IMP_check(keys_.size() > i, "Out of range attribute in array", + IndexException("out of range")); + IMP_check(p->get_value(num_key_) > i, "Out of range attribute in array", + IndexException("out of range")); + p->set_value(keys_[i], v); + } + + unsigned int push_back(Particle *p, + Value v) { + unsigned int osz= p->get_value(num_key_); + Key k= get_key(osz); + p->add_attribute(k, v); + p->set_value(num_key_, osz+1); + return osz; + } + + void insert(Particle *p, + unsigned int loc, + Value v) { + unsigned int osz= p->get_value(num_key_); + IMP_check(loc <= osz, "Attribute array must be contiguous", + IndexException("out of range")); + for (unsigned int i=loc; i < osz; ++i) { + Key k= get_key(i); + Value t= p->get_value(k); + p->set_value(k, v); + v=t; + } + Key k= get_key(osz); + p->add_attribute(k, v); + p->set_value(num_key_, osz+1); + } + + + void erase(Particle *p, + unsigned int loc) const { + unsigned int osz= p->get_value(num_key_); + IMP_check(loc <= osz, "Can only erase values in array", + IndexException("out of range")); + for (unsigned int i=loc+1; i < osz; ++i) { + Key k= keys_[i]; + Key kl= keys_[i-1]; + p->set_value(kl, p->get_value(k)); + } + Key k= keys_[osz-1]; + p->remove_attribute(k); + p->set_value(num_key_, osz-1); + } + + std::string get_prefix() const { + return prefix_; + } + + + bool has_required_attributes(Particle *p) const { + return p->has_attribute(num_key_); + } + + void add_required_attributes(Particle *p) const { + p->add_attribute(num_key_, 0); + } + +private: + Key get_key(unsigned int i) { + while (!(i < keys_.size())) { + std::ostringstream oss; + oss << prefix_ << keys_.size(); + keys_.push_back(Key(oss.str().c_str())); + } + return keys_[i]; + } + + + std::vector keys_; + IntKey num_key_; + std::string prefix_; +}; + +} + +} + +#endif Index: kernel/include/IMP/Particle.h =================================================================== --- kernel/include/IMP/Particle.h (revision 589) +++ kernel/include/IMP/Particle.h (working copy) @@ -46,6 +46,8 @@ optimization, mark all of its attributes as being non-optimizable (set_is_optimized method). + A particle may only belong to one model. + \ingroup kernel */ class IMPDLLEXPORT Particle : public internal::RefCountedObject @@ -368,7 +370,6 @@ // Set pointer to model particle data. void set_model(Model *md, ParticleIndex pi); - // all of the particle data internal::ObjectPointer model_; // true if particle is active Index: kernel/src/decorators/HierarchyDecorator.cpp =================================================================== --- kernel/src/decorators/HierarchyDecorator.cpp (revision 589) +++ kernel/src/decorators/HierarchyDecorator.cpp (working copy) @@ -6,19 +6,22 @@ * */ -#include - #include "IMP/decorators/HierarchyDecorator.h" #include "IMP/decorators/NameDecorator.h" +#include + namespace IMP { -IMP_DECORATOR_ARRAY_DEF(Hierarchy, child, Particle, Particle*); -ParticleKey HierarchyDecorator::parent_key_; -IntKey HierarchyDecorator::parent_index_key_; +IMP_DECORATOR_ARRAY_DEF(HierarchyDecorator, child, + internal::ChildArrayTraits); +namespace internal +{ +ParticleKey ChildArrayTraits::parent_key_; +IntKey ChildArrayTraits::parent_index_key_; +} - void HierarchyDecorator::validate_node() const { //get_particle()->get_model()->show(std::cerr); @@ -32,15 +35,6 @@ "Incorrect parent index in particle " << *get_particle()); } - for (unsigned int i=0; i< get_number_of_children(); ++i) { - IMP_assert(get_particle()->has_attribute(get_child_key(i)), - "Recorded and actual number of children don't match -- " - "too few actual"); - } - IMP_assert(!get_particle()->has_attribute( - get_child_key(get_number_of_children())), - "Recorded and actual number of children don't match -- " - "too many actual"); } void HierarchyDecorator::show(std::ostream &, std::string) const @@ -81,42 +75,23 @@ } -int HierarchyDecorator::get_child_index(Particle *c) const +int HierarchyDecorator::get_child_index(HierarchyDecorator c) const { for (unsigned int i=0; i< get_number_of_children(); ++i ) { - if (get_child(i) == HierarchyDecorator(c)) return i; + if (get_child(i) == c) return i; } return -1; } - -unsigned int HierarchyDecorator::add_child(HierarchyDecorator hd) -{ - IMP_assert(hd.get_particle() != get_particle(), - "A particle can't be its own child " << *this << std::endl - << hd); - //std::cerr << *get_particle() << std::endl; - //std::cerr << *p << std::endl; - //std::cerr << "changing " << std::endl; - //std::cerr << "before\n"; - //show_hierarchy(*this, std::cerr); - int nc= internal_add_child(hd.get_particle()); - - hd.get_particle()->add_attribute(parent_index_key_, nc); - hd.get_particle()->add_attribute(parent_key_, get_particle()); - //std::cerr << "after\n"; - //show_hierarchy(*this, std::cerr); - return nc; -} - - IMP_DECORATOR_INITIALIZE(HierarchyDecorator, DecoratorBase, { - parent_key_ = ParticleKey("hierarchy_parent"); - parent_index_key_ = IntKey("hiearchy_parent_index"); + internal::ChildArrayTraits::parent_key_ + = ParticleKey("hierarchy_parent"); + internal::ChildArrayTraits::parent_index_key_ + = IntKey("hiearchy_parent_index"); IMP_DECORATOR_ARRAY_INIT(HierarchyDecorator, - child, Particle, Particle*); + child); }) Index: kernel/src/decorators/MolecularHierarchyDecorator.cpp =================================================================== --- kernel/src/decorators/MolecularHierarchyDecorator.cpp (revision 589) +++ kernel/src/decorators/MolecularHierarchyDecorator.cpp (working copy) @@ -53,7 +53,7 @@ }) -namespace internal +namespace { struct MHDMatchingType @@ -78,9 +78,79 @@ MolecularHierarchyDecorator::Type t) { Particles out; - hierarchy_gather(mhd, internal::MHDMatchingType(t), + hierarchy_gather(mhd, MHDMatchingType(t), std::back_inserter(out)); return out; } + +namespace +{ + +struct MatchResidueIndex +{ + unsigned int index_; + MatchResidueIndex(unsigned int i): index_(i) {} + bool operator()(Particle *p) const { + MolecularHierarchyDecorator mhd(p); + if (mhd.get_type() == MolecularHierarchyDecorator::RESIDUE + || mhd.get_type() == MolecularHierarchyDecorator::NUCLEICACID) { + ResidueDecorator rd(p); + return (rd.get_index() == index_); + } else { + return false; + } + } +}; + +} + + +ResidueDecorator get_residue(MolecularHierarchyDecorator mhd, + unsigned int index) { + IMP_check(mhd.get_type() == MolecularHierarchyDecorator::PROTEIN + || mhd.get_type() == MolecularHierarchyDecorator::CHAIN + || mhd.get_type() == MolecularHierarchyDecorator::NUCLEOTIDE, + "Invalid type of MolecularHierarchyDecorator passed to get_residue", + ValueException("Bad val")); + MatchResidueIndex mi(index); + HierarchyDecorator hd= hierarchy_find(mhd, mi); + if (hd== HierarchyDecorator()) { + return ResidueDecorator(); + } else { + return ResidueDecorator(hd.get_particle()); + } +} + + + +MolecularHierarchyDecorator +create_fragment(const MolecularHierarchyDecorators &ps) { + IMP_check(!ps.empty(), "Need some particles", + ValueException("")); + MolecularHierarchyDecorator parent= ps[0].get_parent(); + unsigned int index= ps[0].get_parent_index(); + IMP_IF_CHECK(CHEAP) { + for (unsigned int i=0; i< ps.size(); ++i) { + IMP_check(ps[i].get_parent() == parent, + "Parents don't match", + ValueException("")); + } + } + + Particle *fp= new Particle(); + parent.get_particle()->get_model()->add_particle(fp); + MolecularHierarchyDecorator fd= MolecularHierarchyDecorator::create(fp); + fd.set_type(MolecularHierarchyDecorator::FRAGMENT); + + for (unsigned int i=0; i< ps.size(); ++i) { + parent.remove_child(ps[i]); + fd.add_child(ps[i]); + } + + parent.add_child_at(fd, index); + return fd; +} + + } // namespace IMP Index: kernel/src/internal/graph_base.cpp =================================================================== --- kernel/src/internal/graph_base.cpp (revision 589) +++ kernel/src/internal/graph_base.cpp (working copy) @@ -15,22 +15,19 @@ namespace internal { -static void graph_add_edge_key(unsigned int i, const GraphData &d) -{ - while (i >= d.edge_keys_.size()) { - std::ostringstream oss; - oss << d.prefix_ << " edge " << i; - d.edge_keys_.push_back(ParticleKey(oss.str().c_str())); - } +IMPDLLEXPORT void graph_initialize_node(Particle* a, + const GraphData &d) { + d.add_required_attributes(a); } -static ParticleKey graph_get_edge_key(unsigned int i, const GraphData &d) -{ - if (i >= d.edge_keys_.size()) graph_add_edge_key(i, d); - return d.edge_keys_[i]; +/** \internal */ +IMPDLLEXPORT bool graph_is_node(Particle* a, + const GraphData &d) { + return d.has_required_attributes(a); } -Particle* graph_connect(Particle* a, Particle* b, const GraphData &d) + +Particle* graph_connect(Particle* a, Particle* b, GraphData &d) { Model *m= a->get_model(); Particle *p= new Particle(); @@ -39,18 +36,7 @@ p->add_attribute(d.node_keys_[1], b); for (int i=0; i< 2; ++i) { Particle *cp=((i==0)?a:b); - int nc= graph_get_number_of_edges(cp, d); - ParticleKey nm=graph_get_edge_key(nc, d); - if (!cp->has_attribute(nm)) { - cp->add_attribute(nm, p); - } else { - cp->set_value(nm, p); - } - if (cp->has_attribute(d.num_edges_key_)) { - cp->set_value(d.num_edges_key_, nc+1); - } else { - cp->add_attribute(d.num_edges_key_, nc+1); - } + d.push_back(cp, p); } return a->get_model()->get_particle(pi); @@ -63,21 +49,12 @@ 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 { - Particle* v = p[i]->get_value(graph_get_edge_key(j, d)); - p[i]->set_value(graph_get_edge_key(j+shift, d), v); + for (unsigned int j=0; j< d.get_size(p[i]); ++j) { + if (d.get_value(p[i], j) == e) { + d.erase(p[i], j); + break; } } - p[i]->remove_attribute(graph_get_edge_key(nc-1, d)); - 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); e->get_model()->remove_particle(e->get_index()); @@ -87,14 +64,12 @@ Particle* graph_get_edge(Particle* a, int i, const GraphData &d) { - ParticleKey nm= graph_get_edge_key(i, d); - return a->get_value(nm); + return d.get_value(a,i); } Particle* graph_get_neighbor(Particle* a, int i, const GraphData &d) { - ParticleKey nm= graph_get_edge_key(i, d); - Particle *edge= a->get_value(nm); + Particle *edge= d.get_value(a,i); if (graph_get_node(edge, 0, d) == a) { return graph_get_node(edge, 1, d); } else { @@ -106,11 +81,7 @@ unsigned int graph_get_number_of_edges(Particle *a, const GraphData &d) { - if (a->has_attribute(d.num_edges_key_)) { - return a->get_value(d.num_edges_key_); - } else { - return 0; - } + return d.get_size(a); } Particle* graph_get_node(Particle *a, int i, const GraphData &d) Index: kernel/pyext/IMP/pdb.py =================================================================== --- kernel/pyext/IMP/pdb.py (revision 589) +++ kernel/pyext/IMP/pdb.py (working copy) @@ -43,8 +43,14 @@ mab= b[1] pa=atoms[maa.index] pb=atoms[mab.index] - ba= IMP.BondedDecorator.create(pa); - bb= IMP.BondedDecorator.create(pb); + if IMP.BondedDecorator.is_instance_of(pa): + ba= IMP.BondedDecorator.cast(pa) + else: + ba= IMP.BondedDecorator.create(pa) + if IMP.BondedDecorator.is_instance_of(pb): + bb= IMP.BondedDecorator.cast(pb) + else: + bb= IMP.BondedDecorator.create(pb) bp= IMP.bond(ba, bb, IMP.BondDecorator.COVALENT) def read_pdb(name, model): Index: kernel/test/modeller/test_pdb_read.py =================================================================== --- kernel/test/modeller/test_pdb_read.py (revision 589) +++ kernel/test/modeller/test_pdb_read.py (working copy) @@ -33,6 +33,9 @@ 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) + self.assertEqual(rd.get_index(), 29); + def test_bonds(self): """Check that the file loader produces bonds""" m = IMP.Model() Index: kernel/test/states/test_cover_bonds.py =================================================================== --- kernel/test/states/test_cover_bonds.py (revision 589) +++ kernel/test/states/test_cover_bonds.py (working copy) @@ -19,8 +19,9 @@ IMP.Vector3D(10,10,10)) ps.append(p) bds= [] + bb= IMP.BondedDecorator.create(ps[0]) for i in range(1,n): - ba= IMP.BondedDecorator.create(ps[i-1]) + ba= IMP.BondedDecorator.cast(ps[i-1]) bb= IMP.BondedDecorator.create(ps[i]) bds.append(IMP.custom_bond(ba, bb, 10, 1)) bl= IMP.BondDecoratorListScoreState(ps) Index: kernel/test/decorators/test_hierarchy.py =================================================================== --- kernel/test/decorators/test_hierarchy.py (revision 589) +++ kernel/test/decorators/test_hierarchy.py (working copy) @@ -8,13 +8,13 @@ m = IMP.Model() pp=IMP.Particle() m.add_particle(pp) - ppd= IMP.HierarchyDecorator.cast(pp) + ppd= IMP.HierarchyDecorator.create(pp) ppnd= IMP.NameDecorator.create(pp) ppnd.set_name("root"); for i in range(0,10): pc=IMP.Particle() + m.add_particle(pc) pcd= IMP.HierarchyDecorator.create(pc) - m.add_particle(pc) ppd.add_child(pcd) pcnd= IMP.NameDecorator.create(pc) pcnd.set_name(str("child "+str(i)));