diff --git a/modules/io/doc/mmcif.rst b/modules/io/doc/mmcif.rst
index a99538686572a7c8e934d392b835fd87b8ed2e00..d0b8ffba1f98e6cffb6ac1bf5a1106ae7bf99f87 100644
--- a/modules/io/doc/mmcif.rst
+++ b/modules/io/doc/mmcif.rst
@@ -28,6 +28,8 @@ The following categories of a mmCIF file are considered by the parser:
 * ``pdbx_struct_assembly``: Used for :class:`MMCifInfoBioUnit`.
 * ``pdbx_struct_assembly_gen``: Used for :class:`MMCifInfoBioUnit`.
 * ``pdbx_struct_oper_list``: Used for :class:`MMCifInfoBioUnit`.
+* ``struct``: Details about a structure, stored in
+  :class:`MMCifInfoStructDetails`.
 
 
 Info Classes
@@ -76,6 +78,13 @@ of the annotation available.
     Also available as :meth:`GetOperations`. May also be modified by
     :meth:`AddOperation`.
 
+  .. attribute:: struct_details
+
+    Stores details about the structure.
+
+    Also available as :meth:`GetStructDetails`. May also be modified by
+    :meth:`SetStructDetails`.
+
   .. method:: AddCitation(citation)
 
     Add a citation to the citation list of an info object.
@@ -131,6 +140,12 @@ of the annotation available.
 
     See :attr:`operations`
 
+  .. method:: SetStructDetails(details)
+
+    See :attr:`struct_details`
+
+  .. method:: GetStructDetails()
+
 .. class:: MMCifInfoCitation
 
   This stores citation information from an input file.
@@ -428,3 +443,129 @@ of the annotation available.
   .. method:: AddOperations(list of operations)
 
     See :attr:`operations`
+
+.. class:: MMCifInfoStructDetails
+
+  Holds details about the structure.
+
+  .. attribute:: entry_id
+
+    Identifier for a curtain data block. If not provided, resembles an empty
+    string.
+
+    Also available as :meth:`GetEntryID`. May also be modified by
+    :meth:`SetEntryID`.
+
+  .. attribute:: title
+
+    Set a title for the structure.
+
+    Also available as :meth:`GetTitle`. May also be modified by
+    :meth:`SetTitle`.
+
+  .. attribute:: casp_flag
+
+    Tells whether this structure was target in some competition.
+
+    Also available as :meth:`GetCASPFlag`. May also be modified by
+    :meth:`SetCASPFlag`.
+
+  .. attribute:: descriptor
+
+    Descriptor for an NDB structure or the unstructured content of a PDB COMPND
+    record.
+
+    Also available as :meth:`GetDescriptor`. May also be modified by
+    :meth:`SetDescriptor`.
+
+  .. attribute:: mass
+
+    Molecular mass of a molecule.
+
+    Also available as :meth:`GetMass`. May also be modified by
+    :meth:`SetMass`.
+
+  .. attribute:: mass_method
+
+    Method used to determine the molecular weight.
+
+    Also available as :meth:`GetMassMethod`. May also be modified by
+    :meth:`SetMassMethod`.
+
+  .. attribute:: model_details
+
+    Details about how the structure was determined.
+
+    Also available as :meth:`GetModelDetails`. May also be modified by
+    :meth:`SetModelDetails`.
+
+  .. attribute:: model_type_details
+
+    Details about how the type of the structure.
+
+    Also available as :meth:`GetModelTypeDetails`. May also be modified by
+    :meth:`SetModelTypeDetails`.
+
+  .. method:: GetEntryID()
+
+    See :attr:`entry_id`
+
+  .. method:: SetEntryID(id)
+
+    See :attr:`entry_id`
+
+  .. method:: GetTitle()
+
+    See :attr:`title`
+
+  .. method:: SetTitle(title)
+
+    See :attr:`title`
+
+  .. method:: GetCASPFlag()
+
+    See :attr:`casp_flag`
+
+  .. method:: SetCASPFlag(flag)
+
+    See :attr:`casp_flag`
+
+  .. method:: GetDescriptor()
+
+    See :attr:`descriptor`
+
+  .. method:: SetDescriptor(descriptor)
+
+    See :attr:`descriptor`
+
+  .. method:: GetMass()
+
+    See :attr:`mass`
+
+  .. method:: SetMass(mass)
+
+    See :attr:`mass`
+
+  .. method:: GetMassMethod()
+
+    See :attr:`mass_method`
+
+  .. method:: SetMassMethod(method)
+
+    See :attr:`mass_method`
+
+  .. method:: GetModelDetails()
+
+    See :attr:`model_details`
+
+  .. method:: SetModelDetails(details)
+
+    See :attr:`model_details`
+
+  .. method:: GetModelTypeDetails()
+
+    See :attr:`model_type_details`
+
+  .. method:: SetModelTypeDetails(details)
+
+    See :attr:`model_type_details`
diff --git a/modules/io/pymod/export_mmcif_io.cc b/modules/io/pymod/export_mmcif_io.cc
index 6da2ac02afaf8bb56ead9adac83e3360a23a2238..9034c8c16fe7d8c785e5579665b9afcac1ed0a04 100644
--- a/modules/io/pymod/export_mmcif_io.cc
+++ b/modules/io/pymod/export_mmcif_io.cc
@@ -161,6 +161,42 @@ void export_mmcif_io()
     .def(vector_indexing_suite<std::vector<MMCifInfoBioUnit> >())
   ;
 
