diff --git a/modules/mol/alg/pymod/wrap_mol_alg.cc b/modules/mol/alg/pymod/wrap_mol_alg.cc index 67f4fbf9e13454d105b0f69844297b06a1508309..91a9a0904041a90bf502a8c4ecb00e7cbe99c7c0 100644 --- a/modules/mol/alg/pymod/wrap_mol_alg.cc +++ b/modules/mol/alg/pymod/wrap_mol_alg.cc @@ -17,14 +17,12 @@ // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA //------------------------------------------------------------------------------ -/* - * Author Juergen Haas - */ #include <boost/python.hpp> #include <ost/config.hh> #include <ost/mol/alg/local_dist_test.hh> #include <ost/mol/alg/superpose_frames.hh> using namespace boost::python; +using namespace ost; void export_svdSuperPose(); @@ -32,6 +30,12 @@ void export_svdSuperPose(); void export_entity_to_density(); #endif +namespace { + +Real (*ldt_a)(const mol::EntityView&, const mol::EntityView& ref, Real, Real)=&mol::alg::LocalDistTest; +Real (*ldt_b)(const seq::AlignmentHandle&,Real, Real, int, int)=&mol::alg::LocalDistTest; +} + BOOST_PYTHON_MODULE(_mol_alg) { export_svdSuperPose(); @@ -39,8 +43,9 @@ BOOST_PYTHON_MODULE(_mol_alg) export_entity_to_density(); #endif - def("LocalDistTest", &ost::mol::alg::LocalDistTest); + def("LocalDistTest", ldt_a); + def("LocalDistTest", ldt_b, (arg("ref_index")=0, arg("mdl_index")=1)); def("SuperposeFrames", &ost::mol::alg::SuperposeFrames, (arg("source"), arg("sel")=ost::mol::EntityView(), arg("begin")=0, - arg("end")=-1, arg("ref")=-1)); + arg("end")=-1, arg("ref")=-1)); } diff --git a/modules/mol/alg/src/CMakeLists.txt b/modules/mol/alg/src/CMakeLists.txt index fef02349e2e5031cad63583693692230bd181664..15e93c0e72ade2450464aaa55551828073dc1ce3 100644 --- a/modules/mol/alg/src/CMakeLists.txt +++ b/modules/mol/alg/src/CMakeLists.txt @@ -13,7 +13,7 @@ set(OST_MOL_ALG_SOURCES superpose_frames.cc ) -set(MOL_ALG_DEPS mol) +set(MOL_ALG_DEPS mol seq) if (ENABLE_IMG) set(OST_MOL_ALG_HEADERS diff --git a/modules/mol/alg/src/local_dist_test.cc b/modules/mol/alg/src/local_dist_test.cc index 2d97aa915587805c6729327d22320e7db25c7dc3..de78df711c03dcfaf619de243c193b0bd70576f8 100644 --- a/modules/mol/alg/src/local_dist_test.cc +++ b/modules/mol/alg/src/local_dist_test.cc @@ -49,11 +49,11 @@ bool swappable(const String& rname, const String& aname) return false; } -std::pair<Real, Real> calc_overlap(ResidueView ref_res, - EntityView ref, - ChainView mdl_chain, - Real tol, Real max_dist, bool only_fixed, - bool swap) +std::pair<Real, Real> calc_overlap1(ResidueView ref_res, + EntityView ref, + ChainView mdl_chain, + Real tol, Real max_dist, bool only_fixed, + bool swap) { std::pair<Real, Real> overlap(0.0, 0.0); AtomViewList ref_atoms=ref_res.GetAtomList(); @@ -82,7 +82,7 @@ std::pair<Real, Real> calc_overlap(ResidueView ref_res, continue; } AtomView av2=mdl_chain.FindAtom(aj->GetResidue().GetNumber(), - aj->GetName()); + aj->GetName()); overlap.second+=1.0; if (!(av1 && av2)) { continue; @@ -112,20 +112,101 @@ std::pair<Real, Real> calc_overlap(ResidueView ref_res, return overlap; } +std::pair<Real, Real> calc_overlap2(const seq::ConstSequenceHandle& ref_seq, + const seq::ConstSequenceHandle& mdl_seq, + int pos, Real tol, Real max_dist, + bool only_fixed, bool swap) +{ + std::pair<Real, Real> overlap(0.0, 0.0); + EntityView ref=ref_seq.GetAttachedView(); + ResidueView ref_res=ref_seq.GetResidue(pos); + if (!ref_res.IsValid()) { + return std::pair<Real,Real>(0.0, 0.0); + } + AtomViewList ref_atoms=ref_res.GetAtomList(); + ResidueView mdl_res=mdl_seq.GetResidue(pos); + AtomViewList within; + if (max_dist<0) { + within=ref.GetAtomList(); + } + for (AtomViewList::iterator ai=ref_atoms.begin(), + ae=ref_atoms.end(); ai!=ae; ++ai) { + if (ai->GetElement()=="H") { continue; } + String name=swap ? swapped_name(ai->GetName()) : ai->GetName(); + AtomView av1=mdl_res ? mdl_res.FindAtom(name) : AtomView(); + if (max_dist>=0){ + within=ref.FindWithin(ai->GetPos(), max_dist); + } + for (AtomViewList::iterator aj=within.begin(), + ae2=within.end(); aj!=ae2; ++aj) { + if (aj->GetElement()=="H") { continue; } + if (only_fixed) { + if (aj->GetResidue().GetNumber()==ref_res.GetNumber()) { + continue; + } + if (swappable(aj->GetResidue().GetName(), aj->GetName())) { + continue; + } + overlap.second+=1.0; + // map from residue index to position in alignment + try { + int aln_pos=ref_seq.GetPos(aj->GetResidue().GetIndex()); + ResidueView r2=mdl_seq.GetResidue(aln_pos); + if (!r2.IsValid()) { + continue; + } + AtomView av2=r2.FindAtom(aj->GetName()); + if (!(av1 && av2)) { + continue; + } + Real mdl_dist=geom::Length(av1.GetPos()-av2.GetPos()); + Real ref_dist=geom::Length(ai->GetPos()-aj->GetPos()); + if (std::abs(mdl_dist-ref_dist)<tol) { + overlap.first+=1; + } + } catch(...) { } + continue; + } else { + if (aj->GetResidue().GetNumber()>ref_res.GetNumber()) { + overlap.second+=1.0; + try { + int aln_pos=ref_seq.GetPos(aj->GetResidue().GetIndex()); + ResidueView r2=mdl_seq.GetResidue(aln_pos); + if (!r2.IsValid()) { + continue; + } + AtomView av2=r2.FindAtom(aj->GetName()); + if (!(av1 && av2)) { + continue; + } + Real mdl_dist=geom::Length(av1.GetPos()-av2.GetPos()); + Real ref_dist=geom::Length(ai->GetPos()-aj->GetPos()); + if (std::abs(mdl_dist-ref_dist)<tol) { + overlap.first+=1; + } + } catch (...) { } + } + } + } + } + return overlap; +} + } Real LocalDistTest(const EntityView& mdl, const EntityView& ref, Real cutoff, Real max_dist) { - ResidueViewList ref_residues=ref.GetResidueList(); if (!mdl.GetResidueCount()) { - LOG_WARNING("model structures doesn't contain any residues"); - return 0.0; + LOG_WARNING("model structures doesn't contain any residues"); + return 0.0; } - if (ref_residues.empty()) { - LOG_WARNING("reference structures doesn't contain any residues"); - return 0.0; + + if (!ref.GetResidueCount()) { + LOG_WARNING("reference structures doesn't contain any residues"); + return 0.0; } + ResidueViewList ref_residues=ref.GetResidueList(); ChainView mdl_chain=mdl.GetChainList()[0]; // Residues with symmetric side-chains require special treatment as there are // two possible ways to name the atoms. We calculate the overlap with the @@ -143,10 +224,10 @@ Real LocalDistTest(const EntityView& mdl, const EntityView& ref, continue; } - std::pair<Real, Real> ov1=calc_overlap(*i, ref, mdl_chain, + std::pair<Real, Real> ov1=calc_overlap1(*i, ref, mdl_chain, cutoff, max_dist, true, false); - std::pair<Real, Real> ov2=calc_overlap(*i, ref, mdl_chain, + std::pair<Real, Real> ov2=calc_overlap1(*i, ref, mdl_chain, cutoff, max_dist, true, true); if (ov1.first/ov1.second<ov2.first/ov2.second) { @@ -157,18 +238,68 @@ Real LocalDistTest(const EntityView& mdl, const EntityView& ref, edi.RenameAtom(j->GetHandle(), swapped_name(j->GetName())); } } - } } std::pair<Real, Real> total_ov(0.0, 0.0); for (ResidueViewList::iterator i=ref_residues.begin(), e=ref_residues.end(); i!=e; ++i) { - std::pair<Real, Real> ov1=calc_overlap(*i, ref, mdl_chain, cutoff, + std::pair<Real, Real> ov1=calc_overlap1(*i, ref, mdl_chain, cutoff, max_dist, false, false); total_ov.first+=ov1.first; total_ov.second+=ov1.second; } - return total_ov.first/total_ov.second; + return total_ov.first/(total_ov.second ? total_ov.second : 1); +} + +Real LocalDistTest(const ost::seq::AlignmentHandle& aln, + Real cutoff, Real max_dist, int ref_index, int mdl_index) +{ + seq::ConstSequenceHandle ref_seq=aln.GetSequence(ref_index); + seq::ConstSequenceHandle mdl_seq=aln.GetSequence(mdl_index); + if (!ref_seq.HasAttachedView()) { + LOG_ERROR("reference sequence doesn't have a view attached."); + return 0.0; + } + if (!mdl_seq.HasAttachedView()) { + LOG_ERROR("model sequence doesn't have a view attached"); + return 0.0; + } + XCSEditor edi=ref_seq.GetAttachedView().GetHandle().EditXCS(BUFFERED_EDIT); + for (int i=0; i<aln.GetLength(); ++i) { + ResidueView mdl_res=mdl_seq.GetResidue(i); + if (!mdl_res) { + continue; + } + String rname=mdl_res.GetName(); + if (!(rname=="GLU" || rname=="ASP" || rname=="VAL" || rname=="TYR" || + rname=="PHE" || rname=="LYS" || rname=="ARG")) { + continue; + } + std::pair<Real, Real> ov1=calc_overlap2(ref_seq, mdl_seq, i, + cutoff, max_dist, true, + false); + std::pair<Real, Real> ov2=calc_overlap2(ref_seq, mdl_seq, i, + cutoff, max_dist, true, + true); + if (ov1.first/ov1.second<ov2.first/ov2.second) { + AtomViewList atoms=mdl_res.GetAtomList(); + for (AtomViewList::iterator j=atoms.begin(), + e2=atoms.end(); j!=e2; ++j) { + if (swappable(rname, j->GetName())) { + edi.RenameAtom(j->GetHandle(), swapped_name(j->GetName())); + } + } + } + } + std::pair<Real, Real> total_ov(0.0, 0.0); + for (int i=0; i<aln.GetLength(); ++i) { + std::pair<Real, Real> ov1=calc_overlap2(ref_seq, mdl_seq, i, cutoff, + max_dist, false, false); + total_ov.first+=ov1.first; + total_ov.second+=ov1.second; + } + return total_ov.first/(total_ov.second ? total_ov.second : 1); + return 0.0; } }}} diff --git a/modules/mol/alg/src/local_dist_test.hh b/modules/mol/alg/src/local_dist_test.hh index f0ba3ebea20a6138a0cf14f2a34d24839abe3ef4..ab7588cdf84d401aaee052bcfe2b390da8174b15 100644 --- a/modules/mol/alg/src/local_dist_test.hh +++ b/modules/mol/alg/src/local_dist_test.hh @@ -3,12 +3,17 @@ #include <ost/mol/entity_view.hh> #include <ost/mol/alg/module_config.hh> +#include <ost/seq/alignment_handle.hh> namespace ost { namespace mol { namespace alg { Real DLLEXPORT_OST_MOL_ALG LocalDistTest(const EntityView& mdl, const EntityView& ref, Real cutoff, Real max_dist); + +Real DLLEXPORT_OST_MOL_ALG LocalDistTest(const ost::seq::AlignmentHandle& aln, + Real cutoff, Real max_dist, + int ref_index=0, int mdl_index=1); }}} #endif