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