diff --git a/modules/mol/base/doc/entity.rst b/modules/mol/base/doc/entity.rst
index 3a4d0d292748f1c8f7546468d8f8b4657c9d10c2..aeb18459f28e01c33c3c09a48dd8d9b9ee342822 100644
--- a/modules/mol/base/doc/entity.rst
+++ b/modules/mol/base/doc/entity.rst
@@ -342,7 +342,94 @@ The Handle Classes
 
   A chain of one or more :class:`residues <ResidueHandle>`. Chains are always 
   part of an entity.
-  
+
+  .. attribute:: atoms
+
+     Get list of all atoms of this chain. To access a single atom, use
+     :meth:`FindAtom`.
+
+     This property is read-only. Also available as :meth:`GetAtomList`
+
+     :type: :class:`AtomHandleList` (list of :class:`AtomHandle`)
+
+  .. attribute:: bounds
+
+    Axis-aligned bounding box of the chain. Read-only
+
+    :type: :class:`ost.geom.AlignedCuboid`
+
+  .. attribute:: center_of_atoms
+
+    Center of atoms (not mass weighted). Also available as
+    :meth:`GetCenterOfAtoms`.
+
+    :type: :class:`~ost.geom.Vec3`
+
+  .. attribute:: center_of_mass
+
+    Center of mass. Also available as :meth:`GetCenterOfMass`
+
+    :type: :class:`~ost.geom.Vec3`
+
+  .. attribute:: description
+
+     Details about the chain. Not categorised, just text.
+
+  .. attribute:: in_sequence
+
+     Whether the residue numbers are in ascending order. For example:
+
+     .. code-block:: python
+
+       chain=ent.FindChain("A")
+       print(chain.residues) # [A.GLY1, A.GLY2, A.GLY4A, A.GLY4B]
+       print(chain.in_sequence) # prints true
+
+       chain=ent.FindChain("B")
+       print(chain.residues) # [B.GLY1, B.GLY4, B.GLY3]
+       print(chain.in_sequence) # prints false
+
+  .. attribute:: is_oligosaccharide
+
+    Indicates if the chain is an oligosaccharide, a branched, non-linear entity
+    of multiple sugars. Also available as :meth:`IsOligosaccharide`.
+
+    :type: :class:`bool`
+
+  .. attribute:: is_polymer
+
+    Indicates if a chain is a polymer. True for polypeptides, polynucleotides,
+    polysaccharides, oligosaccharides and branched chains. Also available as
+    :meth:`IsPolymer`.
+
+    :type: :class:`bool`
+
+  .. attribute:: is_polynucleotide
+
+    Indicates if a chain is a nucleic acid. Also available as
+    :meth:`IsPolynucleotide`.
+
+    :type: :class:`bool`
+
+  .. attribute:: is_polypeptide
+
+    Indicates if a chain is a protein. Also available as :meth:`IsPolypeptide`.
+
+    :type: :class:`bool`
+
+  .. attribute:: is_polysaccharide
+
+    Indicates if a chain is a polysaccharide. Also available as
+    :meth:`IsPolysaccharide()`.
+
+    :type: :class:`bool`
+
+  .. attribute:: mass
+
+    The total mass of this chain in Dalton. Also available as :meth:`GetMass`
+
+    :type: float
+
   .. attribute:: name
   
      The chain name. The name uniquely identifies the chain in the entity. In 
@@ -356,15 +443,11 @@ The Handle Classes
      
      :type: str
 
-  .. attribute:: type
-
-     Describes the type of the chain.
-
-     :type: :class:`ChainType`.
+  .. attribute:: residue_count
 
-  .. attribute:: description
+    Number of residues. Read-only. See :meth:`GetResidueCount`.
 
-     Details about the chain. Not categorised, just text.
+    :type: :class:`int`
 
   .. attribute:: residues
    
@@ -387,59 +470,11 @@ The Handle Classes
 
      :type: :class:`ResidueHandleList` (list of :class:`ResidueHandle`)
   
