diff --git a/modules/io/pymod/export_mmcif_io.cc b/modules/io/pymod/export_mmcif_io.cc index fb0e2ebe10a1c1e9f36a54168e3fa5ab9cfecb5b..aa7b290a563cefa37aa4fdea444203856293a94b 100644 --- a/modules/io/pymod/export_mmcif_io.cc +++ b/modules/io/pymod/export_mmcif_io.cc @@ -334,17 +334,21 @@ void export_mmcif_io() ; class_<MMCifInfoEntityBranch>("MMCifInfoEntityBranch", init<mol::AtomHandle, - mol::AtomHandle>()) + mol::AtomHandle, unsigned char>()) .def("GetAtom1", &MMCifInfoEntityBranch::GetAtom1) .def("GetAtom2", &MMCifInfoEntityBranch::GetAtom2) + .def("GetBondOrder", &MMCifInfoEntityBranch::GetBondOrder) .def("ConnectBranchLink", &MMCifInfoEntityBranch::ConnectBranchLink) .def("SetAtom1", &MMCifInfoEntityBranch::SetAtom1) .def("SetAtom2", &MMCifInfoEntityBranch::SetAtom2) + .def("SetBondOrder", &MMCifInfoEntityBranch::SetBondOrder) .def(self_ns::str(self)) .add_property("atom1", &MMCifInfoEntityBranch::GetAtom1, &MMCifInfoEntityBranch::SetAtom1) .add_property("atom2", &MMCifInfoEntityBranch::GetAtom2, &MMCifInfoEntityBranch::SetAtom2) + .add_property("bond_order", &MMCifInfoEntityBranch::GetBondOrder, + &MMCifInfoEntityBranch::SetBondOrder) ; class_<MMCifInfoEntityBranchMap>("MMCifInfoEntityBranchMap", init<>()) diff --git a/modules/io/src/mol/mmcif_info.cc b/modules/io/src/mol/mmcif_info.cc index c797a14f8ede547fef96a1f427beb8d6c71fc63a..43dca70f8eab97b2954550883d56386f2191e382 100644 --- a/modules/io/src/mol/mmcif_info.cc +++ b/modules/io/src/mol/mmcif_info.cc @@ -197,7 +197,8 @@ MMCifInfoStructRefSeq::AddDif(int seq_rnum, const String& db_rnum, const String& void MMCifInfo::AddEntityBranchLink(String chain_name, mol::AtomHandle atom1, - mol::AtomHandle atom2) + mol::AtomHandle atom2, + unsigned char bond_order) { // check if element already exists MMCifInfoEntityBranchMap::iterator blm_it = entity_branches_.find(chain_name); @@ -210,7 +211,7 @@ void MMCifInfo::AddEntityBranchLink(String chain_name, blm_it = rit.first; } // add new branch element - blm_it->second.push_back(MMCifInfoEntityBranch(atom1, atom2)); + blm_it->second.push_back(MMCifInfoEntityBranch(atom1, atom2, bond_order)); } const std::vector<MMCifInfoEntityBranch> MMCifInfo::GetEntityBranchLinks() const diff --git a/modules/io/src/mol/mmcif_info.hh b/modules/io/src/mol/mmcif_info.hh index 4e5e62a9df730981b7760b6247501b08ab428d4f..db32cd504f87940951a490e1c3188486fb3f7c49 100644 --- a/modules/io/src/mol/mmcif_info.hh +++ b/modules/io/src/mol/mmcif_info.hh @@ -923,14 +923,18 @@ private: /// class DLLEXPORT_OST_IO MMCifInfoEntityBranch { public: - MMCifInfoEntityBranch(mol::AtomHandle atom1, mol::AtomHandle atom2): - atom1_(atom1), atom2_(atom2) {} + MMCifInfoEntityBranch(mol::AtomHandle atom1, + mol::AtomHandle atom2, + unsigned char bond_order): +atom1_(atom1), atom2_(atom2), bond_order_(bond_order) {} mol::AtomHandle GetAtom1() const { return atom1_;} mol::AtomHandle GetAtom2() const { return atom2_; } + unsigned char GetBondOrder() const { return bond_order_; } void SetAtom1(mol::AtomHandle atom) { atom1_ = atom; } void SetAtom2(mol::AtomHandle atom) { atom2_ = atom; } + void SetBondOrder(unsigned char bond_order) { bond_order_ = bond_order; } void ConnectBranchLink(mol::XCSEditor editor) { - editor.Connect(atom1_, atom2_); + editor.Connect(atom1_, atom2_, bond_order_); } bool operator==(const MMCifInfoEntityBranch& eb) const { @@ -950,6 +954,7 @@ public: private: mol::AtomHandle atom1_; mol::AtomHandle atom2_; + unsigned char bond_order_; }; typedef std::map<String, std::vector<MMCifInfoEntityBranch> > MMCifInfoEntityBranchMap; @@ -1169,7 +1174,8 @@ public: /// \param atom2 second atom of the bond void AddEntityBranchLink(String chain_name, mol::AtomHandle atom1, - mol::AtomHandle atom2); + mol::AtomHandle atom2, + unsigned char bond_order); /// \brief Get all links for all branched entities /// diff --git a/modules/io/src/mol/mmcif_reader.cc b/modules/io/src/mol/mmcif_reader.cc index 8eeb71924f49d0a30a03325ca9b493513f129cf0..1eb1220708e8538aeb81dcc1f647e98795f62523 100644 --- a/modules/io/src/mol/mmcif_reader.cc +++ b/modules/io/src/mol/mmcif_reader.cc @@ -1757,9 +1757,13 @@ void MMCifReader::ParsePdbxEntityBranchLink(const std::vector<StringRef>& column // check stereo values to be N S R /*if (indices_[BL_ATOM_STEREO_CONFIG_2] != -1) { }*/ - // check value order to be ... git grep bond_order - /*if (indices_[BL_VALUE_ORDER] != -1) { - }*/ + // check value order + if (indices_[BL_VALUE_ORDER] != -1) { + link_pair.bond_order = MMCifValueOrderToOSTBondOrder( + columns[indices_[BL_VALUE_ORDER]]); + } else { + link_pair.bond_order = 1; + } std::pair<MMCifPdbxEntityBranchLinkMap::iterator, bool> rit; @@ -1827,7 +1831,8 @@ void MMCifReader::OnEndData() bl_it->res_num_2, ' ')); info_.AddEntityBranchLink(css->first.GetName(), res1.FindAtom(bl_it->atm_nm_1), - res2.FindAtom(bl_it->atm_nm_2)); + res2.FindAtom(bl_it->atm_nm_2), + bl_it->bond_order); } } } @@ -1924,4 +1929,64 @@ void MMCifReader::OnEndData() << strand_list_.size() << " strands"); } +unsigned char MMCifValueOrderToOSTBondOrder(const StringRef value_order) +{ + if (value_order == StringRef("sing", 4)) { + return 1; + } + if (value_order == StringRef("doub", 4)) { + return 2; + } + if (value_order == StringRef("trip", 4)) { + return 3; + } + LOG_WARNING("Non-covered bond order found: '" << value_order << "'"); + if (value_order == StringRef("arom", 4)) { + return 4; + } + if (value_order == StringRef("delo", 4)) { + return 5; + } + if (value_order == StringRef("pi", 2)) { + return 6; + } + if (value_order == StringRef("poly", 4)) { + return 7; + } + if (value_order == StringRef("quad", 4)) { + return 8; + } + return 1; +} + +String OSTBondOrderToMMCifValueOrder(const unsigned char bond_order) +{ + if (bond_order == 1) { + return String("sing"); + } + if (bond_order == 2) { + return String("doub"); + } + if (bond_order == 3) { + return String("trip"); + } + if (bond_order == 4) { + return String("arom"); + } + if (bond_order == 5) { + return String("delo"); + } + if (bond_order == 6) { + return String("pi"); + } + if (bond_order == 7) { + return String("poly"); + } + if (bond_order == 8) { + return String("quad"); + } + LOG_WARNING("Unknow bond order found: '" << (int)bond_order << "'"); + return String(""); +} + }} diff --git a/modules/io/src/mol/mmcif_reader.hh b/modules/io/src/mol/mmcif_reader.hh index 8d975600c4737a8e36e55277ec8e04c148817098..a9339c6acc6d423ff49b03d22efd8eb778dbb290 100644 --- a/modules/io/src/mol/mmcif_reader.hh +++ b/modules/io/src/mol/mmcif_reader.hh @@ -680,6 +680,7 @@ private: int res_num_2; ///< index of the linked residue relative to its chain String cmp_2; ///< tlc of residue (sugar) String atm_nm_2; ///< index of the linked residue relative to its chain + unsigned char bond_order; ///< ID of value_order as OST bond_order } MMCifPdbxEntityBranchLink; typedef std::map<String, std::vector<MMCifPdbxEntityBranchLink> > MMCifPdbxEntityBranchLinkMap; @@ -723,6 +724,18 @@ private: MMCifPdbxEntityBranchLinkMap entity_branch_link_map_; }; +/// \brief Translate mmCIF info on bond type (e.g. +/// pdbx_entity_branch_link.value_order) to OST bond_order +/// +/// \param value_order abbreviation detemrining the bond order +DLLEXPORT_OST_IO unsigned char MMCifValueOrderToOSTBondOrder( + const StringRef value_order); + +/// \brief Translate an OST bond_order to mmCIF value_order +/// +/// \param bond_order OST bond order +DLLEXPORT_OST_IO String OSTBondOrderToMMCifValueOrder( + const unsigned char bond_order); }} #endif diff --git a/modules/io/tests/test_io_mmcif.py b/modules/io/tests/test_io_mmcif.py index 8f850f55eef11d668729513c8ecdd9fc1b5ee6dd..8e909c349449776b44018dff29bb43607909430c 100644 --- a/modules/io/tests/test_io_mmcif.py +++ b/modules/io/tests/test_io_mmcif.py @@ -272,8 +272,9 @@ class TestMMCifInfo(unittest.TestCase): res2 = editor.AppendResidue(ch, "MAN"); atom1 = editor.InsertAtom(res2, "C1", geom.Vec3()); atom2 = editor.InsertAtom(res1, "O3", geom.Vec3()); - branch = io.MMCifInfoEntityBranch(atom1, atom2) + branch = io.MMCifInfoEntityBranch(atom1, atom2, 1) self.assertEqual(branch.atom1.qualified_name, "A.MAN2.C1") + self.assertEqual(branch.bond_order, 1) branch.ConnectBranchLink(editor) self.assertEqual(atom2.GetBondPartners()[0].qualified_name, "A.MAN2.C1") @@ -285,14 +286,16 @@ class TestMMCifInfo(unittest.TestCase): atom3 = editor.InsertAtom(res2, "C1", geom.Vec3()); atom4 = editor.InsertAtom(res1, "O4", geom.Vec3()); info = io.MMCifInfo() - info.AddEntityBranchLink("A", atom1, atom2) - info.AddEntityBranchLink(ch.name, atom3, atom4) + info.AddEntityBranchLink("A", atom1, atom2, 1) + info.AddEntityBranchLink(ch.name, atom3, atom4, 1) blinks = info.GetEntityBranchLinks() self.assertEqual(blinks[0].GetAtom1().qualified_name, "A.MAN2.C1") self.assertEqual(blinks[0].atom2.qualified_name, "A.BMA1.O3") + self.assertEqual(blinks[0].GetBondOrder(), 1) self.assertEqual(blinks[1].atom1.qualified_name, "B.NAG2.C1") self.assertEqual(blinks[1].GetAtom2().qualified_name, "B.NAG1.O4") + self.assertEqual(blinks[1].GetBondOrder(), 1) info.ConnectBranchLinks() self.assertEqual(atom4.GetBondPartners()[0].qualified_name, "B.NAG2.C1") diff --git a/modules/io/tests/test_mmcif_info.cc b/modules/io/tests/test_mmcif_info.cc index 6265eba1db4486dffef8ac04eeea2030d6af4f9d..2c4a760e3e41df03a2ddd32ff8d90b88ddf8be4d 100644 --- a/modules/io/tests/test_mmcif_info.cc +++ b/modules/io/tests/test_mmcif_info.cc @@ -293,10 +293,11 @@ BOOST_AUTO_TEST_CASE(mmcif_info_branch) mol::AtomHandle atom1 = editor.InsertAtom(res2, "C1",geom::Vec3()); mol::AtomHandle atom2 = editor.InsertAtom(res1, "O4",geom::Vec3()); - MMCifInfoEntityBranch branch1(atom1, atom2); + MMCifInfoEntityBranch branch1(atom1, atom2, 1); BOOST_CHECK(branch1.GetAtom1().GetQualifiedName() == "A.NAG2.C1"); BOOST_CHECK(branch1.GetAtom2().GetQualifiedName() == "A.NAG1.O4"); - + BOOST_CHECK(branch1.GetBondOrder() == 1); + BOOST_TEST_MESSAGE(" done."); } @@ -348,15 +349,17 @@ BOOST_AUTO_TEST_CASE(mmcif_info) // create AtomHandles for testing mol::AtomHandle atom21 = editor.InsertAtom(res22, "C1",geom::Vec3()); mol::AtomHandle atom22 = editor.InsertAtom(res21, "O3",geom::Vec3()); - info.AddEntityBranchLink(ch1.GetName(), atom11, atom12); - info.AddEntityBranchLink(ch2.GetName(), atom21, atom22); + info.AddEntityBranchLink(ch1.GetName(), atom11, atom12, 1); + info.AddEntityBranchLink(ch2.GetName(), atom21, atom22, 1); std::vector<MMCifInfoEntityBranch> blinks = info.GetEntityBranchLinks(); BOOST_CHECK(blinks.size() == 2); BOOST_CHECK(blinks[0].GetAtom1().GetQualifiedName() == "A.NAG2.C1"); BOOST_CHECK(blinks[0].GetAtom2().GetQualifiedName() == "A.NAG1.O4"); + BOOST_CHECK(blinks[0].GetBondOrder() == 1); BOOST_CHECK(blinks[1].GetAtom1().GetQualifiedName() == "B.MAN2.C1"); BOOST_CHECK(blinks[1].GetAtom2().GetQualifiedName() == "B.BMA1.O3"); + BOOST_CHECK(blinks[1].GetBondOrder() == 1); // check that branch links get bonds info.ConnectBranchLinks();