From 2de8fa94abb17dee2d8be291c5ba61965e38797a Mon Sep 17 00:00:00 2001
From: B13nch3n <stefan.bienert@me.com>
Date: Fri, 17 Jul 2020 16:48:03 +0200
Subject: [PATCH] SCHWED-4848: Function to get chain names of branched entitis

---
 modules/io/doc/mmcif.rst            |  6 ++++++
 modules/io/pymod/export_mmcif_io.cc | 15 +++++++++++++++
 modules/io/src/mol/mmcif_info.cc    | 11 +++++++++++
 modules/io/src/mol/mmcif_info.hh    |  5 +++++
 modules/io/tests/test_io_mmcif.py   |  3 +++
 modules/io/tests/test_mmcif_info.cc |  7 ++++++-
 6 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/modules/io/doc/mmcif.rst b/modules/io/doc/mmcif.rst
index a2111f546..924065a11 100644
--- a/modules/io/doc/mmcif.rst
+++ b/modules/io/doc/mmcif.rst
@@ -1246,6 +1246,12 @@ of the annotation available.
     :type editor: :class:`~ost.mol.XCSEditor`
     :returns: Nothing
 
+  .. method:: GetEntityBranchChainNames
+
+    Get a list of chain names which contain branched entities.
+
+    :returns: :class:`list` od :class:`str`
+
   .. method:: GetAtom1
 
     See :attr:`atom1`
diff --git a/modules/io/pymod/export_mmcif_io.cc b/modules/io/pymod/export_mmcif_io.cc
index b8dae1b05..f64403548 100644
--- a/modules/io/pymod/export_mmcif_io.cc
+++ b/modules/io/pymod/export_mmcif_io.cc
@@ -30,6 +30,20 @@ using namespace ost;
 using namespace ost::io;
 using namespace ost::mol;
 
+template<typename T>
+boost::python::list VecToList(std::vector<T>& vec){
+  boost::python::list l;
+  for(typename std::vector<T>::iterator it=vec.begin();it!=vec.end();++it){
+    l.append(*it);
+  }
+  return l;
+}
+
+boost::python::list WrapGetNames(MMCifInfo *p){
+  std::vector<String> names = p->GetEntityBranchChainNames();
+  return VecToList<String>(names);
+}
+
 void export_mmcif_io()
 {
   class_<MMCifReader, boost::noncopyable>("MMCifReader", init<const String&, EntityHandle&, const IOProfile&>())
@@ -400,6 +414,7 @@ void export_mmcif_io()
     .def("AddEntityBranchLink", &MMCifInfo::AddEntityBranchLink)
     .def("GetEntityBranchLinks", &MMCifInfo::GetEntityBranchLinks)
     .def("ConnectBranchLinks", &MMCifInfo::ConnectBranchLinks)
+    .def("GetEntityBranchChainNames", &WrapGetNames)
     .add_property("citations", make_function(&MMCifInfo::GetCitations,
                                    return_value_policy<copy_const_reference>()))
     .add_property("biounits", make_function(&MMCifInfo::GetBioUnits,
diff --git a/modules/io/src/mol/mmcif_info.cc b/modules/io/src/mol/mmcif_info.cc
index 5db86d1cc..1fb5ee93d 100644
--- a/modules/io/src/mol/mmcif_info.cc
+++ b/modules/io/src/mol/mmcif_info.cc
@@ -227,6 +227,17 @@ const std::vector<MMCifInfoEntityBranchLink> MMCifInfo::GetEntityBranchLinks() c
   return all_links;
 }
 
+const std::vector<String> MMCifInfo::GetEntityBranchChainNames() const
+{
+  std::vector<String> chain_names;
+  MMCifInfoEntityBranchLinkMap::const_iterator blm_it;
+  for (blm_it = entity_branches_.begin();
+       blm_it != entity_branches_.end(); ++blm_it) {
+    chain_names.push_back(blm_it->first);
+  }
+  return chain_names;
+}
+
 void MMCifInfo::ConnectBranchLinks()
 {
   MMCifInfoEntityBranchLinkMap::iterator blm_it;
diff --git a/modules/io/src/mol/mmcif_info.hh b/modules/io/src/mol/mmcif_info.hh
index 76d418147..510365d49 100644
--- a/modules/io/src/mol/mmcif_info.hh
+++ b/modules/io/src/mol/mmcif_info.hh
@@ -1180,6 +1180,11 @@ public:
   /// \brief Get all links for all branched entities
   ///
   const std::vector<MMCifInfoEntityBranchLink> GetEntityBranchLinks() const;
+
+  /// \brief Get the names of all chains of branched entities.
+  ///
+  const std::vector<String> GetEntityBranchChainNames() const;
+
   //GetEntityBranchChains
   //GetEntityBranchByChain
 
diff --git a/modules/io/tests/test_io_mmcif.py b/modules/io/tests/test_io_mmcif.py
index d0f902ac4..ad16f55e1 100644
--- a/modules/io/tests/test_io_mmcif.py
+++ b/modules/io/tests/test_io_mmcif.py
@@ -300,6 +300,9 @@ class TestMMCifInfo(unittest.TestCase):
     info.ConnectBranchLinks()
     self.assertEqual(atom4.GetBondPartners()[0].qualified_name, "B.NAG2.C1")
 
+    chain_names = info.GetEntityBranchChainNames()
+    self.assertEqual(chain_names, ['A', 'B'])
+
 if __name__== '__main__':
   from ost import testutils
   testutils.RunTests()
diff --git a/modules/io/tests/test_mmcif_info.cc b/modules/io/tests/test_mmcif_info.cc
index 0ab74afb9..7c5db68ee 100644
--- a/modules/io/tests/test_mmcif_info.cc
+++ b/modules/io/tests/test_mmcif_info.cc
@@ -352,7 +352,7 @@ BOOST_AUTO_TEST_CASE(mmcif_info)
   info.AddEntityBranchLink(ch1.GetName(), atom11, atom12, 1);
   info.AddEntityBranchLink(ch2.GetName(), atom21, atom22, 1);
   std::vector<MMCifInfoEntityBranchLink> 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");
@@ -367,6 +367,11 @@ BOOST_AUTO_TEST_CASE(mmcif_info)
   BOOST_CHECK(atom11.GetBondPartners()[0] == atom12);
   BOOST_CHECK(atom22.GetBondPartners()[0] == atom21);
 
+  // check chain(name) retrieval works
+  std::vector<String> chain_names = info.GetEntityBranchChainNames();
+  BOOST_CHECK(chain_names[0] == "A");
+  BOOST_CHECK(chain_names[1] == "B");
+
   BOOST_TEST_MESSAGE("  done.");
 }
 
-- 
GitLab