-  .. attribute:: in_sequence
-  
-     Whether the residue numbers are in ascending order. For example:
-     
-     .. code-block:: python
-     
-       chain=ent.FindChain("A")
-       print(chain.residues) # [A.GLY1, A.GLY2, A.GLY4A, A.GLY4B]
-       print(chain.in_sequence) # prints true
-       
-       chain=ent.FindChain("B")
-       print(chain.residues) # [B.GLY1, B.GLY4, B.GLY3]
-       print(chain.in_sequence) # prints false
-
-  .. attribute:: residue_count
-
-    Number of residues. Read-only. See :meth:`GetResidueCount`.
-
-    :type: :class:`int`
-
-  .. attribute:: atoms
-
-     Get list of all atoms of this chain. To access a single atom, use
-     :meth:`FindAtom`.
-   
-     This property is read-only. Also available as :meth:`GetAtomList`
-
-     :type: :class:`AtomHandleList` (list of :class:`AtomHandle`)
-
-  .. attribute:: bounds
-
-    Axis-aligned bounding box of the chain. Read-only
-
-    :type: :class:`ost.geom.AlignedCuboid`
-          
-  .. attribute:: mass
-  
-    The total mass of this chain in Dalton. Also available as :meth:`GetMass`
-  
-    :type: float
+  .. attribute:: type
 
-  .. attribute:: center_of_mass
+     Describes the type of the chain.
 
-    Center of mass. Also available as :meth:`GetCenterOfMass`
-  
-    :type: :class:`~ost.geom.Vec3`
-  
-  .. attribute:: center_of_atoms
-    
-    Center of atoms (not mass weighted). Also available as 
-    :meth:`GetCenterOfAtoms`.
-    
-    :type: :class:`~ost.geom.Vec3`
+     :type: :class:`ChainType`.
 
   .. attribute:: valid
 
@@ -491,6 +526,26 @@ The Handle Classes
 
     See :attr:`type`
 
+  .. method:: IsOligosaccharide()
+
+    See :attr:`is_oligosaccharide`
+
+  .. method:: IsPolymer()
+
+    See :attr:`is_polymer`
+
+  .. method:: IsPolynucleotide()
+
+    See :attr:`is_polynucleotide`
+
+  .. method:: IsPolypeptide()
+
+    See :attr:`is_polypeptide`
+
+  .. method:: IsPolysaccharide()
+
+    See :attr:`is_polysaccharide`
+
   .. method:: GetDescription()
 
     See :attr:`description`
diff --git a/modules/mol/base/pymod/export_chain.cc b/modules/mol/base/pymod/export_chain.cc
index 1664c13a33ed03c1fbdc404bbac9b081522c8e4a..b5ce6d91cba30b6a3dab3a83a066f044139e1d41 100644
--- a/modules/mol/base/pymod/export_chain.cc
+++ b/modules/mol/base/pymod/export_chain.cc
@@ -58,10 +58,12 @@ void export_Chain()
     .def("IsPolypeptide", &ChainBase::IsPolypeptide)
     .def("IsPolynucleotide", &ChainBase::IsPolynucleotide)
     .def("IsPolysaccharide", &ChainBase::IsPolysaccharide)
+    .def("IsOligosaccharide", &ChainBase::IsOligosaccharide)
     .def("IsPolymer", &ChainBase::IsPolymer)
     .add_property("is_polypeptide", &ChainBase::IsPolypeptide)
     .add_property("is_polynucleotide", &ChainBase::IsPolynucleotide)
     .add_property("is_polysaccharide", &ChainBase::IsPolysaccharide)
+    .add_property("is_oligosaccharide", &ChainBase::IsOligosaccharide)
     .add_property("is_polymer", &ChainBase::IsPolymer)
     .add_property("type", &ChainBase::GetType)
     .add_property("description", &ChainBase::GetDescription)
