diff --git a/modules/mol/alg/pymod/wrap_mol_alg.cc b/modules/mol/alg/pymod/wrap_mol_alg.cc index 7b403f02d410525986db487beec6397c678c4fc3..1a02874c599e05c66af011a60f737207b26844c0 100644 --- a/modules/mol/alg/pymod/wrap_mol_alg.cc +++ b/modules/mol/alg/pymod/wrap_mol_alg.cc @@ -21,10 +21,13 @@ #include <boost/python/suite/indexing/map_indexing_suite.hpp> #include <ost/config.hh> #include <ost/mol/alg/local_dist_diff_test.hh> +#include <ost/mol/alg/distance_test_common.hh> #include <ost/mol/alg/superpose_frames.hh> #include <ost/mol/alg/filter_clashes.hh> #include <ost/mol/alg/consistency_checks.hh> #include <ost/export_helper/pair_to_tuple_conv.hh> +#include <ost/export_helper/vec_to_list_conv.hh> + using namespace boost::python; using namespace ost; @@ -91,6 +94,7 @@ ost::mol::alg::GlobalRDMap create_distance_list_from_multiple_references(const l return ost::mol::alg::CreateDistanceListFromMultipleReferences(ref_list_vector, cutoff_list_vector, sequence_separation, max_dist); } + } @@ -117,7 +121,9 @@ BOOST_PYTHON_MODULE(_ost_mol_alg) def("LDDTHA",&mol::alg::LDDTHA, (arg("sequence_separation")=0)); def("CreateDistanceList",&mol::alg::CreateDistanceList); def("CreateDistanceListFromMultipleReferences",&create_distance_list_from_multiple_references); - + + + def("SuperposeFrames", superpose_frames1, (arg("source"), arg("sel")=ost::mol::EntityView(), arg("begin")=0, arg("end")=-1, arg("ref")=-1)); @@ -150,8 +156,8 @@ BOOST_PYTHON_MODULE(_ost_mol_alg) .def("GetResNum",&mol::alg::UniqueAtomIdentifier::GetResNum) .def("GetResidueName",&mol::alg::UniqueAtomIdentifier::GetResidueName) .def("GetAtomName",&mol::alg::UniqueAtomIdentifier::GetAtomName) + .def("GetQualifiedAtomName",&mol::alg::UniqueAtomIdentifier::GetQualifiedAtomName) ; - class_<mol::alg::ResidueRDMap>("ResidueRDMap") .def(map_indexing_suite<mol::alg::ResidueRDMap>()) @@ -177,14 +183,47 @@ BOOST_PYTHON_MODULE(_ost_mol_alg) .def("GetCount",&mol::alg::BondLengthInfo::GetCount) ; + class_<mol::alg::ClashEvent> ("ClashEvent" ,init <>()) + .def(init<const mol::alg::UniqueAtomIdentifier&,const mol::alg::UniqueAtomIdentifier&, Real, Real>()) + .def("GetFirstAtom",&mol::alg::ClashEvent::GetFirstAtom) + .def("GetSecondAtom",&mol::alg::ClashEvent::GetSecondAtom) + .def("GetModelDistance",&mol::alg::ClashEvent::GetModelDistance) + .def("GetAdjustedReferenceDistance",&mol::alg::ClashEvent::GetAdjustedReferenceDistance) + ; + + class_<mol::alg::StereoChemicalBondViolation> ("StereoChemicalBondViolation" ,init <>()) + .def(init<const mol::alg::UniqueAtomIdentifier&,const mol::alg::UniqueAtomIdentifier&, + Real, const std::pair<Real, Real>& >()) + .def("GetFirstAtom",&mol::alg::StereoChemicalBondViolation::GetFirstAtom) + .def("GetSecondAtom",&mol::alg::StereoChemicalBondViolation::GetSecondAtom) + .def("GetModelValue",&mol::alg::StereoChemicalBondViolation::GetModelValue) + .def("GetAllowedRange",&mol::alg::StereoChemicalBondViolation::GetAllowedRange) + ; + + class_<mol::alg::StereoChemicalAngleViolation> ("StereoChemicalAngleViolation" ,init <>()) + .def(init<const mol::alg::UniqueAtomIdentifier&,const mol::alg::UniqueAtomIdentifier&, + const mol::alg::UniqueAtomIdentifier&, Real, const std::pair<Real, Real>& >()) + .def("GetFirstAtom",&mol::alg::StereoChemicalAngleViolation::GetFirstAtom) + .def("GetSecondAtom",&mol::alg::StereoChemicalAngleViolation::GetSecondAtom) + .def("GetThirdAtom",&mol::alg::StereoChemicalAngleViolation::GetThirdAtom) + .def("GetModelValue",&mol::alg::StereoChemicalAngleViolation::GetModelValue) + .def("GetAllowedRange",&mol::alg::StereoChemicalAngleViolation::GetAllowedRange) + ; + class_<mol::alg::ClashingInfo> ("ClashingInfo" ,init <>()) - .def(init<int,Real>()) + .def(init<int,Real,const std::vector<mol::alg::ClashEvent> >()) .def("GetClashCount",&mol::alg::ClashingInfo::GetClashCount) .def("GetAverageOffset",&mol::alg::ClashingInfo::GetAverageOffset) + .def("GetClashList",&mol::alg::ClashingInfo::GetClashList) ; + to_python_converter<std::pair<mol::EntityView,mol::alg::ClashingInfo>, + PairToTupleConverter<mol::EntityView, mol::alg::ClashingInfo> >(); + class_<mol::alg::StereoChemistryInfo> ("StereoChemistryInfo" ,init <>()) - .def(init<Real,int,int,Real,int,int, const std::map<String,mol::alg::BondLengthInfo>&>()) + .def(init<Real,int,int,Real,int,int, const std::map<String,mol::alg::BondLengthInfo>&, + const std::vector<mol::alg::StereoChemicalBondViolation>&, + const std::vector<mol::alg::StereoChemicalAngleViolation>& >()) .def("GetAvgZscoreBonds",&mol::alg::StereoChemistryInfo::GetAvgZscoreBonds) .def("GetBadBondCount",&mol::alg::StereoChemistryInfo::GetBadBondCount) .def("GetBondCount",&mol::alg::StereoChemistryInfo::GetBondCount) @@ -192,8 +231,21 @@ BOOST_PYTHON_MODULE(_ost_mol_alg) .def("GetBadAngleCount",&mol::alg::StereoChemistryInfo::GetBadAngleCount) .def("GetAngleCount",&mol::alg::StereoChemistryInfo::GetAngleCount) .def("GetAvgBondLengthInfo",&mol::alg::StereoChemistryInfo::GetAvgBondLengthInfo) + .def("GetBondViolationList",&mol::alg::StereoChemistryInfo::GetBondViolationList) + .def("GetAngleViolationList",&mol::alg::StereoChemistryInfo::GetAngleViolationList) ; + to_python_converter<std::pair<mol::EntityView,mol::alg::StereoChemistryInfo>, + PairToTupleConverter<mol::EntityView, mol::alg::StereoChemistryInfo> >(); + + + to_python_converter<std::vector<mol::alg::ClashEvent>, + VectorToListConverter<mol::alg::ClashEvent> >(); + + to_python_converter<std::vector<mol::alg::StereoChemicalBondViolation>, + VectorToListConverter<mol::alg::StereoChemicalBondViolation> >(); + to_python_converter<std::vector<mol::alg::StereoChemicalAngleViolation>, + VectorToListConverter<mol::alg::StereoChemicalAngleViolation> >(); } diff --git a/modules/mol/alg/src/CMakeLists.txt b/modules/mol/alg/src/CMakeLists.txt index eca9aa6e892d9a8bd463be00b1e2f01fc3e59125..68a7a9104b20e60818479a816f47ea95a6094d7e 100644 --- a/modules/mol/alg/src/CMakeLists.txt +++ b/modules/mol/alg/src/CMakeLists.txt @@ -3,6 +3,7 @@ set(OST_MOL_ALG_HEADERS module_config.hh sec_structure_segments.hh local_dist_diff_test.hh + distance_test_common.hh superpose_frames.hh filter_clashes.hh construct_cbeta.hh @@ -17,6 +18,7 @@ set(OST_MOL_ALG_SOURCES clash_score.cc sec_structure_segments.cc local_dist_diff_test.cc + distance_test_common.cc superpose_frames.cc filter_clashes.cc construct_cbeta.cc diff --git a/modules/mol/alg/src/distance_test_common.cc b/modules/mol/alg/src/distance_test_common.cc new file mode 100644 index 0000000000000000000000000000000000000000..2835205fd7ed8418f6727f84e1adcf521c461dac --- /dev/null +++ b/modules/mol/alg/src/distance_test_common.cc @@ -0,0 +1,81 @@ +#include <ost/mol/alg/distance_test_common.hh> + +namespace ost { namespace mol { namespace alg { + + +String UniqueAtomIdentifier::GetQualifiedAtomName() const +{ + std::stringstream output_string_s; + output_string_s << chain_ << "." << residue_name_ << residue_ << "." << atom_; + return (output_string_s.str()); +} + +bool UniqueAtomIdentifier::operator==(const UniqueAtomIdentifier& rhs) const +{ + return chain_==rhs.chain_ && residue_==rhs.residue_ && atom_==rhs.atom_; +} + +bool UniqueAtomIdentifier::operator<(const UniqueAtomIdentifier& rhs) const +{ + int cc=chain_.compare(rhs.chain_); + if (cc) { + return cc<0; + } + if (residue_<rhs.residue_) { + return true; + } else if (residue_>rhs.residue_) { + return false; + } + return atom_.compare(rhs.atom_)<0; +} + +// helper function +String SwappedName(const String& name) +{ + if (name=="OE1") return "OE2"; + if (name=="OE2") return "OE1"; + + if (name=="OD1") return "OD2"; + if (name=="OD2") return "OD1"; + + if (name=="CG1") return "CG2"; + if (name=="CG2") return "CG1"; + + if (name=="CE1") return "CE2"; + if (name=="CE2") return "CE1"; + + if (name=="CD1") return "CD2"; + if (name=="CD2") return "CD1"; + + if (name=="NH1") return "NH2"; + if (name=="NH2") return "NH1"; + + return name; +} + +// helper function +bool Swappable(const String& rname, const String& aname) +{ + if (rname=="GLU") { + return (aname=="OE1" || aname=="OE2"); + } + if (rname=="ASP") { + return (aname=="OD1" || aname=="OD2"); + } + if (rname=="VAL") { + + return (aname=="CG1" || aname=="CG2"); + } + if (rname=="TYR" || rname=="PHE") { + return (aname=="CD1" || aname=="CD2" || aname=="CE1" || aname=="CE2"); + } + if (rname=="LEU") { + return (aname=="CD1" || aname=="CD2"); + } + if (rname=="ARG") { + return (aname=="NH1" || aname=="NH2"); + } + return false; +} + +}}} diff --git a/modules/mol/alg/src/distance_test_common.hh b/modules/mol/alg/src/distance_test_common.hh new file mode 100644 index 0000000000000000000000000000000000000000..ca76a33b5e4c2d06c10b11e15301acdc855146a1 --- /dev/null +++ b/modules/mol/alg/src/distance_test_common.hh @@ -0,0 +1,92 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#ifndef OST_MOL_ALG_DISTANCE_TEST_COMMON_HH +#define OST_MOL_ALG_DISTANCE_TEST_COMMON_HH + +#include <ost/mol/entity_view.hh> +#include <ost/mol/alg/module_config.hh> + +namespace ost { namespace mol { namespace alg { + +String DLLEXPORT_OST_MOL_ALG SwappedName(const String& name); +bool DLLEXPORT_OST_MOL_ALG Swappable(const String& rname, const String& aname); + +/// \brief Contains the infomation needed to uniquely identify an atom in a structure +/// +/// Used by the the Local Distance Difference Test classes and functions +class DLLEXPORT_OST_MOL_ALG UniqueAtomIdentifier +{ + +public: + /// \brief Constructor with all the relevant information + UniqueAtomIdentifier(const String& chain,const ResNum& residue,const String& residue_name, const String& atom): chain_(chain),residue_(residue),residue_name_(residue_name),atom_(atom) {} + + // to make the compiler happy (boost python map suite) + UniqueAtomIdentifier(): chain_(""),residue_(ResNum(1)),residue_name_(""),atom_("") {} + + /// \brief Returns the name of the chain to which the atom belongs, as a String + String GetChainName() const { return chain_; } + + /// \brief Returns the ResNum of the residue to which the atom belongs + ResNum GetResNum() const { return residue_; } + + /// \brief Returns the name of the residue to which the atom belongs, as a String + String GetResidueName() const { return residue_name_; } + + /// \brief Returns the name of the atom, as a String + String GetAtomName() const { return atom_; } + + /// \brief Returns the qualified name of the atom, as a String + String GetQualifiedAtomName() const ; + + // required because UniqueAtomIdentifier is used as a key for a std::map + bool operator==(const UniqueAtomIdentifier& rhs) const ; + + // required because UniqueAtomIdentifier is used as a key for a std::map + bool operator<(const UniqueAtomIdentifier& rhs) const; + +private: + + String chain_; + ResNum residue_; + String residue_name_; + String atom_; +}; + +// typedef used to make the code cleaner +typedef std::pair<UniqueAtomIdentifier,UniqueAtomIdentifier> UAtomIdentifiers; + +/// \brief Residue distance list. +/// +/// Container for all the interatomic distances that are checked in a Local Distance Difference Test +/// and are originating from a single specific residue +typedef std::map<std::pair<UniqueAtomIdentifier,UniqueAtomIdentifier>,std::pair<Real,Real> > ResidueRDMap; + +/// \brief Global distance list. +/// +/// Container for all the residue-based interatomic distance lists that are checked in a Local Distance Difference Test +/// and belong to the same structure +typedef std::map<ost::mol::ResNum,ResidueRDMap> GlobalRDMap; + +// used by the multi-reference distance-list generator function +typedef std::map<UniqueAtomIdentifier,int> ExistenceMap; + +}}} + +#endif diff --git a/modules/mol/alg/src/filter_clashes.cc b/modules/mol/alg/src/filter_clashes.cc index e544ce95b724bd0d01372bd18696b7d1ee1d0e3f..875db0aa178c32269868638d82e3b2c273380922 100644 --- a/modules/mol/alg/src/filter_clashes.cc +++ b/modules/mol/alg/src/filter_clashes.cc @@ -82,6 +82,22 @@ String angle_string(const ost::mol::AtomHandle& atom1, const ost::mol::AtomView& namespace ost { namespace mol { namespace alg { +std::vector<ClashEvent> ClashingInfo::GetClashList() const +{ + std::vector<ClashEvent> return_list; + std::vector<UAtomIdentifiers> seen_list; + for (std::vector<ClashEvent>::const_iterator cl_it=clash_list_.begin();cl_it!=clash_list_.end();++cl_it) { + UniqueAtomIdentifier atom1 = cl_it->GetFirstAtom(); + UniqueAtomIdentifier atom2 = cl_it->GetSecondAtom(); + UAtomIdentifiers check = std::make_pair<UniqueAtomIdentifier,UniqueAtomIdentifier>(atom2,atom1); + if (std::find(seen_list.begin(),seen_list.end(),check)==seen_list.end()) { + return_list.push_back(*cl_it); + seen_list.push_back(std::make_pair<UniqueAtomIdentifier,UniqueAtomIdentifier>(atom1,atom2)); + } + } + return return_list; +} + void ClashingDistances::SetClashingDistance(const String& ele1,const String& ele2, Real min_distance, Real tolerance) { std::stringstream stkey; @@ -331,6 +347,8 @@ ClashingDistances FillClashingDistances(std::vector<String>& stereo_chemical_pro std::pair<EntityView,StereoChemistryInfo> CheckStereoChemistry(const EntityView& ent, const StereoChemicalParams& bond_table, const StereoChemicalParams& angle_table, Real bond_tolerance, Real angle_tolerance, bool always_remove_bb) { + std::vector<StereoChemicalBondViolation> bond_violation_list; + std::vector<StereoChemicalAngleViolation> angle_violation_list; Real running_sum_zscore_bonds=0.0; Real running_sum_zscore_angles=0.0; int bond_count = 0; @@ -382,6 +400,10 @@ std::pair<EntityView,StereoChemistryInfo> CheckStereoChemistry(const EntityView& if (blength < min_length || blength > max_length) { LOG_INFO("BOND:" << " " << res.GetChain() << " " << res.GetName() << " " << res.GetNumber() << " " << bond_str << " " << min_length << " " << max_length << " " << blength << " " << zscore << " " << "FAIL") bad_bond_count++; + UniqueAtomIdentifier atom_ui(atom.GetResidue().GetChain().GetName(),atom.GetResidue().GetNumber(),atom.GetResidue().GetName(),atom.GetName()); + UniqueAtomIdentifier other_atom_ui(other_atom.GetResidue().GetChain().GetName(),other_atom.GetResidue().GetNumber(),other_atom.GetResidue().GetName(),other_atom.GetName()); + StereoChemicalBondViolation bond_v(atom_ui,other_atom_ui,blength,std::make_pair<Real,Real>(min_length,max_length)); + bond_violation_list.push_back(bond_v); remove_sc=true; if (always_remove_bb==true) { remove_bb=true; @@ -446,7 +468,12 @@ std::pair<EntityView,StereoChemistryInfo> CheckStereoChemistry(const EntityView& Real zscore = (awidth - ref_width)/ref_stddev; if (awidth < min_width || awidth > max_width) { LOG_INFO("ANGLE:" << " " << res.GetChain() << " " << res.GetName() << " " << res.GetNumber() << " " << angle_str << " " << min_width << " " << max_width << " " << awidth << " " << zscore << " " << "FAIL") - bad_angle_count++; + bad_angle_count++; + UniqueAtomIdentifier atom1_ui(atom1.GetResidue().GetChain().GetName(),atom1.GetResidue().GetNumber(),atom1.GetResidue().GetName(),atom1.GetName()); + UniqueAtomIdentifier atom_ui(atom.GetResidue().GetChain().GetName(),atom.GetResidue().GetNumber(),atom.GetResidue().GetName(),atom.GetName()); + UniqueAtomIdentifier atom2_ui(atom2.GetResidue().GetChain().GetName(),atom2.GetResidue().GetNumber(),atom2.GetResidue().GetName(),atom2.GetName()); + StereoChemicalAngleViolation angle_v(atom1_ui,atom_ui,atom2_ui,awidth,std::make_pair<Real,Real>(min_width,max_width)); + angle_violation_list.push_back(angle_v); remove_sc=true; if (always_remove_bb==true) { remove_bb=true; @@ -499,7 +526,8 @@ std::pair<EntityView,StereoChemistryInfo> CheckStereoChemistry(const EntityView& avg_bond_length_info[key]=bond_info; } StereoChemistryInfo info(avg_zscore_bonds, bad_bond_count, bond_count,avg_zscore_angles, - bad_angle_count, angle_count,avg_bond_length_info); + bad_angle_count, angle_count,avg_bond_length_info, + bond_violation_list,angle_violation_list); filtered.AddAllInclusiveBonds(); return std::make_pair<EntityView,StereoChemistryInfo>(filtered,info); } @@ -513,6 +541,7 @@ std::pair<EntityView,StereoChemistryInfo> CheckStereoChemistry(const EntityHandl std::pair<EntityView,ClashingInfo> FilterClashes(const EntityView& ent, const ClashingDistances& min_distances, bool always_remove_bb) { + std::vector<ClashEvent> clash_list; int distance_count = 0; int bad_distance_count = 0; Real average_offset_sum = 0.0; @@ -564,6 +593,10 @@ std::pair<EntityView,ClashingInfo> FilterClashes(const EntityView& ent, const Cl if (d<threshold*threshold) { LOG_INFO(atom.GetResidue().GetChain() << " " << atom.GetResidue().GetName() << " " << atom.GetResidue().GetNumber() << " " << atom.GetName() << " " << atom2.GetResidue().GetChain() << " " << atom2.GetResidue().GetName() << " " << atom2.GetResidue().GetNumber() << " " << atom2.GetName() << " " << threshold << " " << sqrt(d) << " " << sqrt(d)-threshold << " " << "FAIL") bad_distance_count++; + UniqueAtomIdentifier atom_ui(atom.GetResidue().GetChain().GetName(),atom.GetResidue().GetNumber(),atom.GetResidue().GetName(),atom.GetName()); + UniqueAtomIdentifier atom2_ui(atom2.GetResidue().GetChain().GetName(),atom2.GetResidue().GetNumber(),atom2.GetResidue().GetName(),atom2.GetName()); + ClashEvent clash_event(atom_ui,atom2_ui,sqrt(d),threshold); + clash_list.push_back(clash_event); average_offset_sum+=sqrt(d)-threshold; remove_sc=true; if (always_remove_bb==true) { @@ -604,7 +637,7 @@ std::pair<EntityView,ClashingInfo> FilterClashes(const EntityView& ent, const Cl if (bad_distance_count!=0) { average_offset = average_offset_sum / static_cast<Real>(bad_distance_count); } - ClashingInfo info(bad_distance_count,average_offset); + ClashingInfo info(bad_distance_count,average_offset,clash_list); filtered.AddAllInclusiveBonds(); return std::make_pair<EntityView,ClashingInfo>(filtered,info); } diff --git a/modules/mol/alg/src/filter_clashes.hh b/modules/mol/alg/src/filter_clashes.hh index d8e1c4c2ea7978536e7e4ad8073bf0e08e1b87a3..a11bd5d8a842581e4f11a049fff4a395d1bad538 100644 --- a/modules/mol/alg/src/filter_clashes.hh +++ b/modules/mol/alg/src/filter_clashes.hh @@ -21,7 +21,7 @@ #include <ost/mol/entity_view.hh> #include <ost/mol/alg/module_config.hh> - +#include <ost/mol/alg/distance_test_common.hh> namespace ost { namespace mol { namespace alg { class BondLengthInfo @@ -42,20 +42,81 @@ private: int count_; }; +class ClashEvent +{ +public: + ClashEvent(): atom1_(UniqueAtomIdentifier()),atom2_(UniqueAtomIdentifier()),mdl_dist_(0.0),adjusted_ref_dist_(0.0) {} + ClashEvent(const UniqueAtomIdentifier& atom1,const UniqueAtomIdentifier& atom2, Real mdl_dist, Real adjusted_ref_dist ): + atom1_(atom1),atom2_(atom2),mdl_dist_(mdl_dist),adjusted_ref_dist_(adjusted_ref_dist) {} + UniqueAtomIdentifier GetFirstAtom() const { return atom1_; } + UniqueAtomIdentifier GetSecondAtom() const { return atom2_; } + Real GetModelDistance() const { return mdl_dist_; } + Real GetAdjustedReferenceDistance() const { return adjusted_ref_dist_; } +private: + UniqueAtomIdentifier atom1_; + UniqueAtomIdentifier atom2_; + Real mdl_dist_; + Real adjusted_ref_dist_; +}; class ClashingInfo { public: - ClashingInfo(): clash_count_(0), average_offset_ (0) {} - ClashingInfo (int clash_count, Real average_offset): - clash_count_(clash_count), average_offset_ (average_offset) {} - int GetClashCount() {return clash_count_;} - Real GetAverageOffset() {return average_offset_;} + ClashingInfo(): clash_count_(0), average_offset_ (0), clash_list_(std::vector<ClashEvent>()) {} + ClashingInfo (int clash_count, Real average_offset, const std::vector<ClashEvent>& clash_list): + clash_count_(clash_count), average_offset_ (average_offset),clash_list_(clash_list) {} + int GetClashCount() const {return clash_count_/2.0;} + Real GetAverageOffset() const {return average_offset_;} + std::vector<ClashEvent> GetClashList() const; private: int clash_count_; Real average_offset_; + std::vector<ClashEvent> clash_list_; +}; + +class StereoChemicalBondViolation +{ +public: + StereoChemicalBondViolation(): + atom1_(UniqueAtomIdentifier()),atom2_(UniqueAtomIdentifier()),mdl_value_(0.0),allowed_range_(std::pair<Real,Real>(0.0,0.0)) {} + StereoChemicalBondViolation(const UniqueAtomIdentifier& atom1, + const UniqueAtomIdentifier& atom2, + Real mdl_value, std::pair<Real,Real> allowed_range ): + atom1_(atom1),atom2_(atom2),mdl_value_(mdl_value),allowed_range_(allowed_range) {} + UniqueAtomIdentifier GetFirstAtom() const { return atom1_; } + UniqueAtomIdentifier GetSecondAtom() const { return atom2_; } + Real GetModelValue() const { return mdl_value_; } + std::pair<Real,Real> GetAllowedRange() const { return allowed_range_; } +private: + UniqueAtomIdentifier atom1_; + UniqueAtomIdentifier atom2_; + Real mdl_value_; + std::pair<Real,Real> allowed_range_; +}; + +class StereoChemicalAngleViolation +{ +public: + StereoChemicalAngleViolation(): + atom1_(UniqueAtomIdentifier()),atom2_(UniqueAtomIdentifier()),atom3_(UniqueAtomIdentifier()),mdl_value_(0.0),allowed_range_(std::pair<Real,Real>(0.0,0.0)) {} + StereoChemicalAngleViolation(const UniqueAtomIdentifier& atom1, + const UniqueAtomIdentifier& atom2, + const UniqueAtomIdentifier& atom3, + Real mdl_value, std::pair<Real,Real> allowed_range ): + atom1_(atom1),atom2_(atom2),atom3_(atom3),mdl_value_(mdl_value),allowed_range_(allowed_range) {} + UniqueAtomIdentifier GetFirstAtom() const { return atom1_; } + UniqueAtomIdentifier GetSecondAtom() const { return atom2_; } + UniqueAtomIdentifier GetThirdAtom() const { return atom3_; } + Real GetModelValue() const { return mdl_value_; } + std::pair<Real,Real> GetAllowedRange() const { return allowed_range_; } +private: + UniqueAtomIdentifier atom1_; + UniqueAtomIdentifier atom2_; + UniqueAtomIdentifier atom3_; + Real mdl_value_; + std::pair<Real,Real> allowed_range_; }; class StereoChemistryInfo @@ -68,24 +129,33 @@ public: avg_zscore_angles_(0), bad_angle_count_(0), angle_count_(0), - avg_bond_length_info_(std::map<String,BondLengthInfo>()) {} + avg_bond_length_info_(std::map<String,BondLengthInfo>()), + bond_violation_list_(std::vector<StereoChemicalBondViolation>()), + angle_violation_list_(std::vector<StereoChemicalAngleViolation>()) {} StereoChemistryInfo(Real avg_zscore_bonds, int bad_bond_count, int bond_count, Real avg_zscore_angles, int bad_angle_count, int angle_count, - const std::map<String,BondLengthInfo>& avg_bond_length_info): + const std::map<String,BondLengthInfo>& avg_bond_length_info, + const std::vector<StereoChemicalBondViolation>& bond_violation_list, + const std::vector<StereoChemicalAngleViolation>& angle_violation_list): avg_zscore_bonds_(avg_zscore_bonds), bad_bond_count_(bad_bond_count), bond_count_(bond_count), avg_zscore_angles_(avg_zscore_angles), bad_angle_count_(bad_angle_count), angle_count_(angle_count), - avg_bond_length_info_(avg_bond_length_info) {} - Real GetAvgZscoreBonds() {return avg_zscore_bonds_;} - int GetBadBondCount() {return bad_bond_count_;} - int GetBondCount() {return bond_count_;} - Real GetAvgZscoreAngles() {return avg_zscore_angles_;} - int GetBadAngleCount() {return bad_angle_count_;} - int GetAngleCount() {return angle_count_;} + avg_bond_length_info_(avg_bond_length_info), + bond_violation_list_(bond_violation_list), + angle_violation_list_(angle_violation_list) {} + Real GetAvgZscoreBonds() const {return avg_zscore_bonds_;} + int GetBadBondCount() const {return bad_bond_count_;} + int GetBondCount() const {return bond_count_;} + Real GetAvgZscoreAngles() const {return avg_zscore_angles_;} + int GetBadAngleCount() const {return bad_angle_count_;} + int GetAngleCount() const {return angle_count_;} std::map<String,BondLengthInfo> GetAvgBondLengthInfo() {return avg_bond_length_info_;} + std::vector<StereoChemicalBondViolation> GetBondViolationList() { return bond_violation_list_; } + std::vector<StereoChemicalAngleViolation> GetAngleViolationList() { return angle_violation_list_; } + private: Real avg_zscore_bonds_; @@ -95,6 +165,8 @@ private: int bad_angle_count_; int angle_count_; std::map<String,BondLengthInfo> avg_bond_length_info_; + std::vector<StereoChemicalBondViolation> bond_violation_list_; + std::vector<StereoChemicalAngleViolation> angle_violation_list_; }; diff --git a/modules/mol/alg/src/local_dist_diff_test.cc b/modules/mol/alg/src/local_dist_diff_test.cc index 8f936411652c58d407fe70706f17c09e6d087a05..2bf01896c77f29d48306946ad850027d02083a89 100644 --- a/modules/mol/alg/src/local_dist_diff_test.cc +++ b/modules/mol/alg/src/local_dist_diff_test.cc @@ -7,55 +7,6 @@ namespace ost { namespace mol { namespace alg { namespace { -// helper function -String swapped_name(const String& name) -{ - if (name=="OE1") return "OE2"; - if (name=="OE2") return "OE1"; - - if (name=="OD1") return "OD2"; - if (name=="OD2") return "OD1"; - - if (name=="CG1") return "CG2"; - if (name=="CG2") return "CG1"; - - if (name=="CE1") return "CE2"; - if (name=="CE2") return "CE1"; - - if (name=="CD1") return "CD2"; - if (name=="CD2") return "CD1"; - - if (name=="NH1") return "NH2"; - if (name=="NH2") return "NH1"; - - return name; -} - -// helper function -bool swappable(const String& rname, const String& aname) -{ - if (rname=="GLU") { - return (aname=="OE1" || aname=="OE2"); - } - if (rname=="ASP") { - return (aname=="OD1" || aname=="OD2"); - } - if (rname=="VAL") { - - return (aname=="CG1" || aname=="CG2"); - } - if (rname=="TYR" || rname=="PHE") { - return (aname=="CD1" || aname=="CD2" || aname=="CE1" || aname=="CE2"); - } - if (rname=="LEU") { - return (aname=="CD1" || aname=="CD2"); - } - if (rname=="ARG") { - return (aname=="NH1" || aname=="NH2"); - } - return false; -} - // helper function bool within_tolerance(Real mdl_dist, const std::pair<Real,Real>& values, Real tol) { @@ -76,14 +27,14 @@ std::pair<long int, long int> calc_overlap1(const ResidueRDMap& res_distance_lis const std::pair <Real,Real>& values = ai->second; const UniqueAtomIdentifier& first_atom=uais.first; const UniqueAtomIdentifier& second_atom=uais.second; - String name=swap ? swapped_name(first_atom.GetAtomName()) : first_atom.GetAtomName(); + String name=swap ? SwappedName(first_atom.GetAtomName()) : first_atom.GetAtomName(); AtomView av1=mdl_res ? mdl_res.FindAtom(name) : AtomView(); if (only_fixed) { if (std::abs(first_atom.GetResNum().GetNum()-second_atom.GetResNum().GetNum())<=sequence_separation) { continue; } - if (swappable(second_atom.GetResidueName(), second_atom.GetAtomName())) { + if (Swappable(second_atom.GetResidueName(), second_atom.GetAtomName())) { continue; } } @@ -157,7 +108,7 @@ std::pair<Real, Real> calc_overlap2(const seq::ConstSequenceHandle& ref_seq, 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(); + String name=swap ? SwappedName(ai->GetName()) : ai->GetName(); AtomView av1=mdl_res ? mdl_res.FindAtom(name) : AtomView(); if (max_dist>=0){ within=ref.FindWithin(ai->GetPos(), max_dist); @@ -172,7 +123,7 @@ std::pair<Real, Real> calc_overlap2(const seq::ConstSequenceHandle& ref_seq, if (aj->GetResidue().GetNumber()==ref_res.GetNumber()) { continue; } - if (swappable(aj->GetResidue().GetName(), aj->GetName())) { + if (Swappable(aj->GetResidue().GetName(), aj->GetName())) { continue; } overlap.second+=1.0; @@ -254,8 +205,8 @@ void check_and_swap(const GlobalRDMap& glob_dist_list, const EntityView& mdl, st static_cast<Real>(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())); + if (Swappable(rname, j->GetName())) { + edi.RenameAtom(j->GetHandle(), SwappedName(j->GetName())); } } } @@ -557,8 +508,8 @@ Real LocalDistDiffTest(const ost::seq::AlignmentHandle& aln, 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())); + if (Swappable(rname, j->GetName())) { + edi.RenameAtom(j->GetHandle(), SwappedName(j->GetName())); } } } diff --git a/modules/mol/alg/src/local_dist_diff_test.hh b/modules/mol/alg/src/local_dist_diff_test.hh index 9803f0a723d3c77ae8b1332ef5ab09e444ae5ff1..6f0d2c20f7530e8ba98967612c7d7906cfc547b7 100644 --- a/modules/mol/alg/src/local_dist_diff_test.hh +++ b/modules/mol/alg/src/local_dist_diff_test.hh @@ -19,81 +19,12 @@ #ifndef OST_MOL_ALG_LOCAL_DIST_TEST_HH #define OST_MOL_ALG_LOCAL_DIST_TEST_HH -#include <ost/mol/entity_view.hh> #include <ost/mol/alg/module_config.hh> #include <ost/seq/alignment_handle.hh> +#include <ost/mol/alg/distance_test_common.hh> namespace ost { namespace mol { namespace alg { -/// \brief Contains the infomation needed to uniquely identify an atom in a structure -/// -/// Used by the the Local Distance Difference Test classes and functions -class DLLEXPORT_OST_MOL_ALG UniqueAtomIdentifier -{ - -public: - /// \brief Constructor with all the relevant information - UniqueAtomIdentifier(const String& chain,const ResNum& residue,const String& residue_name, const String& atom): chain_(chain),residue_(residue),residue_name_(residue_name),atom_(atom) {} - - // to make the compiler happy (boost python map suite) - UniqueAtomIdentifier(): chain_(""),residue_(ResNum(1)),residue_name_(""),atom_("") {} - - /// \brief Returns the name of the chain to which the atom belongs, as a String - String GetChainName() const { return chain_; } - - /// \brief Returns the ResNum of the residue to which the atom belongs - ResNum GetResNum() const { return residue_; } - - /// \brief Returns the name of the residue to which the atom belongs, as a String - String GetResidueName() const { return residue_name_; } - - /// \brief Returns the name of the atom, as a String - String GetAtomName() const { return atom_; } - - // required because UniqueAtomIdentifier is used as a key for a std::map - bool operator==(const UniqueAtomIdentifier& rhs) const { - return chain_==rhs.chain_ && residue_==rhs.residue_ && atom_==rhs.atom_; - } - - // required because UniqueAtomIdentifier is used as a key for a std::map - bool operator<(const UniqueAtomIdentifier& rhs) const { - int cc=chain_.compare(rhs.chain_); - if (cc) { - return cc<0; - } - if (residue_<rhs.residue_) { - return true; - } else if (residue_>rhs.residue_) { - return false; - } - return atom_.compare(rhs.atom_)<0; - } -private: - - String chain_; - ResNum residue_; - String residue_name_; - String atom_; -}; - -// typedef used to make the code cleaner -typedef std::pair<UniqueAtomIdentifier,UniqueAtomIdentifier> UAtomIdentifiers; - -/// \brief Residue distance list. -/// -/// Container for all the interatomic distances that are checked in a Local Distance Difference Test -/// and are originating from a single specific residue -typedef std::map<std::pair<UniqueAtomIdentifier,UniqueAtomIdentifier>,std::pair<Real,Real> > ResidueRDMap; - -/// \brief Global distance list. -/// -/// Container for all the residue-based interatomic distance lists that are checked in a Local Distance Difference Test -/// and belong to the same structure -typedef std::map<ost::mol::ResNum,ResidueRDMap> GlobalRDMap; - -// used by the multi-reference distance-list generator function -typedef std::map<UniqueAtomIdentifier,int> ExistenceMap; - /// \brief Calculates number of distances conserved in a model, given a list of distances to check and a model /// /// Calculates the two values needed to determine the Local Distance Difference Test for a given model, i.e.