diff --git a/modules/mol/base/pymod/export_editors.cc b/modules/mol/base/pymod/export_editors.cc index 4d3b42197fcc22a8d98a6d4e2e1b58e2d34bfdb7..2a59feef9f8527366fdb3cd122d8e01fc87abf38 100644 --- a/modules/mol/base/pymod/export_editors.cc +++ b/modules/mol/base/pymod/export_editors.cc @@ -48,15 +48,15 @@ ResidueHandle (EditorBase::*append_a)(ChainHandle ch, ResidueHandle (EditorBase::*append_b)(ChainHandle ch, const ResidueKey&, const ResNum&)=&EditorBase::AppendResidue; -void (ICSEditor::*set_torsion_a)(TorsionHandle, Real)=&ICSEditor::SetTorsionAngle; +void (ICSEditor::*set_torsion_a)(TorsionHandle, Real, bool)=&ICSEditor::SetTorsionAngle; void (ICSEditor::*set_torsion_b)(const AtomHandle&, const AtomHandle&, const AtomHandle&, const AtomHandle&, - Real)=&ICSEditor::SetTorsionAngle; + Real, bool)=&ICSEditor::SetTorsionAngle; -void (ICSEditor::*rotate_torsion_a)(TorsionHandle, Real)=&ICSEditor::RotateTorsionAngle; +void (ICSEditor::*rotate_torsion_a)(TorsionHandle, Real, bool)=&ICSEditor::RotateTorsionAngle; void (ICSEditor::*rotate_torsion_b)(const AtomHandle&, const AtomHandle&, const AtomHandle&, const AtomHandle&, - Real)=&ICSEditor::RotateTorsionAngle; + Real, bool)=&ICSEditor::RotateTorsionAngle; #if OST_NUMPY_SUPPORT_ENABLED template<typename T, bool O> @@ -234,10 +234,16 @@ void export_Editors() class_<ICSEditor, bases<EditorBase> >("ICSEditor", no_init) .def("SetAngle", &ICSEditor::SetAngle) .def("SetBondLength", &ICSEditor::SetBondLength) - .def("SetTorsionAngle", set_torsion_a) - .def("SetTorsionAngle", set_torsion_b) - .def("RotateTorsionAngle", rotate_torsion_a) - .def("RotateTorsionAngle", rotate_torsion_b) + .def("SetTorsionAngle", set_torsion_a, + (arg("torsion"),arg("angle"), arg("update_others")=true)) + .def("SetTorsionAngle", set_torsion_b, + (arg("atom_a"), arg("atom_b"), arg("atom_c"), arg("atom_d"), + arg("angle"), arg("update_others"))) + .def("RotateTorsionAngle", rotate_torsion_a, + (arg("torsion"),arg("angle"), arg("update_others")=true)) + .def("RotateTorsionAngle", rotate_torsion_b, + (arg("atom_a"), arg("atom_b"), arg("atom_c"), arg("atom_d"), + arg("angle"), arg("update_others"))) .def("UpdateXCS", &ICSEditor::UpdateXCS) .def("__exit__", &ICSEditor::UpdateXCS) ; diff --git a/modules/mol/base/pymod/export_torsion.cc b/modules/mol/base/pymod/export_torsion.cc index e7b45e0fd4c3afb385410f688267e05406351250..fbf9e2b726880b9e56a430e3def0aa50f0c1fd7b 100644 --- a/modules/mol/base/pymod/export_torsion.cc +++ b/modules/mol/base/pymod/export_torsion.cc @@ -49,14 +49,8 @@ void export_Torsion() .add_property("third", &TorsionHandle::GetThird) .add_property("fourth", &TorsionHandle::GetFourth) .def("IsValid", &TorsionHandle::IsValid) - .def("SetAngle", &TorsionHandle::SetAngle) .def("GetAngle", &TorsionHandle::GetAngle) - .def("RotateAngle", &TorsionHandle::RotateAngle, - X_rotate_angle_overloads(args("angle", "up"))) - .add_property("angle", &TorsionHandle::GetAngle, - &TorsionHandle::SetAngle) - .def("SetAngle", &TorsionHandle::SetAngle, - X_set_angle_overloads(args("angle", "up"))) + .add_property("angle", &TorsionHandle::GetAngle) .def(self_ns::str(self)) ; diff --git a/modules/mol/base/src/ics_editor.cc b/modules/mol/base/src/ics_editor.cc index c374a0f09697accb0f56fee925200d3b03df4879..910c7fd85365f747e12eed613147bde49b2a4fdb 100644 --- a/modules/mol/base/src/ics_editor.cc +++ b/modules/mol/base/src/ics_editor.cc @@ -23,6 +23,7 @@ #include "impl/torsion_impl.hh" #include "impl/entity_impl.hh" #include "impl/connector_impl.hh" +#include "impl/atom_impl.hh" /* Author: Marco Biasini */ @@ -96,18 +97,20 @@ bool ICSEditor::SetAngle(const AtomHandle& atom_a, const AtomHandle& atom_b, return return_value; } -void ICSEditor::SetTorsionAngle(TorsionHandle torsion, Real angle) +void ICSEditor::SetTorsionAngle(TorsionHandle torsion, Real angle, + bool update_others) { CheckHandleValidity(torsion); - torsion.Impl()->SetAngle(angle, false); + torsion.Impl()->SetAngle(angle, update_others); ent_.Impl()->MarkXCSDirty(); this->Update(); } -void ICSEditor::RotateTorsionAngle(TorsionHandle torsion, Real angle) +void ICSEditor::RotateTorsionAngle(TorsionHandle torsion, Real angle, + bool update_others) { CheckHandleValidity(torsion); - torsion.Impl()->RotateAngle(angle, false); + torsion.Impl()->RotateAngle(angle, update_others); ent_.Impl()->MarkXCSDirty(); this->Update(); } @@ -116,7 +119,9 @@ void ICSEditor::RotateTorsionAngle(TorsionHandle torsion, Real angle) void ICSEditor::RotateTorsionAngle(const AtomHandle& atom_a, const AtomHandle& atom_b, const AtomHandle& atom_c, - const AtomHandle& atom_d, Real angle) + const AtomHandle& atom_d, + Real angle, + bool update_others) { CheckHandleValidity(atom_a); CheckHandleValidity(atom_b); @@ -124,7 +129,7 @@ void ICSEditor::RotateTorsionAngle(const AtomHandle& atom_a, CheckHandleValidity(atom_d); impl::Dihedral d(atom_a.Impl(), atom_b.Impl(), atom_c.Impl(), atom_d.Impl()); Real cur_angle=d.GetAngleICS(); - d.SetAngleICS(cur_angle+angle); + d.SetAngleICS(cur_angle+angle, update_others); ent_.Impl()->MarkXCSDirty(); this->Update(); } @@ -133,16 +138,19 @@ void ICSEditor::RotateTorsionAngle(const AtomHandle& atom_a, void ICSEditor::SetTorsionAngle(const AtomHandle& atom_a, const AtomHandle& atom_b, const AtomHandle& atom_c, - const AtomHandle& atom_d, Real angle) + const AtomHandle& atom_d, + Real angle, + bool update_others) { CheckHandleValidity(atom_a); CheckHandleValidity(atom_b); CheckHandleValidity(atom_c); CheckHandleValidity(atom_d); impl::Dihedral d(atom_a.Impl(), atom_b.Impl(), atom_c.Impl(), atom_d.Impl()); - d.SetAngleICS(angle, false); + d.SetAngleICS(angle, update_others); ent_.Impl()->MarkXCSDirty(); this->Update(); } + }} // ns diff --git a/modules/mol/base/src/ics_editor.hh b/modules/mol/base/src/ics_editor.hh index 9643336949dbf2fe700187feee372f5baca235cc..eb51807432d2a9aa3f2ddeb08b48c5a8ea88d073 100644 --- a/modules/mol/base/src/ics_editor.hh +++ b/modules/mol/base/src/ics_editor.hh @@ -74,19 +74,22 @@ public: /// bonds untouched, use the SetDihedralAngle() function /// /// \sa RotateTorsionAngle - void SetTorsionAngle(TorsionHandle torsion, Real angle); + void SetTorsionAngle(TorsionHandle torsion, Real angle, + bool update_others=true); /// \brief rotate torsion angle - void RotateTorsionAngle(TorsionHandle torsion, Real delta); + void RotateTorsionAngle(TorsionHandle torsion, Real delta, + bool update_others=true); void RotateTorsionAngle(const AtomHandle& atom_a, const AtomHandle& atom_b, const AtomHandle& atom_c, const AtomHandle& atom_d, - Real angle); + Real angle, + bool update_others=true); void SetTorsionAngle(const AtomHandle& atom_a, const AtomHandle& atom_b, const AtomHandle& atom_c, const AtomHandle& atom_d, - Real angle); + Real angle, bool update_others=true); /// \brief immediately update external coordinate system void UpdateXCS(); diff --git a/modules/mol/base/src/impl/dihedral.hh b/modules/mol/base/src/impl/dihedral.hh index 2996205ba7e06cfd53c2a45829335c365a034d28..a722c93e60ff4b8d015d5f5bb97bc7d1b3a9709c 100644 --- a/modules/mol/base/src/impl/dihedral.hh +++ b/modules/mol/base/src/impl/dihedral.hh @@ -52,7 +52,7 @@ public: /// \param update_other /// If true, connectors of atom3 are updated accordingly, otherwise /// they will be left untouched - void SetAngleICS(Real angle, bool update_other=false); + void SetAngleICS(Real angle, bool update_other); geom::Vec3 GetPos() const; geom::Vec3 GetOriginalPos() const; diff --git a/modules/mol/base/src/impl/torsion_impl.cc b/modules/mol/base/src/impl/torsion_impl.cc index 744d648f33f3139d1bb03c7327f8ef0a9a77b7f1..9f9ffcdd9b74fa46969ed70f934b1c0a434e4602 100644 --- a/modules/mol/base/src/impl/torsion_impl.cc +++ b/modules/mol/base/src/impl/torsion_impl.cc @@ -48,8 +48,8 @@ Real TorsionImpl::GetAngle() const { } } -void TorsionImpl::SetAngle(Real angle, bool up) { - this->SetAngleICS(angle, true); +void TorsionImpl::SetAngle(Real angle, bool update_others) { + this->SetAngleICS(angle, update_others); } void TorsionImpl::Apply(EntityVisitor& v) { @@ -57,8 +57,8 @@ void TorsionImpl::Apply(EntityVisitor& v) { v.VisitTorsion(TorsionHandle(shared_from_this())); } -void TorsionImpl::RotateAngle(Real angle, bool up) { - this->SetAngle(this->GetAngleICS()+angle, up); +void TorsionImpl::RotateAngle(Real angle, bool update_others) { + this->SetAngle(this->GetAngleICS()+angle, update_others); } }}} // ns diff --git a/modules/mol/base/src/torsion_handle.cc b/modules/mol/base/src/torsion_handle.cc index c4bac5ff1455e70cf4ba5f3ba51c650d9cea3334..2830bc8211ef30477693f3610b76b46fdf79d27e 100644 --- a/modules/mol/base/src/torsion_handle.cc +++ b/modules/mol/base/src/torsion_handle.cc @@ -95,18 +95,6 @@ Real TorsionHandle::GetAngle() const this->CheckValidity(); return impl_->GetAngle(); } - -void TorsionHandle::SetAngle(Real a, bool up) -{ - this->CheckValidity(); - impl_->SetAngle(a, up); -} - -void TorsionHandle::RotateAngle(Real angle, bool up) -{ - this->CheckValidity(); - impl_->RotateAngle(angle, up); -} void TorsionHandle::CheckValidity() const { if (!impl_) diff --git a/modules/mol/base/src/torsion_handle.hh b/modules/mol/base/src/torsion_handle.hh index 856cd67e731983ee898213101d52764b214ddb07..06f7e7bf0eb7283318617f8fd0a4f222718f87ad 100644 --- a/modules/mol/base/src/torsion_handle.hh +++ b/modules/mol/base/src/torsion_handle.hh @@ -87,18 +87,6 @@ public: /// \brief get position, i.e midpoint between the second and third atom (original coordinates) geom::Vec3 GetOriginalPos() const; - /// \brief set absolute torsion angle - /// - /// All connectors at the third atom (A3) will be adjusted accordingly. If - /// you only want to adjust the bond between A3 and A4, and leave the other - /// bonds untouched, use the ost::SetDihedralAngle() function - /// - /// \sa RotateAngle - void SetAngle(Real a, bool up=true); - - /// relative rotation, either upstream or downstream - void RotateAngle(Real angle, bool up=true); - impl::TorsionImplP& Impl() { return impl_; } diff --git a/modules/mol/base/tests/test_ics.cc b/modules/mol/base/tests/test_ics.cc index 8c26db5d96c1738e8454487366989ca1041255c1..f7ffd372289be951b9ecdec7968e375c15a8ab0a 100644 --- a/modules/mol/base/tests/test_ics.cc +++ b/modules/mol/base/tests/test_ics.cc @@ -59,6 +59,37 @@ struct Structure { AtomHandle a5; }; +struct TorsionStructure { + TorsionStructure() + { + e=CreateEntity(); + ICSEditor editor=e.EditICS(); + c=editor.InsertChain("A"); + r=editor.AppendResidue(c, "TORSTIN"); + a1=editor.InsertAtom(r, "X1", geom::Vec3( 0.0, -1.0, 0.0)); + a2=editor.InsertAtom(r, "X2", geom::Vec3( 1.0, 0.0, 0.0)); + a3=editor.InsertAtom(r, "X3", geom::Vec3( 2.0, 0.0, 0.0)); + a4=editor.InsertAtom(r, "X4", geom::Vec3( 3.0, 1.0, 0.0)); + a5=editor.InsertAtom(r, "X5", geom::Vec3( 3.0, -1.0, 0.0)); + editor.Connect(a1, a2); + editor.Connect(a2, a3); + editor.Connect(a3, a4); + editor.Connect(a3, a5); + t1 = editor.AddTorsion("T1", a1, a2, a3, a4); + t2 = editor.AddTorsion("T2", a1, a2, a3, a5); + } + EntityHandle e; + ChainHandle c; + ResidueHandle r; + AtomHandle a1; + AtomHandle a2; + AtomHandle a3; + AtomHandle a4; + AtomHandle a5; + TorsionHandle t1; + TorsionHandle t2; +}; + const static Real EPSILON=0.000001; Real angle_xcs(AtomHandle a1, AtomHandle a2, AtomHandle a3) { @@ -72,6 +103,111 @@ bool test_angle(Real a, Real e) { BOOST_AUTO_TEST_SUITE( mol_base ) +BOOST_AUTO_TEST_CASE(ics_settorsion_unbuffered) +{ + Real eps = 0.0001; + TorsionStructure s; + ICSEditor e = s.e.EditICS(mol::UNBUFFERED_EDIT); + BOOST_CHECK_CLOSE(s.t1.GetAngle(), M_PI, eps); + BOOST_CHECK_SMALL(s.t2.GetAngle(), eps); + e.SetTorsionAngle(s.t1,0); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI, eps); + e.SetTorsionAngle(s.t2,M_PI/4); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI/4, eps); + BOOST_CHECK_CLOSE(s.t1.GetAngle(), -M_PI+M_PI/4, eps); + e.SetTorsionAngle(s.t1,-M_PI/4); + BOOST_CHECK_CLOSE(s.t1.GetAngle(), -M_PI/4, eps); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), 3/4.*M_PI, eps); + e.RotateTorsionAngle(s.t1, M_PI/4); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_CLOSE(std::abs(s.t2.GetAngle()), M_PI, eps); +} + +BOOST_AUTO_TEST_CASE(ics_settorsion_buffered) +{ + Real eps = 0.0001; + TorsionStructure s; + ICSEditor e = s.e.EditICS(mol::BUFFERED_EDIT); + BOOST_CHECK_CLOSE(s.t1.GetAngle(), M_PI, eps); + BOOST_CHECK_SMALL(s.t2.GetAngle(), eps); + e.SetTorsionAngle(s.t1,0); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI, eps); + e.SetTorsionAngle(s.t2,M_PI/4); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI/4, eps); + BOOST_CHECK_CLOSE(s.t1.GetAngle(), -M_PI+M_PI/4, eps); + e.SetTorsionAngle(s.t1,-M_PI/4); + BOOST_CHECK_CLOSE(s.t1.GetAngle(), -M_PI/4, eps); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), 3/4.*M_PI, eps); + e.RotateTorsionAngle(s.t1, M_PI/4); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_CLOSE(std::abs(s.t2.GetAngle()), M_PI, eps); +} + +BOOST_AUTO_TEST_CASE(ics_settorsion_unbuffered_update_others) +{ + Real eps = 0.0001; + TorsionStructure s; + ICSEditor e = s.e.EditICS(mol::UNBUFFERED_EDIT); + BOOST_CHECK_CLOSE(s.t1.GetAngle(), M_PI, eps); + BOOST_CHECK_SMALL(s.t2.GetAngle(), eps); + e.SetTorsionAngle(s.t1,0,false); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_SMALL(s.t2.GetAngle(), eps); + e.SetTorsionAngle(s.t2,M_PI/4,false); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI/4, eps); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + e.SetTorsionAngle(s.t1,-M_PI/4,false); + BOOST_CHECK_CLOSE(s.t1.GetAngle(), -M_PI/4, eps); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI/4, eps); + e.RotateTorsionAngle(s.t1, M_PI/4,false); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI/4, eps); +} + +BOOST_AUTO_TEST_CASE(ics_settorsion_buffered_update_others) +{ + Real eps = 0.0001; + TorsionStructure s; + ICSEditor e = s.e.EditICS(mol::BUFFERED_EDIT); + BOOST_CHECK_CLOSE(s.t1.GetAngle(), M_PI, eps); + BOOST_CHECK_SMALL(s.t2.GetAngle(), eps); + e.SetTorsionAngle(s.t1,0,false); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_SMALL(s.t2.GetAngle(), eps); + e.SetTorsionAngle(s.t2,M_PI/4,false); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI/4, eps); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + e.SetTorsionAngle(s.t1,-M_PI/4,false); + BOOST_CHECK_CLOSE(s.t1.GetAngle(), -M_PI/4, eps); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI/4, eps); + e.RotateTorsionAngle(s.t1, M_PI/4,false); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI/4, eps); +} + +BOOST_AUTO_TEST_CASE(ics_settorsion_linear_unbuffered) +{ + Real eps = 0.0001; + TorsionStructure s; + ICSEditor e = s.e.EditICS(mol::UNBUFFERED_EDIT); + e.SetAngle(s.a2,s.a3,s.a4,M_PI); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_SMALL(s.t2.GetAngle(), eps); + e.SetTorsionAngle(s.t1,0); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_SMALL(s.t2.GetAngle(), eps); + e.SetTorsionAngle(s.t2,M_PI/4); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI/4, eps); + e.SetTorsionAngle(s.t1,-M_PI/4); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_SMALL(s.t2.GetAngle(), eps); + e.RotateTorsionAngle(s.t1, M_PI/4); + BOOST_CHECK_SMALL(s.t1.GetAngle(), eps); + BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI/4, eps); +} BOOST_AUTO_TEST_CASE(ics_angle_trivia) { @@ -147,4 +283,4 @@ BOOST_AUTO_TEST_CASE(ics_get_angle) << " found"); } -BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file +BOOST_AUTO_TEST_SUITE_END()