From a5e1745cd10191790757934a8fa3c3575f00842f Mon Sep 17 00:00:00 2001 From: Marco Biasini <marco.biasini@unibas.ch> Date: Mon, 21 Mar 2011 18:58:00 +0100 Subject: [PATCH] improve calculation of ResidueImpl::GetIndex Previously we were returning the wrong index for residues in chains that contained a certain residue number more than once. We were always returning the index of the first residue. Among other things, this fixes BZDNG-229. --- modules/mol/base/src/impl/chain_impl.cc | 93 +++++++++++++++-------- modules/mol/base/src/impl/chain_impl.hh | 12 +-- modules/mol/base/src/impl/residue_impl.cc | 3 +- modules/mol/base/tests/test_residue.cc | 16 ++++ 4 files changed, 88 insertions(+), 36 deletions(-) diff --git a/modules/mol/base/src/impl/chain_impl.cc b/modules/mol/base/src/impl/chain_impl.cc index 854b3d850..e0f51ada1 100644 --- a/modules/mol/base/src/impl/chain_impl.cc +++ b/modules/mol/base/src/impl/chain_impl.cc @@ -154,7 +154,7 @@ void ChainImpl::DeleteAllResidues() { } void ChainImpl::DeleteResidue(const ResNum& number) { - int index=this->GetIndex(number); + int index=this->GetIndexForResNum(number); if (index>=0) { ResidueImplPtr r=residue_list_[index]; r->DeleteAllAtoms(); @@ -166,7 +166,13 @@ void ChainImpl::DeleteResidue(const ResNum& number) { void ChainImpl::DeleteResidue(const ResidueImplPtr& residue) { if (residue->GetChain().get()!=this) return; - this->DeleteResidue(residue->GetNumber()); + int index=this->GetIndex(residue); + if (index>=0) { + ResidueImplPtr r=residue_list_[index]; + r->DeleteAllAtoms(); + residue_list_.erase(residue_list_.begin()+index); + this->UpdateShifts(); + } } ResidueImplPtr ChainImpl::AppendResidue(const ResidueKey& key, @@ -220,7 +226,7 @@ ResidueImplPtr ChainImpl::GetPrev(const ResidueImplPtr& r) const { if (!r) return ResidueImplPtr(); - int index=this->GetIndex(r->GetNumber())-1; + int index=this->GetIndex(r)-1; if (index>-1 && index<static_cast<int>(residue_list_.size())-1) { return residue_list_[index]; } @@ -256,7 +262,7 @@ ResidueImplPtr ChainImpl::GetNext(const ResidueImplPtr& r) const { if (!r) return ResidueImplPtr(); - int index=this->GetIndex(r->GetNumber())+1; + int index=this->GetIndex(r)+1; if (index>0 && index<=static_cast<int>(residue_list_.size())-1) { return residue_list_[index]; } @@ -282,7 +288,7 @@ void ChainImpl::Apply(EntityVisitor& v) ResidueImplPtr ChainImpl::FindResidue(const ResNum& number) const { - int index=this->GetIndex(number); + int index=this->GetIndexForResNum(number); bool invalid=index<0 || index>static_cast<int>(residue_list_.size())-1; return invalid ? ResidueImplPtr() : residue_list_[index]; } @@ -301,36 +307,63 @@ EntityImplPtr ChainImpl::GetEntity() const { return ent_.lock(); } - -int ChainImpl::GetIndex(const ResNum& number) const +int ChainImpl::GetIndexForResNum(const ResNum& number) const { - if (in_sequence_) { - int pos=number.GetNum()-1; - std::list<Shift>::const_iterator i; - for (i=shifts_.begin(); i!=shifts_.end(); ++i) { - const Shift& s=*i; - if (pos<s.start) { - break; - } else if (pos<s.start+s.shift) { - return -1; - } - pos-=s.shift; - } - while (pos>=0 && pos<static_cast<int>(residue_list_.size()) && - residue_list_[pos]->GetNumber()<number) { - pos++; - } - if (pos<0 || pos>=static_cast<int>(residue_list_.size())) { - return -1; - } - assert(residue_list_[pos]->GetNumber()==number); - return pos; + return this->GetIndexForResNumInSequence(number); } else { - ResidueImplList::const_iterator k; + ResidueImplList::const_iterator k; k=std::find_if(residue_list_.begin(), residue_list_.end(), bind(&ResidueImpl::GetNumber, _1)==number); + + if (k==residue_list_.end()) + return -1; + int pos=std::distance(residue_list_.begin(), k); + assert(residue_list_[pos]->GetNumber()==number); + return pos; + } +} + +int ChainImpl::GetIndexForResNumInSequence(const ResNum& number) const +{ + int pos=number.GetNum()-1; + std::list<Shift>::const_iterator i; + for (i=shifts_.begin(); i!=shifts_.end(); ++i) { + const Shift& s=*i; + if (pos<s.start) { + break; + } else if (pos<s.start+s.shift) { + return -1; + } + pos-=s.shift; + } + while (pos>=0 && pos<static_cast<int>(residue_list_.size()) && + residue_list_[pos]->GetNumber()<number) { + pos++; + } + if (pos<0 || pos>=static_cast<int>(residue_list_.size())) { + return -1; + } + assert(residue_list_[pos]->GetNumber()==number); + return pos; +} + +int ChainImpl::GetIndex(const ResidueImplPtr& res) const +{ + if (!res) { + return -1; + } + ResNum number=res->GetNumber(); + if (in_sequence_) { + return this->GetIndexForResNumInSequence(number); + } else { + ResidueImplList::const_iterator k=residue_list_.begin()-1; + do { + k=std::find_if(k+1, residue_list_.end(), + bind(&ResidueImpl::GetNumber, _1)==number); + } while(k!=residue_list_.end() && (*k)!=res); + if (k==residue_list_.end()) return -1; int pos=std::distance(residue_list_.begin(), k); @@ -343,7 +376,7 @@ void ChainImpl::AssignSecondaryStructure(SecStructure ss, const ResNum& start, const ResNum& end) { - int start_index=this->GetIndex(start); + int start_index=this->GetIndexForResNum(start); int i=start_index; bool found_end=false; if (i>=0) { diff --git a/modules/mol/base/src/impl/chain_impl.hh b/modules/mol/base/src/impl/chain_impl.hh index cf7c1b838..d7d2ca64b 100644 --- a/modules/mol/base/src/impl/chain_impl.hh +++ b/modules/mol/base/src/impl/chain_impl.hh @@ -91,7 +91,7 @@ public: ResidueImplPtr FindResidue(const ResNum& number) const; AtomImplPtr FindAtom(const ResNum& number, - const String& atom_name) const; + const String& atom_name) const; //! Get number of residues of this chain int GetResidueCount() const; @@ -114,12 +114,14 @@ public: void ReorderResidues(); - int GetIndex(const ResNum& number) const; + int GetIndex(const ResidueImplPtr& res) const; + void AssignSecondaryStructure(SecStructure ss, + const ResNum& start, + const ResNum& end); + int GetIndexForResNum(const ResNum& number) const; - void AssignSecondaryStructure(SecStructure ss, - const ResNum& start, - const ResNum& end); private: + int GetIndexForResNumInSequence(const ResNum& number) const; void UpdateShifts(); typedef struct { int start; diff --git a/modules/mol/base/src/impl/residue_impl.cc b/modules/mol/base/src/impl/residue_impl.cc index 4d22f927b..cf4729239 100644 --- a/modules/mol/base/src/impl/residue_impl.cc +++ b/modules/mol/base/src/impl/residue_impl.cc @@ -516,7 +516,8 @@ void ResidueImpl::AddAltAtomPos(const String& group, } int ResidueImpl::GetIndex() const { - return this->GetChain()->GetIndex(this->GetNumber()); + ResidueImplPtr res_impl=const_cast<ResidueImpl*>(this)->shared_from_this(); + return this->GetChain()->GetIndex(res_impl); } bool ResidueImpl::HasAltAtomGroup(const String& group) const { diff --git a/modules/mol/base/tests/test_residue.cc b/modules/mol/base/tests/test_residue.cc index a5a31a2fc..3451f6f5b 100644 --- a/modules/mol/base/tests/test_residue.cc +++ b/modules/mol/base/tests/test_residue.cc @@ -46,6 +46,22 @@ BOOST_AUTO_TEST_CASE(test_in_sequence) } +BOOST_AUTO_TEST_CASE(test_res_index_bzdng227) +{ + std::cout << "HERE" << std::endl; + EntityHandle eh=CreateEntity(); + XCSEditor e=eh.EditXCS(); + ChainHandle ch1=e.InsertChain("A"); + ResidueHandle ra = e.AppendResidue(ch1, "A", 1); + ResidueHandle rb = e.AppendResidue(ch1, "B", 2); + ResidueHandle rc = e.AppendResidue(ch1, "C", 1); + + BOOST_CHECK_EQUAL(ra.GetIndex(), 0); + BOOST_CHECK_EQUAL(rb.GetIndex(), 1); + BOOST_CHECK_EQUAL(rc.GetIndex(), 2); +} + + BOOST_AUTO_TEST_CASE(throw_invalid_res_handle) { ChainHandle chain; -- GitLab