+  class_<MMCifInfoStructDetails>("MMCifInfoStructDetails", init<>())
+    .def("SetEntryID", &MMCifInfoStructDetails::SetEntryID)
+    .def("GetEntryID", &MMCifInfoStructDetails::GetEntryID)
+    .def("SetTitle", &MMCifInfoStructDetails::SetTitle)
+    .def("GetTitle", &MMCifInfoStructDetails::GetTitle)
+    .def("SetCASPFlag", &MMCifInfoStructDetails::SetCASPFlag)
+    .def("GetCASPFlag", &MMCifInfoStructDetails::GetCASPFlag)
+    .def("SetDescriptor", &MMCifInfoStructDetails::SetDescriptor)
+    .def("GetDescriptor", &MMCifInfoStructDetails::GetDescriptor)
+    .def("SetMass", &MMCifInfoStructDetails::SetMass)
+    .def("GetMass", &MMCifInfoStructDetails::GetMass)
+    .def("SetMassMethod", &MMCifInfoStructDetails::SetMassMethod)
+    .def("GetMassMethod", &MMCifInfoStructDetails::GetMassMethod)
+    .def("SetModelDetails", &MMCifInfoStructDetails::SetModelDetails)
+    .def("GetModelDetails", &MMCifInfoStructDetails::GetModelDetails)
+    .def("SetModelTypeDetails", &MMCifInfoStructDetails::SetModelTypeDetails)
+    .def("GetModelTypeDetails", &MMCifInfoStructDetails::GetModelTypeDetails)
+    .add_property("entry_id", &MMCifInfoStructDetails::GetEntryID,
+                  &MMCifInfoStructDetails::SetEntryID)
+    .add_property("title", &MMCifInfoStructDetails::GetTitle,
+                  &MMCifInfoStructDetails::SetTitle)
+    .add_property("casp_flag", &MMCifInfoStructDetails::GetCASPFlag,
+                  &MMCifInfoStructDetails::SetCASPFlag)
+    .add_property("descriptor", &MMCifInfoStructDetails::GetDescriptor,
+                  &MMCifInfoStructDetails::SetDescriptor)
+    .add_property("mass", &MMCifInfoStructDetails::GetMass,
+                  &MMCifInfoStructDetails::SetMass)
+    .add_property("mass_method", &MMCifInfoStructDetails::GetMassMethod,
+                  &MMCifInfoStructDetails::SetMassMethod)
+    .add_property("model_details", &MMCifInfoStructDetails::GetModelDetails,
+                  &MMCifInfoStructDetails::SetModelDetails)
+    .add_property("model_type_details",
+                  &MMCifInfoStructDetails::GetModelTypeDetails,
+                  &MMCifInfoStructDetails::SetModelTypeDetails)
+;
+
   class_<MMCifInfo>("MMCifInfo", init<>())
     .def("AddCitation", &MMCifInfo::AddCitation)
     .def("GetCitations", make_function(&MMCifInfo::GetCitations,
@@ -176,6 +212,8 @@ void export_mmcif_io()
     .def("AddOperation", &MMCifInfo::AddOperation)
     .def("GetOperations", make_function(&MMCifInfo::GetOperations,
                                    return_value_policy<copy_const_reference>()))
+    .def("SetStructDetails", &MMCifInfo::SetStructDetails)
+    .def("GetStructDetails", &MMCifInfo::GetStructDetails)
     .add_property("citations", make_function(&MMCifInfo::GetCitations,
                                    return_value_policy<copy_const_reference>()))
     .add_property("biounits", make_function(&MMCifInfo::GetBioUnits,
@@ -185,5 +223,7 @@ void export_mmcif_io()
                   &MMCifInfo::SetResolution)
     .add_property("operations", make_function(&MMCifInfo::GetOperations,
                                    return_value_policy<copy_const_reference>()))
+    .add_property("struct_details", &MMCifInfo::GetStructDetails,
+                  &MMCifInfo::SetStructDetails)
   ;
 }
diff --git a/modules/io/src/mol/mmcif_info.hh b/modules/io/src/mol/mmcif_info.hh
index b8b0aba50c34d60dff7607874322580c70c4c75a..3e9400194f8c65e735bf5207330a5807b1fd0b12 100644
--- a/modules/io/src/mol/mmcif_info.hh
+++ b/modules/io/src/mol/mmcif_info.hh
@@ -27,6 +27,129 @@
 
 namespace ost { namespace io {
 
+class DLLEXPORT_OST_IO MMCifInfoStructDetails {
+public:
+  /// \brief Create a details object.
+  MMCifInfoStructDetails(): entry_id_(""), title_(""), casp_flag_('\0'),
+    descriptor_(""), mass_(0.0), mass_method_(""), model_details_(""),
+    model_type_details_("") {};
+
+  /// \brief Set id.
+  ///
+  /// \param id id
+  void SetEntryID(String id) { entry_id_ = id; }
+  /// \brief Get id.
+  ///
+  /// \return id
+  String GetEntryID() const { return entry_id_; }
+
+  /// \brief Set CASP flag.
+  ///
+  /// \param flag flag
+  void SetCASPFlag(char flag) { casp_flag_ = flag; }
+  /// \brief Get CASP flag.
+  ///
+  /// \return flag
+  char GetCASPFlag() const { return casp_flag_; }
+
+  /// \brief Set descriptor.
+  ///
+  /// \param desc descriptor for an NDB structure or PDB COMPND record
+  void SetDescriptor(String desc) { descriptor_ = desc; }
+  /// \brief Get CASP flag.
+  ///
+  /// \return flag
+  String GetDescriptor() const { return descriptor_; }
+
+  /// \brief Set mass.
+  ///
+  /// \param mass molecular mass
+  void SetMass(Real mass) { mass_ = mass; }
+  /// \brief Get molecular weight.
+  ///
+  /// \return mass
+  Real GetMass() const { return mass_; }
+
+  /// \brief Set the method how the molecular weight was detected.
+  ///
+  /// \param method detection method
+  void SetMassMethod(String method) { mass_method_ = method; }
+  /// \brief Get the method how the molecular weight was determined.
+  ///
+  /// \return method
+  String GetMassMethod() const { return mass_method_; }
+
+  /// \brief Set the description about the production of this structure.
+  ///
+  /// \param desc explaination
+  void SetModelDetails(String desc) { model_details_ = desc; }
+  /// \brief Get the details how the structure was determined.
+  ///
+  /// \return details
+  String GetModelDetails() const { return model_details_; }
+
+  /// \brief Set a description for the type of the structure model.
+  ///
+  /// \param desc explaination
+  void SetModelTypeDetails(String desc) { model_type_details_ = desc; }
+  /// \brief Get the description for the type of the structure model.
+  ///
+  /// \return details
+  String GetModelTypeDetails() const { return model_type_details_; }
+
+  /// \brief Set a title for the data block.
+  ///
+  /// \param title title
+  void SetTitle(String title) { title_ = title; }
+  /// \brief Get the title of the structure model.
+  ///
+  /// \return title
+  String GetTitle() const { return title_; }
+
+  bool operator==(const MMCifInfoStructDetails& sd) const {
+    if (this->entry_id_ != sd.entry_id_) {
+      return false;
+    }
+    if (this->casp_flag_ != sd.casp_flag_) {
+      return false;
+    }
+    if (this->descriptor_ != sd.descriptor_) {
+      return false;
+    }
+    if (this->mass_ != sd.mass_) {
+      return false;
+    }
+    if (this->mass_method_ != sd.mass_method_) {
+      return false;
+    }
+    if (this->model_details_ != sd.model_details_) {
+      return false;
+    }
+    if (this->model_type_details_ != sd.model_type_details_) {
+      return false;
+    }
+    if (this->title_ != sd.title_) {
+      return false;
+    }
+
+    return true;
+  }
+
+  bool operator!=(const MMCifInfoStructDetails& sd) const {
+    return !this->operator == (sd);
+  }
+
+private:
+  String entry_id_;
+  String title_;
+  char   casp_flag_;
+  String descriptor_;
+  Real   mass_;
+  String mass_method_;
+  String model_details_;
+  String model_type_details_;
+};
+
 class DLLEXPORT_OST_IO MMCifInfoTransOp {
 public:
   /// \brief Create an operation
@@ -156,6 +279,31 @@ public:
     if (this->chains_ != bu.chains_) {
       return false;
     }
+    if (this->operations_.size() == bu.operations_.size()) {
+      std::vector<std::vector<MMCifInfoTransOpPtr> >::const_iterator th_ops_it;
+      std::vector<std::vector<MMCifInfoTransOpPtr> >::const_iterator bu_ops_it;
+      std::vector<MMCifInfoTransOpPtr>::const_iterator th_op_it;
+      std::vector<MMCifInfoTransOpPtr>::const_iterator bu_op_it;
+
+      for (th_ops_it = this->operations_.begin(),
+             bu_ops_it = bu.operations_.begin();
+           th_ops_it != this->operations_.end();
+           ++th_ops_it, ++bu_ops_it) {
+        if (th_ops_it->size() == bu_ops_it->size()) {
+          for (th_op_it = th_ops_it->begin(), bu_op_it = bu_ops_it->begin();
+               th_op_it != th_ops_it->end();
+               ++th_op_it, ++bu_op_it) {
+            if (*th_op_it != *bu_op_it) {
+              return false;
+            }
+          }
+        } else {
+          return false;
+        }
+      }
+    } else {
+      return false;
+    }
 
     return true;
   }
@@ -468,12 +616,29 @@ public:
     return transops_;
   }
 
+  /// \brief Add a set of structure details
+  ///
+  /// \param details info block to be added
+  void SetStructDetails(MMCifInfoStructDetails details)
+  {
+    struct_details_ = details;
+  }
+
+  /// \brief Get the list of details about structures.
+  ///
+  /// \return vector of MMCifInfoStructDetails objects
+  const MMCifInfoStructDetails GetStructDetails() const
+  {
+    return struct_details_;
+  }
+
 //protected:
 
 private:
   // members
   String exptl_method_;
   Real resolution_;
+  MMCifInfoStructDetails struct_details_;     ///< mmCIF struct category
   std::vector<MMCifInfoCitation> citations_;  ///< list of citations
   std::vector<MMCifInfoBioUnit>  biounits_;   ///< list of biounits
   std::vector<MMCifInfoTransOpPtr> transops_;
diff --git a/modules/io/src/mol/mmcif_reader.cc b/modules/io/src/mol/mmcif_reader.cc
index 45275c6b09244de827918083990f05fa000087c2..213187e258882f3e30a37003b6e295e2cd4fdf46 100644
--- a/modules/io/src/mol/mmcif_reader.cc
+++ b/modules/io/src/mol/mmcif_reader.cc
@@ -245,6 +245,21 @@ bool MMCifParser::OnBeginLoop(const StarLoopDesc& header)
     indices_[MATRIX_3_2] = header.GetIndex("matrix[3][2]");
     indices_[MATRIX_3_3] = header.GetIndex("matrix[3][3]");
     cat_available = true;
+  } else if (header.GetCategory() == "struct") {
+    category_ = STRUCT;
+    // mandatory items
+    this->TryStoreIdx(STRUCT_ENTRY_ID, "entry_id", header);
+    // optional items
+    indices_[PDBX_CASP_FLAG]             = header.GetIndex("pdbx_CASP_flag");
+    indices_[PDBX_DESCRIPTOR]            = header.GetIndex("pdbx_descriptor");
+    indices_[PDBX_FORMULA_WEIGHT]      = header.GetIndex("pdbx_formula_weight");
+    indices_[PDBX_FORMULA_WEIGHT_METHOD]
+       = header.GetIndex("pdbx_formula_weight_method");
+    indices_[PDBX_MODEL_DETAILS]        = header.GetIndex("pdbx_model_details");
+    indices_[PDBX_MODEL_TYPE_DETAILS]
+       = header.GetIndex("pdbx_model_type_details");
+    indices_[STRUCT_TITLE]               = header.GetIndex("title");
+    cat_available = true;
   }
   category_counts_[category_]++;
   return cat_available;
@@ -946,6 +961,48 @@ void MMCifParser::ParsePdbxStructOperList(const std::vector<StringRef>& columns)
   info_.AddOperation(op);
 }
 
+void MMCifParser::ParseStruct(const std::vector<StringRef>& columns)
+{
+  MMCifInfoStructDetails details = MMCifInfoStructDetails();
+
+  details.SetEntryID(columns[indices_[STRUCT_ENTRY_ID]].str());
+
+  if (indices_[STRUCT_TITLE] != -1) {
+    details.SetTitle(columns[indices_[STRUCT_TITLE]].str());
+  }
+
+  if ((indices_[PDBX_CASP_FLAG] != -1) &&
+      (columns[indices_[PDBX_CASP_FLAG]][0] != '?')) {
+    details.SetCASPFlag(columns[indices_[PDBX_CASP_FLAG]][0]);
+  }
+
+  if (indices_[PDBX_DESCRIPTOR] != -1) {
+    details.SetDescriptor(columns[indices_[PDBX_DESCRIPTOR]].str());
+  }
+
+  if (indices_[PDBX_FORMULA_WEIGHT] != -1) {
+    details.SetMass(this->TryGetReal(columns[indices_[PDBX_FORMULA_WEIGHT]],
+                                     "struct.pdbx_formula_weight"));
+  }
+
+  if (indices_[PDBX_FORMULA_WEIGHT_METHOD] != -1) {
+    details.SetMassMethod(columns[indices_[PDBX_FORMULA_WEIGHT_METHOD]].str());
+  }
+
+  if ((indices_[PDBX_MODEL_DETAILS] != -1) &&
+      (columns[indices_[PDBX_MODEL_DETAILS]][0] != '?')) {
+    details.SetModelDetails(columns[indices_[PDBX_MODEL_DETAILS]].str());
+  }
+
+  if ((indices_[PDBX_MODEL_TYPE_DETAILS] != -1) &&
+      (columns[indices_[PDBX_MODEL_TYPE_DETAILS]][0] != '?')) {
+    details.SetModelTypeDetails(
+                              columns[indices_[PDBX_MODEL_TYPE_DETAILS]].str());
+  }
+
+  info_.SetStructDetails(details);
+}
+
 void MMCifParser::OnDataRow(const StarLoopDesc& header, 
                             const std::vector<StringRef>& columns)
 {
@@ -990,6 +1047,10 @@ void MMCifParser::OnDataRow(const StarLoopDesc& header,
     LOG_TRACE("processing pdbx_struct_oper_list entry")
     this->ParsePdbxStructOperList(columns);
     break;
+  case STRUCT:
+    LOG_TRACE("processing struct entry")
+    this->ParseStruct(columns);
+    break;
   default:
     throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR,
                        "Uncatched category '"+ header.GetCategory() +"' found.",
diff --git a/modules/io/src/mol/mmcif_reader.hh b/modules/io/src/mol/mmcif_reader.hh
index 568350bbaf71e102286d2afe186a929873404438..740a93132c2dfa8ec4aee0d795ee0d875cb1a777 100644
--- a/modules/io/src/mol/mmcif_reader.hh
+++ b/modules/io/src/mol/mmcif_reader.hh
@@ -51,6 +51,7 @@ namespace ost { namespace io {
 /// \li pdbx_struct_assembly
 /// \li pdbx_struct_assembly_gen
 /// \li pdbx_struct_oper_list
+/// \li struct
 class DLLEXPORT_OST_IO MMCifParser : public StarParser  {
 public:
   /// \brief create a MMCifParser
@@ -264,6 +265,10 @@ protected:
   /// \param columns data row
   void ParsePdbxStructOperList(const std::vector<StringRef>& columns);
 
+  /// \brief Fetch MMCif struct information
+  ///
+  /// \param columns data row
+  void ParseStruct(const std::vector<StringRef>& columns);
 
 private:
   /// \enum magic numbers of this class
@@ -377,6 +382,18 @@ private:
     MATRIX_3_3  ///< matrix component
   } PdbxStructOperListItems;
 
+  /// \enum items of the struct category
+  typedef enum {
+     STRUCT_ENTRY_ID,     ///< name of the structure
+     PDBX_CASP_FLAG,      ///< CASP/ CASD-NMR/ other contest target
+     PDBX_DESCRIPTOR,     ///< descriptor for NDB structure/ PDB COMPND record
+     PDBX_FORMULA_WEIGHT, ///< mass in daltons
+     PDBX_FORMULA_WEIGHT_METHOD, ///< how mass was determined
+     PDBX_MODEL_DETAILS,  ///< methodology
+     PDBX_MODEL_TYPE_DETAILS, ///< type of structure model
+     STRUCT_TITLE         ///< title for the data block
+  } StructItems;
+
   /// \enum categories of the mmcif format
   typedef enum {
     ATOM_SITE,
@@ -389,6 +406,7 @@ private:
     PDBX_STRUCT_ASSEMBLY,
     PDBX_STRUCT_ASSEMBLY_GEN,
     PDBX_STRUCT_OPER_LIST,
+    STRUCT,
     DONT_KNOW
   } MMCifCategory;
 
diff --git a/modules/io/tests/test_io_mmcif.py b/modules/io/tests/test_io_mmcif.py
index d6d669aa96b5cb5e0f2ab784685b40f8a25bc36d..64caccbe1d6ee51b9faa2e7583a8740d188b70d3 100644
--- a/modules/io/tests/test_io_mmcif.py
+++ b/modules/io/tests/test_io_mmcif.py
@@ -103,6 +103,38 @@ class TestMMCifInfo(unittest.TestCase):
     oll = b.GetOperations()
     self.assertEquals(oll[0][0].GetID(), '1')
 
+  def test_mmcifinfo_structdetails(self):
+    d = io.MMCifInfoStructDetails()
+
+    d.SetEntryID('1BAR')
+    d.SetTitle('A Title')
+    d.SetCASPFlag('N')
+    d.SetDescriptor('FooBar')
+    d.SetMass(1.0)
+    d.SetMassMethod('Good Guess')
+    d.SetModelDetails('Created with SwissModel')
+    d.SetModelTypeDetails('Average')
+    self.assertEquals(d.GetEntryID(), '1BAR')
+    self.assertEquals(d.GetTitle(), 'A Title')
+    self.assertEquals(d.GetCASPFlag(), 'N')
+    self.assertEquals(d.GetDescriptor(), 'FooBar')
+    self.assertEquals(d.GetMass(), 1.0)
+    self.assertEquals(d.GetMassMethod(), 'Good Guess')
+    self.assertEquals(d.GetModelDetails(), 'Created with SwissModel')  
+    self.assertEquals(d.GetModelTypeDetails(), 'Average') 
+
+    i = io.MMCifInfo()
+    i.SetStructDetails(d)
+    self.assertEquals(i.GetStructDetails().GetEntryID(), '1BAR')
+    self.assertEquals(i.GetStructDetails().GetTitle(), 'A Title')
+    self.assertEquals(i.GetStructDetails().GetCASPFlag(), 'N')
+    self.assertEquals(i.GetStructDetails().GetDescriptor(), 'FooBar')
+    self.assertEquals(i.GetStructDetails().GetMass(), 1.0)
+    self.assertEquals(i.GetStructDetails().GetMassMethod(), 'Good Guess')
+    self.assertEquals(i.GetStructDetails().GetModelDetails(),
+                      'Created with SwissModel')
+    self.assertEquals(i.GetStructDetails().GetModelTypeDetails(), 'Average')
+
 if __name__== '__main__':
     unittest.main()
 
diff --git a/modules/io/tests/test_mmcif_info.cc b/modules/io/tests/test_mmcif_info.cc
index 238b71cdc95c7264ecf4c4642da746ec7e75c49b..2c0b7b3e9e3bd38db83c6c92a321fedef3fa1df2 100644
--- a/modules/io/tests/test_mmcif_info.cc
+++ b/modules/io/tests/test_mmcif_info.cc
@@ -129,6 +129,37 @@ BOOST_AUTO_TEST_CASE(mmcif_info_transoperation)
   BOOST_MESSAGE("  done.");
 }
 
+BOOST_AUTO_TEST_CASE(mmcif_info_structdetails)
+{
+  BOOST_MESSAGE("  Running mmcif_info_structdetails tests...");
+
+  MMCifInfoStructDetails sd = MMCifInfoStructDetails();
+
+  sd.SetEntryID("1BAR");
+  sd.SetTitle("More than a structure");
+  sd.SetCASPFlag('Y');
+  sd.SetDescriptor("ADENYLATE KINASE");
+  sd.SetMass(1.0);
+  sd.SetMassMethod("Good Guess");
+  sd.SetModelDetails("Even more guessing");
+  sd.SetModelTypeDetails("MINIMIZED AVERAGE");
+
+  BOOST_CHECK(sd.GetEntryID() == "1BAR");
+  BOOST_CHECK(sd.GetTitle() == "More than a structure");
+  BOOST_CHECK(sd.GetCASPFlag() == 'Y');
+  BOOST_CHECK(sd.GetDescriptor() == "ADENYLATE KINASE");
+  BOOST_CHECK_CLOSE(sd.GetMass(), 1.0f, 0.001f);
+  BOOST_CHECK(sd.GetMassMethod() == "Good Guess");
+  BOOST_CHECK(sd.GetModelDetails() == "Even more guessing");
+  BOOST_CHECK(sd.GetModelTypeDetails() == "MINIMIZED AVERAGE");
+
+  MMCifInfo info = MMCifInfo();
+  info.SetStructDetails(sd);
+  BOOST_CHECK(info.GetStructDetails() == sd);
+
+  BOOST_MESSAGE("  done.");
+}
+
 BOOST_AUTO_TEST_CASE(mmcif_info)
 {
   BOOST_MESSAGE("  Running mmcif_info tests...");
diff --git a/modules/io/tests/test_mmcif_reader.cc b/modules/io/tests/test_mmcif_reader.cc
index 6ae040448b1d63f0ac4d91a15a2965cde816a420..14adae17dbf60ffe24a5fa92a7a9595ceb965489 100644
--- a/modules/io/tests/test_mmcif_reader.cc
+++ b/modules/io/tests/test_mmcif_reader.cc
@@ -59,11 +59,13 @@ public:
   using MMCifParser::ParsePdbxStructAssemblyGen;
   using MMCifParser::ParsePdbxStructAssembly;
   using MMCifParser::ParsePdbxStructOperList;
+  using MMCifParser::ParseStruct;
   using MMCifParser::TryStoreIdx;
   using MMCifParser::SetReadSeqRes;
   using MMCifParser::SetReadCanonicalSeqRes;
   using MMCifParser::ClearState;
   using MMCifParser::ConvertSEQRES;
+  using MMCifParser::GetInfo;
 };
 
 BOOST_AUTO_TEST_SUITE( io );
@@ -729,6 +731,44 @@ BOOST_AUTO_TEST_CASE(mmcif_biounit_tests)
   BOOST_MESSAGE("  done.");
 }
 
+BOOST_AUTO_TEST_CASE(mmcif_struct_tests)
+{
+  BOOST_MESSAGE("  Running mmcif_struct_tests...");
+
+  mol::EntityHandle eh = mol::CreateEntity();
+  TestMMCifParserProtected tmmcif_p("testfiles/mmcif/atom_site.mmcif", eh);
+  StarLoopDesc tmmcif_h;
+  std::vector<StringRef> columns;
+
+  tmmcif_h.SetCategory(StringRef("struct", 6));
+  tmmcif_h.Add(StringRef("entry_id", 8));
+  tmmcif_h.Add(StringRef("pdbx_CASP_flag", 14));
+  tmmcif_h.Add(StringRef("pdbx_model_details", 18));
+  tmmcif_h.Add(StringRef("pdbx_model_type_details", 23));
+  tmmcif_h.Add(StringRef("pdbx_formula_weight", 19));
+  tmmcif_p.OnBeginLoop(tmmcif_h);
+
+  columns.push_back(StringRef("1BAR", 4));
+  columns.push_back(StringRef("?", 1));
+  columns.push_back(StringRef("?", 1));
+  columns.push_back(StringRef("?", 1));
+  columns.push_back(StringRef("1.0", 3));
+  BOOST_CHECK_NO_THROW(tmmcif_p.ParseStruct(columns));
+
+  MMCifInfoStructDetails sd = MMCifInfoStructDetails();
+  sd = tmmcif_p.GetInfo().GetStructDetails();
+
+  BOOST_CHECK(sd.GetCASPFlag() == '\0');
+  BOOST_CHECK(sd.GetModelDetails() == "");
+  BOOST_CHECK(sd.GetModelTypeDetails() == "");
+
+  columns.pop_back();
+  columns.push_back(StringRef("A", 1));
+  BOOST_CHECK_THROW(tmmcif_p.ParseStruct(columns), IOException);
+
+  BOOST_MESSAGE("  done.");
+}
+
 BOOST_AUTO_TEST_CASE(mmcif_parseatomident)
 {
   BOOST_MESSAGE("  Running mmcif_parseatomident tests...");
@@ -835,6 +875,15 @@ BOOST_AUTO_TEST_CASE(mmcif_testreader)
   MMCifInfoBioUnit bu = mmcif_p.GetInfo().GetBioUnits().back();
   BOOST_CHECK(bu.GetOperations().back().back()->GetType() ==
               "identity operation");
+  MMCifInfoStructDetails sd = mmcif_p.GetInfo().GetStructDetails();
+  BOOST_CHECK(sd.GetEntryID() == "1BAR");
+  BOOST_CHECK(sd.GetTitle() == "A Title");
+  BOOST_CHECK(sd.GetCASPFlag() == 'Y');
+  BOOST_CHECK(sd.GetDescriptor() == "ADENYLATE KINASE");
+  BOOST_CHECK_CLOSE(sd.GetMass(), 1.0f, 0.001f);
+  BOOST_CHECK(sd.GetMassMethod() == "Good Guess");
+  BOOST_CHECK(sd.GetModelDetails() == "Even better guessing");
+  BOOST_CHECK(sd.GetModelTypeDetails() == "Guess");
   BOOST_MESSAGE("          done.");
 
   BOOST_MESSAGE("  done.");
diff --git a/modules/io/tests/testfiles/mmcif/atom_site.mmcif b/modules/io/tests/testfiles/mmcif/atom_site.mmcif
index b10009871d934a8ece41ad4e2c1fcc1a07ed661e..cf3b4c75192b01316625877d21852c2b7dc5e968 100644
--- a/modules/io/tests/testfiles/mmcif/atom_site.mmcif
+++ b/modules/io/tests/testfiles/mmcif/atom_site.mmcif
@@ -85,6 +85,15 @@ _pdbx_struct_oper_list.matrix[3][3]         1.0000000000
 _pdbx_struct_oper_list.vector[3]            23.3000000000 
 # biounit end
 
+_struct.entry_id                   1BAR
+_struct.title                      'A Title'
+_struct.pdbx_CASP_flag             Y
+_struct.pdbx_descriptor            'ADENYLATE KINASE'
+_struct.pdbx_formula_weight        1.0
+_struct.pdbx_formula_weight_method 'Good Guess'
+_struct.pdbx_model_details         'Even better guessing'
+_struct.pdbx_model_type_details    'Guess'
+
 loop_
 _atom_site.group_PDB
 _atom_site.type_symbol