From ae3c5c0d480641fad81c3e4cb2ba58b5a130db37 Mon Sep 17 00:00:00 2001 From: Marco Biasini <marco.biasini@unibas.ch> Date: Thu, 26 Jul 2012 12:17:51 +0200 Subject: [PATCH] added RuleBasedConop RuleBased conop is an experimental new interface for processing structures in the conop module. The class exposes a single method Process with takes care of the complete conop procedure. There are still a few methods missing, they will be added shortly. --- CMakeLists.txt | 15 ++ modules/conop/pymod/CMakeLists.txt | 1 + modules/conop/pymod/export_rule_based.cc | 12 ++ modules/conop/pymod/wrap_conop.cc | 2 + modules/conop/src/CMakeLists.txt | 2 + modules/conop/src/rule_based.cc | 210 +++++++++++++++++++++++ modules/conop/src/rule_based.hh | 32 ++++ modules/conop/src/rule_based_builder.cc | 1 + 8 files changed, 275 insertions(+) create mode 100644 modules/conop/pymod/export_rule_based.cc create mode 100644 modules/conop/src/rule_based.cc create mode 100644 modules/conop/src/rule_based.hh diff --git a/CMakeLists.txt b/CMakeLists.txt index 91c10973b..fba8fd543 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -189,6 +189,21 @@ if (ENABLE_INFO) find_package(Qt4 4.5.0 REQUIRED) endif() +if (OPTIMIZE) + if (CXX_FLAGS) + set (CMAKE_CXX_FLAGS_RELEASE ${CXX_FLAGS}) + endif() + if (C_FLAGS) + set (CMAKE_C_FLAGS_RELEASE ${C_FLAGS}) + endif() +else() + if (CXX_FLAGS) + set(CMAKE_CXX_FLAGS_DEBUG ${CXX_FLAGS}) + endif() + if (C_FLAGS) + set(CMAKE_C_FLAGS_DEBUG ${C_FLAGS}) + endif() +endif() if (ENABLE_GFX) if(USE_MESA) find_package(Mesa REQUIRED) diff --git a/modules/conop/pymod/CMakeLists.txt b/modules/conop/pymod/CMakeLists.txt index c1bf89d0e..2ceff8be3 100644 --- a/modules/conop/pymod/CMakeLists.txt +++ b/modules/conop/pymod/CMakeLists.txt @@ -4,6 +4,7 @@ set(OST_CONOP_PYMOD_SOURCES export_compound.cc export_amino_acids.cc export_conop.cc + export_rule_based.cc export_non_standard.cc export_ring_finder.cc ) diff --git a/modules/conop/pymod/export_rule_based.cc b/modules/conop/pymod/export_rule_based.cc new file mode 100644 index 000000000..74112149b --- /dev/null +++ b/modules/conop/pymod/export_rule_based.cc @@ -0,0 +1,12 @@ +#include <boost/python.hpp> +#include <ost/conop/rule_based.hh> + +using namespace boost::python; +using namespace ost::conop; + +void export_rule_based() +{ + class_<RuleBasedConop>("RuleBasedConop", init<CompoundLibPtr>()) + .def("Process", &RuleBasedConop::Process) + ; +} diff --git a/modules/conop/pymod/wrap_conop.cc b/modules/conop/pymod/wrap_conop.cc index 6573bf41a..99ceec316 100644 --- a/modules/conop/pymod/wrap_conop.cc +++ b/modules/conop/pymod/wrap_conop.cc @@ -27,10 +27,12 @@ void export_RingFinder(); void export_AminoAcids(); void export_NonStandard(); +void export_rule_based(); BOOST_PYTHON_MODULE(_ost_conop) { export_Builder(); export_Conop(); + export_rule_based(); export_Compound(); export_RingFinder(); export_AminoAcids(); diff --git a/modules/conop/src/CMakeLists.txt b/modules/conop/src/CMakeLists.txt index 8f493e83e..55eb837f9 100644 --- a/modules/conop/src/CMakeLists.txt +++ b/modules/conop/src/CMakeLists.txt @@ -9,6 +9,7 @@ model_check.hh compound.hh compound_lib.hh module_config.hh +rule_based.hh nonstandard.hh rule_based_builder.hh ring_finder.hh @@ -19,6 +20,7 @@ builder.cc amino_acids.cc conop.cc diag.cc +rule_based.cc model_check.cc heuristic_builder.cc compound.cc diff --git a/modules/conop/src/rule_based.cc b/modules/conop/src/rule_based.cc new file mode 100644 index 000000000..941ecade4 --- /dev/null +++ b/modules/conop/src/rule_based.cc @@ -0,0 +1,210 @@ +#include <ost/log.hh> +#include <ost/mol/xcs_editor.hh> +#include <ost/mol/bond_handle.hh> +#include <ost/mol/impl/residue_impl.hh> +#include <ost/mol/impl/atom_impl.hh> +#include <ost/mol/residue_handle.hh> +#include "rule_based.hh" +namespace ost { namespace conop { + +struct OrdinalAtomComp { + bool operator()(const mol::impl::AtomImplPtr& a, + const mol::impl::AtomImplPtr& b) const { + return a->GetState()<b->GetState(); + } +}; + +void RuleBasedConop::Process(mol::EntityHandle ent) +{ + mol::ChainHandleList chains=ent.GetChainList(); + for (mol::ChainHandleList::iterator + i = chains.begin(), e = chains.end(); i!= e; ++i) { + mol::ChainHandle& chain = *i; + mol::ResidueHandleList residues = chain.GetResidueList(); + mol::ResidueHandle prev; + for (mol::ResidueHandleList::iterator + j = residues.begin(), e2 = residues.end(); j != e2; ++j) { + mol::ResidueHandle residue = *j; + CompoundPtr compound = lib_->FindCompound(residue.GetName(), Compound::PDB); + if (!compound) { + // process unknown residue... + continue; + } + this->ReorderAtoms(residue, compound); + bool unks = this->HasUnknownAtoms(residue, compound); + if (unks) { + LOG_WARNING("residue " << residue << " doesn't look like a standard " + << residue.GetKey() << " (" << compound->GetFormula() << ")"); + residue.SetChemClass(mol::ChemClass(mol::ChemClass::UNKNOWN)); + residue.SetChemType(mol::ChemType(mol::ChemType::UNKNOWN)); + residue.SetOneLetterCode('?'); + continue; + } + this->FillResidueProps(residue, compound); + this->ConnectAtomsOfResidue(residue, compound); + this->ConnectResidues(prev, residue); + prev = residue; + } + } +} + +void RuleBasedConop::ConnectResidues(mol::ResidueHandle rh, + mol::ResidueHandle next) +{ + if (!next.IsValid() || !rh.IsValid()) { + return; + } + + mol::XCSEditor e=rh.GetEntity().EditXCS(mol::BUFFERED_EDIT); + + // check if both of the residues are able to form a peptide bond. + if (rh.IsPeptideLinking() && next.IsPeptideLinking()) { + // If we have an OXT then there is no peptide bond connecting the two + // residues. + if (rh.FindAtom("OXT")) + return; + mol::AtomHandle c=rh.FindAtom("C"); + mol::AtomHandle n=next.FindAtom("N"); + // Give subclasses a chance to give us their opinions on the feasibility of + // the peptide bond. + if (c.IsValid() && n.IsValid() && this->IsBondFeasible(c, n)) { + e.Connect(c, n, 1); + rh.SetIsProtein(true); + next.SetIsProtein(true); + } + } else if (rh.IsNucleotideLinking() && next.IsNucleotideLinking()) { + mol::AtomHandle c=rh.FindAtom("O3'"); + mol::AtomHandle n=next.FindAtom("P"); + if (c.IsValid() && n.IsValid() && this->IsBondFeasible(c, n)) { + e.Connect(c, n, 1); + } + } +} + +void RuleBasedConop::FillResidueProps(mol::ResidueHandle residue, + CompoundPtr compound) +{ + residue.SetChemClass(compound->GetChemClass()); + residue.SetChemType(compound->GetChemType()); + residue.SetOneLetterCode(compound->GetOneLetterCode()); +} + +mol::AtomHandle RuleBasedConop::LocateAtom(const mol::AtomHandleList& ahl, + int ordinal) +{ + if (ahl.empty()) + return mol::AtomHandle(); + const mol::AtomHandle* r_it=&ahl.back(); + if (static_cast<int>(ahl.size())>ordinal) { + r_it=&ahl.front()+ordinal; + } + while ((r_it>=&ahl.front()) && + (static_cast<int>(r_it->Impl()->GetState())>ordinal)) { + --r_it; + } + bool not_found=(r_it<&ahl.front() || + static_cast<int>(r_it->Impl()->GetState())!=ordinal); + return not_found ? mol::AtomHandle() : *r_it; +} + + +void RuleBasedConop::ConnectAtomsOfResidue(mol::ResidueHandle rh, CompoundPtr compound) +{ + + //if (!compound) { + // dist_connect(this, rh.GetAtomList()); + // return; + //} + //if (unknown_atoms_) { + // dist_connect(this, rh.GetAtomList()); + // return; + //} + mol::XCSEditor e=rh.GetEntity().EditXCS(mol::BUFFERED_EDIT); + BondSpecList::const_iterator j=compound->GetBondSpecs().begin(); + mol::AtomHandleList atoms=rh.GetAtomList(); + for(; j!=compound->GetBondSpecs().end(); ++j) { + const BondSpec& bond=*j; + mol::AtomHandle a1=this->LocateAtom(atoms, bond.atom_one); + mol::AtomHandle a2=this->LocateAtom(atoms, bond.atom_two); + if (a1.IsValid() && a2.IsValid()) { + if (!check_bond_feasibility_) { + if (strict_hydrogens_ && (a1.GetElement()=="H" || + a2.GetElement()=="D")) { + continue; + } + e.Connect(a1, a2, bond.order); + } else { + if (this->IsBondFeasible(a1, a2)) { + if (strict_hydrogens_ && (a1.GetElement()=="H" || + a2.GetElement()=="D")) { + continue; + } + e.Connect(a1, a2, bond.order); + } + } + } + } + //for (mol::AtomHandleList::iterator i=atoms.begin(), e=atoms.end(); i!=e; ++i) { + // if (((*i).GetElement()=="H" || (*i).GetElement()=="D") && + // (*i).GetBondCount()==0) { + // this->DistanceBasedConnect(*i); + // } + // } +} + +bool RuleBasedConop::IsBondFeasible(const mol::AtomHandle& atom_a, + const mol::AtomHandle& atom_b) +{ + Real radii=0.0; + if (atom_a.GetRadius()>0.0) { + radii=atom_a.GetRadius(); + } else { + return false; + } + if (atom_b.GetRadius()>0.0) { + radii+=atom_b.GetRadius(); + } else { + return false; + } + Real len=geom::Length2(atom_a.GetPos()-atom_b.GetPos()); + Real lower_bound=radii*radii*0.0625; + Real upper_bound=lower_bound*6.0; + return (len<=upper_bound && len>=lower_bound); +} +void RuleBasedConop::ReorderAtoms(mol::ResidueHandle residue, + CompoundPtr compound) +{ + mol::impl::ResidueImplPtr impl=residue.Impl(); + mol::impl::AtomImplList::iterator i=impl->GetAtomList().begin(); + for (; i!=impl->GetAtomList().end(); ++i) { + mol::impl::AtomImplPtr atom=*i; + atom->SetState(std::numeric_limits<unsigned int>::max()); + int index=compound->GetAtomSpecIndex(atom->GetName()); + if (index==-1) { + atom->SetState(std::numeric_limits<unsigned int>::max()); + continue; + } + atom->SetState((compound->GetAtomSpecs())[index].ordinal); + } + std::sort(impl->GetAtomList().begin(), impl->GetAtomList().end(), + OrdinalAtomComp()); +} + +bool RuleBasedConop::HasUnknownAtoms(mol::ResidueHandle res, CompoundPtr compound) +{ + AtomSpecList::const_iterator j=compound->GetAtomSpecs().begin(); + mol::AtomHandleList atoms=res.GetAtomList(); + mol::AtomHandleList::iterator i=atoms.begin(); + for (mol::AtomHandleList::iterator + i=atoms.begin(), e=atoms.end(); i!=e; ++i) { + if ((*i).Impl()->GetState()==std::numeric_limits<unsigned int>::max()) { + if (((*i).GetElement()=="H" || (*i).GetElement()=="D") && + !strict_hydrogens_) { + continue; + } + return true; + } + } + return false; +} +}} diff --git a/modules/conop/src/rule_based.hh b/modules/conop/src/rule_based.hh new file mode 100644 index 000000000..2a8c95b8d --- /dev/null +++ b/modules/conop/src/rule_based.hh @@ -0,0 +1,32 @@ +#ifndef OST_CONOP_RULE_BASED_HH +#define OST_CONOP_RULE_BASED_HH + +#include <ost/mol/entity_handle.hh> +#include "compound_lib.hh" +#include "diag.hh" +namespace ost { namespace conop { + + +class DLLEXPORT_OST_CONOP RuleBasedConop { +public: + RuleBasedConop(CompoundLibPtr compound_lib): lib_(compound_lib), + strict_hydrogens_(false), check_bond_feasibility_(false) {} + + void Process(mol::EntityHandle ent); + +private: + bool HasUnknownAtoms(mol::ResidueHandle residue, CompoundPtr compound); + void ReorderAtoms(mol::ResidueHandle residue, CompoundPtr compound); + void FillResidueProps(mol::ResidueHandle residue, CompoundPtr compound); + void ConnectAtomsOfResidue(mol::ResidueHandle residue, CompoundPtr compound); + void ConnectResidues(mol::ResidueHandle residue, mol::ResidueHandle next); + bool IsBondFeasible(const mol::AtomHandle&, const mol::AtomHandle&); + mol::AtomHandle LocateAtom(const mol::AtomHandleList&, int ordinal); + CompoundLibPtr lib_; + bool strict_hydrogens_; + bool check_bond_feasibility_; +}; + +}} +#endif + diff --git a/modules/conop/src/rule_based_builder.cc b/modules/conop/src/rule_based_builder.cc index 529fbcbc6..53410e52d 100644 --- a/modules/conop/src/rule_based_builder.cc +++ b/modules/conop/src/rule_based_builder.cc @@ -216,6 +216,7 @@ inline void dist_connect(RuleBasedBuilder* b, mol::AtomHandleList atoms) b->DistanceBasedConnect(*i); } } + void RuleBasedBuilder::ConnectAtomsOfResidue(mol::ResidueHandle rh) { -- GitLab