diff --git a/modules/mol/base/src/chain_base.cc b/modules/mol/base/src/chain_base.cc
index 4114a1462be137b7ea2e84cac6618df2309849e3..2b693b7fc031d07bf3da2492a1644db649557b30 100644
--- a/modules/mol/base/src/chain_base.cc
+++ b/modules/mol/base/src/chain_base.cc
@@ -81,6 +81,13 @@ bool ChainBase::IsPolysaccharide() const
   
 }
 
+bool ChainBase::IsOligosaccharide() const
+{
+  this->CheckValidity();
+  return impl_->IsOligosaccharide();
+
+}
+
 bool ChainBase::IsPolypeptide() const
 {
   this->CheckValidity();
diff --git a/modules/mol/base/src/chain_base.hh b/modules/mol/base/src/chain_base.hh
index 5463ef0a8627eac578b12e801618da69bc74c898..0ab82a3dbaf784193d3ba09fe1e687af4f96eaeb 100644
--- a/modules/mol/base/src/chain_base.hh
+++ b/modules/mol/base/src/chain_base.hh
@@ -82,7 +82,10 @@ public:
   
   /// \brief whether the chain is a polysaccharide
   bool IsPolysaccharide() const;
-  
+
+  /// \brief whether the chain is an oligsaccharide (branched mmCIF entity)
+  bool IsOligosaccharide() const;
+
   /// \brief whether the chain is a polypeptide
   bool IsPolypeptide() const;
   
diff --git a/modules/mol/base/src/impl/chain_impl.hh b/modules/mol/base/src/impl/chain_impl.hh
index a3a7a97dcec720f024c39a2bcf73ff0bc108e9b6..e5bc7aac338d1d3c82c81730b9b5709eba7cf569 100644
--- a/modules/mol/base/src/impl/chain_impl.hh
+++ b/modules/mol/base/src/impl/chain_impl.hh
@@ -69,14 +69,20 @@ public:
   {
     return type_==CHAINTYPE_POLY || this->IsPolypeptide() || 
            this->IsPolynucleotide() || this->IsPolysaccharide() ||
-           type_==CHAINTYPE_POLY_PEPTIDE_DN_RN ||
-           type_==CHAINTYPE_OLIGOSACCHARIDE;
+           this->IsOligosaccharide() ||
+           type_==CHAINTYPE_POLY_PEPTIDE_DN_RN || type_==CHAINTYPE_BRANCHED;
   }
   /// \brief whether the chain is a polysaccharide
   bool IsPolysaccharide() const
   {
     return type_==CHAINTYPE_POLY_SAC_D || type_==CHAINTYPE_POLY_SAC_L;
   }
+
+  /// \brief whether the chain is a polysaccharide
+  bool IsOligosaccharide() const
+  {
+    return type_==CHAINTYPE_OLIGOSACCHARIDE;
+  }
   /// \brief whether the chain is a polypeptide
   bool IsPolypeptide() const
   {
diff --git a/modules/mol/base/tests/test_chain.cc b/modules/mol/base/tests/test_chain.cc
index 2154bdeab94555e73c89892847e6f9cac1759af4..f965fced69eb87d610baec27f4830e8d82202369 100644
--- a/modules/mol/base/tests/test_chain.cc
+++ b/modules/mol/base/tests/test_chain.cc
@@ -235,59 +235,69 @@ BOOST_AUTO_TEST_CASE(chain_type)
    BOOST_CHECK(ch1.GetType() == CHAINTYPE_UNKNOWN);
    BOOST_CHECK(!ch1.IsPolymer());
    BOOST_CHECK(!ch1.IsPolysaccharide());
+   BOOST_CHECK(!ch1.IsOligosaccharide());
    BOOST_CHECK(!ch1.IsPolypeptide());
    BOOST_CHECK(!ch1.IsPolynucleotide());
    e.SetChainType(ch1, CHAINTYPE_POLY);
    BOOST_CHECK(ch1.GetType() == CHAINTYPE_POLY);
    BOOST_CHECK(ch1.IsPolymer());
    BOOST_CHECK(!ch1.IsPolysaccharide());
+   BOOST_CHECK(!ch1.IsOligosaccharide());
    BOOST_CHECK(!ch1.IsPolypeptide());
    BOOST_CHECK(!ch1.IsPolynucleotide());
    e.SetChainType(ch1, CHAINTYPE_NON_POLY);
    BOOST_CHECK(ch1.GetType() == CHAINTYPE_NON_POLY);
    BOOST_CHECK(!ch1.IsPolymer());
    BOOST_CHECK(!ch1.IsPolysaccharide());
+   BOOST_CHECK(!ch1.IsOligosaccharide());
    BOOST_CHECK(!ch1.IsPolypeptide());
    BOOST_CHECK(!ch1.IsPolynucleotide());
    e.SetChainType(ch1, CHAINTYPE_WATER);
    BOOST_CHECK(ch1.GetType() == CHAINTYPE_WATER);
    BOOST_CHECK(!ch1.IsPolymer());
    BOOST_CHECK(!ch1.IsPolysaccharide());
+   BOOST_CHECK(!ch1.IsOligosaccharide());
    BOOST_CHECK(!ch1.IsPolypeptide());
    BOOST_CHECK(!ch1.IsPolynucleotide());
    e.SetChainType(ch1, CHAINTYPE_POLY_PEPTIDE_D);
    BOOST_CHECK(ch1.IsPolymer());
    BOOST_CHECK(!ch1.IsPolysaccharide());
+   BOOST_CHECK(!ch1.IsOligosaccharide());
    BOOST_CHECK(ch1.IsPolypeptide());
    BOOST_CHECK(!ch1.IsPolynucleotide());
    BOOST_CHECK(ch1.GetType() == CHAINTYPE_POLY_PEPTIDE_D);
    e.SetChainType(ch1, CHAINTYPE_POLY_PEPTIDE_L);
    BOOST_CHECK(ch1.IsPolymer());
    BOOST_CHECK(!ch1.IsPolysaccharide());
+   BOOST_CHECK(!ch1.IsOligosaccharide());
    BOOST_CHECK(ch1.IsPolypeptide());
    BOOST_CHECK(!ch1.IsPolynucleotide());
    BOOST_CHECK(ch1.GetType() == CHAINTYPE_POLY_PEPTIDE_L);
    e.SetChainType(ch1, CHAINTYPE_POLY_DN);
    BOOST_CHECK(ch1.IsPolymer());
    BOOST_CHECK(!ch1.IsPolysaccharide());
+   BOOST_CHECK(!ch1.IsOligosaccharide());
    BOOST_CHECK(!ch1.IsPolypeptide());
    BOOST_CHECK(ch1.IsPolynucleotide());
    BOOST_CHECK(ch1.GetType() == CHAINTYPE_POLY_DN);
    e.SetChainType(ch1, CHAINTYPE_POLY_RN);
    BOOST_CHECK(ch1.IsPolymer());
    BOOST_CHECK(!ch1.IsPolysaccharide());
+   BOOST_CHECK(!ch1.IsOligosaccharide());
    BOOST_CHECK(!ch1.IsPolypeptide());
    BOOST_CHECK(ch1.IsPolynucleotide());
    BOOST_CHECK(ch1.GetType() == CHAINTYPE_POLY_RN);
    e.SetChainType(ch1, CHAINTYPE_POLY_SAC_D);
    BOOST_CHECK(ch1.IsPolymer());
    BOOST_CHECK(ch1.IsPolysaccharide());
+   BOOST_CHECK(!ch1.IsOligosaccharide());
    BOOST_CHECK(!ch1.IsPolypeptide());
    BOOST_CHECK(!ch1.IsPolynucleotide());
    BOOST_CHECK(ch1.GetType() == CHAINTYPE_POLY_SAC_D);
    e.SetChainType(ch1, CHAINTYPE_POLY_SAC_L);
    BOOST_CHECK(ch1.IsPolymer());
    BOOST_CHECK(ch1.IsPolysaccharide());
+   BOOST_CHECK(!ch1.IsOligosaccharide());
    BOOST_CHECK(!ch1.IsPolypeptide());
    BOOST_CHECK(!ch1.IsPolynucleotide());
    BOOST_CHECK(ch1.GetType() == CHAINTYPE_POLY_SAC_L);
@@ -295,6 +305,7 @@ BOOST_AUTO_TEST_CASE(chain_type)
    BOOST_CHECK(ch1.GetType() == CHAINTYPE_POLY_DN_RN);
    BOOST_CHECK(ch1.IsPolymer());
    BOOST_CHECK(!ch1.IsPolysaccharide());
+   BOOST_CHECK(!ch1.IsOligosaccharide());
    BOOST_CHECK(!ch1.IsPolypeptide());
    BOOST_CHECK(ch1.IsPolynucleotide());
    e.SetChainType(ch1, CHAINTYPE_N_CHAINTYPES);
@@ -305,30 +316,35 @@ BOOST_AUTO_TEST_CASE(chain_type)
    BOOST_CHECK(ch1.GetType() == CHAINTYPE_MACROLIDE);
    BOOST_CHECK(!ch1.IsPolymer());
    BOOST_CHECK(!ch1.IsPolysaccharide());
+   BOOST_CHECK(!ch1.IsOligosaccharide());
    BOOST_CHECK(!ch1.IsPolypeptide());
    BOOST_CHECK(!ch1.IsPolynucleotide());
    e.SetChainType(ch1, CHAINTYPE_CYCLIC_PSEUDO_PEPTIDE);
    BOOST_CHECK(ch1.GetType() == CHAINTYPE_CYCLIC_PSEUDO_PEPTIDE);
    BOOST_CHECK(ch1.IsPolymer());
    BOOST_CHECK(!ch1.IsPolysaccharide());
+   BOOST_CHECK(!ch1.IsOligosaccharide());
    BOOST_CHECK(ch1.IsPolypeptide());
    BOOST_CHECK(!ch1.IsPolynucleotide());
    e.SetChainType(ch1, CHAINTYPE_POLY_PEPTIDE_DN_RN);
    BOOST_CHECK(ch1.GetType() == CHAINTYPE_POLY_PEPTIDE_DN_RN);
    BOOST_CHECK(ch1.IsPolymer());
    BOOST_CHECK(!ch1.IsPolysaccharide());
+   BOOST_CHECK(!ch1.IsOligosaccharide());
    BOOST_CHECK(!ch1.IsPolypeptide());
    BOOST_CHECK(!ch1.IsPolynucleotide());
    e.SetChainType(ch1, CHAINTYPE_BRANCHED);
    BOOST_CHECK(ch1.GetType() == CHAINTYPE_BRANCHED);
-   BOOST_CHECK(!ch1.IsPolymer());
+   BOOST_CHECK(ch1.IsPolymer());
    BOOST_CHECK(!ch1.IsPolysaccharide());
+   BOOST_CHECK(!ch1.IsOligosaccharide());
    BOOST_CHECK(!ch1.IsPolypeptide());
    BOOST_CHECK(!ch1.IsPolynucleotide());
    e.SetChainType(ch1, CHAINTYPE_OLIGOSACCHARIDE);
    BOOST_CHECK(ch1.GetType() == CHAINTYPE_OLIGOSACCHARIDE);
    BOOST_CHECK(ch1.IsPolymer());
    BOOST_CHECK(!ch1.IsPolysaccharide());
+   BOOST_CHECK(ch1.IsOligosaccharide());
    BOOST_CHECK(!ch1.IsPolypeptide());
    BOOST_CHECK(!ch1.IsPolynucleotide());