diff --git a/modules/io/doc/mmcif.rst b/modules/io/doc/mmcif.rst index 78e126def7cf2b67171435e5c2f9efe49ee43de2..bed692ff4bc7e137e71c0ee1a8e18dfe8a0d9419 100644 --- a/modules/io/doc/mmcif.rst +++ b/modules/io/doc/mmcif.rst @@ -25,7 +25,8 @@ The following categories of a mmCIF file are considered by the reader: * ``citation``: Goes into :class:`MMCifInfoCitation` * ``citation_author``: Goes into :class:`MMCifInfoCitation` * ``exptl``: Goes into :class:`MMCifInfo` as :attr:`~MMCifInfo.method`. -* ``refine``: Goes into :class:`MMCifInfo` as :attr:`~MMCifInfo.resolution`. +* ``refine``: Goes into :class:`MMCifInfo` as :attr:`~MMCifInfo.resolution`, + :attr:`~MMCifInfo.r_free` and :attr:`~MMCifInfo.r_work`. * ``pdbx_struct_assembly``: Used for :class:`MMCifInfoBioUnit`. * ``pdbx_struct_assembly_gen``: Used for :class:`MMCifInfoBioUnit`. * ``pdbx_struct_oper_list``: Used for :class:`MMCifInfoBioUnit`. @@ -93,11 +94,28 @@ of the annotation available. .. attribute:: resolution - Stores the resolution of the crystal structure. + Stores the resolution of the crystal structure. Set to 0 if no value in + loaded mmCIF file. Also available as :meth:`GetResolution`. May also be modified by :meth:`SetResolution`. + .. attribute:: r_free + + Stores the R-free value of the crystal structure. Set to 0 if no value in + loaded mmCIF file. + + Also available as :meth:`GetRFree`. May also be modified by + :meth:`SetRFree`. + + .. attribute:: r_work + + Stores the R-work value of the crystal structure. Set to 0 if no value in + loaded mmCIF file. + + Also available as :meth:`GetRWork`. May also be modified by + :meth:`SetRWork`. + .. attribute:: operations Stores the operations needed to transform a crystal structure into a diff --git a/modules/io/pymod/export_mmcif_io.cc b/modules/io/pymod/export_mmcif_io.cc index 447761e76bebe047f6fb1fdc674ca8f2cd6d38fa..dd90843e39fa7a32ed661975b208ea6325e7f7db 100644 --- a/modules/io/pymod/export_mmcif_io.cc +++ b/modules/io/pymod/export_mmcif_io.cc @@ -310,6 +310,10 @@ void export_mmcif_io() .def("GetMethod", &MMCifInfo::GetMethod) .def("SetResolution", &MMCifInfo::SetResolution) .def("GetResolution", &MMCifInfo::GetResolution) + .def("SetRFree", &MMCifInfo::SetRFree) + .def("GetRFree", &MMCifInfo::GetRFree) + .def("SetRWork", &MMCifInfo::SetRWork) + .def("GetRWork", &MMCifInfo::GetRWork) .def("AddAuthorsToCitation", &MMCifInfo::AddAuthorsToCitation) .def("AddOperation", &MMCifInfo::AddOperation) .def("GetOperations", make_function(&MMCifInfo::GetOperations, @@ -334,6 +338,8 @@ void export_mmcif_io() .add_property("method", &MMCifInfo::GetMethod, &MMCifInfo::SetMethod) .add_property("resolution", &MMCifInfo::GetResolution, &MMCifInfo::SetResolution) + .add_property("r_free", &MMCifInfo::GetRFree, &MMCifInfo::SetRFree) + .add_property("r_work", &MMCifInfo::GetRWork, &MMCifInfo::SetRWork) .add_property("operations", make_function(&MMCifInfo::GetOperations, return_value_policy<copy_const_reference>())) .add_property("struct_details", &MMCifInfo::GetStructDetails, diff --git a/modules/io/src/mol/mmcif_info.hh b/modules/io/src/mol/mmcif_info.hh index 49cd8e16c9901a6d2132ca91c2b7d66f7e11f19d..0a00a838258de949f47c1796a9c70c93b284ef1e 100644 --- a/modules/io/src/mol/mmcif_info.hh +++ b/modules/io/src/mol/mmcif_info.hh @@ -869,7 +869,7 @@ private: class DLLEXPORT_OST_IO MMCifInfo { public: /// \brief Create an info object. - MMCifInfo(): exptl_method_(""), resolution_(0.0f) {}; + MMCifInfo(): exptl_method_(""), resolution_(0), r_free_(0), r_work_(0) { } /// \brief Add an item to the list of citations /// @@ -916,6 +916,26 @@ public: /// \return experiment resolution Real GetResolution() const { return resolution_; } + /// \brief Set R-free value. + /// + /// \param res experiment R-free value + void SetRFree(Real r_free) { r_free_ = r_free; } + + /// \brief Get R-free value. + /// + /// \return experiment R-free value + Real GetRFree() const { return r_free_; } + + /// \brief Set R-work value. + /// + /// \param r_work experiment R-work value + void SetRWork(Real r_work) { r_work_ = r_work; } + + /// \brief Get R-work value. + /// + /// \return experiment R-work value + Real GetRWork() const { return r_work_; } + /// \brief Add a new mmCIF/ PDB chain name tuple. /// /// \param cif chain name as used by the mmCIF file (label_asym_id) @@ -1049,6 +1069,8 @@ private: // members String exptl_method_; Real resolution_; + Real r_free_; + Real r_work_; MMCifInfoStructDetails struct_details_; ///< mmCIF struct category MMCifInfoObsolete obsolete_; ///< obsolete/ superseded entry MMCifInfoRevisions revisions_; ///< list of revisions diff --git a/modules/io/src/mol/mmcif_reader.cc b/modules/io/src/mol/mmcif_reader.cc index abd02fe6e153746cc2df08c56cfdb60c698e8880..1c971ee2fa6ee08101d9303cd09e7bda21c1a9bc 100644 --- a/modules/io/src/mol/mmcif_reader.cc +++ b/modules/io/src/mol/mmcif_reader.cc @@ -219,9 +219,12 @@ bool MMCifReader::OnBeginLoop(const StarLoopDesc& header) } else if (header.GetCategory() == "refine") { category_ = REFINE; // mandatory items - this->TryStoreIdx(REFINE_ENTRY_ID, "entry_id", header); - this->TryStoreIdx(LS_D_RES_HIGH, "ls_d_res_high", header); - this->TryStoreIdx(LS_D_RES_LOW, "ls_d_res_low", header); + this->TryStoreIdx(LS_D_RES_HIGH, "ls_d_res_high", header); + // optional items + indices_[REFINE_ENTRY_ID] = header.GetIndex("entry_id"); + indices_[LS_D_RES_LOW] = header.GetIndex("ls_d_res_low"); + indices_[LS_R_FACTOR_R_WORK] = header.GetIndex("ls_R_factor_R_work"); + indices_[LS_R_FACTOR_R_FREE] = header.GetIndex("ls_R_factor_R_free"); cat_available = true; } else if (header.GetCategory() == "pdbx_struct_assembly") { category_ = PDBX_STRUCT_ASSEMBLY; @@ -909,10 +912,21 @@ void MMCifReader::ParseExptl(const std::vector<StringRef>& columns) void MMCifReader::ParseRefine(const std::vector<StringRef>& columns) { - StringRef col=columns[indices_[LS_D_RES_HIGH]]; + StringRef col = columns[indices_[LS_D_RES_HIGH]]; if (col.size()!=1 || (col[0]!='?' && col[0]!='.')) { - info_.SetResolution(this->TryGetReal(columns[indices_[LS_D_RES_HIGH]], - "refine.ls_d_res_high")); + info_.SetResolution(this->TryGetReal(col, "refine.ls_d_res_high")); + } + if (indices_[LS_R_FACTOR_R_WORK] != -1) { + col = columns[indices_[LS_R_FACTOR_R_WORK]]; + if (col.size()!=1 || (col[0]!='?' && col[0]!='.')) { + info_.SetRWork(this->TryGetReal(col, "refine.ls_R_factor_R_work")); + } + } + if (indices_[LS_R_FACTOR_R_FREE] != -1) { + col = columns[indices_[LS_R_FACTOR_R_FREE]]; + if (col.size()!=1 || (col[0]!='?' && col[0]!='.')) { + info_.SetRFree(this->TryGetReal(col, "refine.ls_R_factor_R_free")); + } } } diff --git a/modules/io/src/mol/mmcif_reader.hh b/modules/io/src/mol/mmcif_reader.hh index 55a195652092481182c644dd3f936e7b3593b2bc..3503223eb5e543088b93b44749cdd2edd508c494 100644 --- a/modules/io/src/mol/mmcif_reader.hh +++ b/modules/io/src/mol/mmcif_reader.hh @@ -427,7 +427,9 @@ private: typedef enum { REFINE_ENTRY_ID, ///< id LS_D_RES_HIGH, ///< crystal resolution - LS_D_RES_LOW + LS_D_RES_LOW, + LS_R_FACTOR_R_WORK, ///< R-work value + LS_R_FACTOR_R_FREE ///< R-free value } RefineItems; /// \enum items of the pdbx_struct_assembly category diff --git a/modules/io/tests/test_mmcif_reader.cc b/modules/io/tests/test_mmcif_reader.cc index 83cba518f76fd002405e1a0f789fb43afc4b5f22..fb87382d106a3742a4ca3e0eee908da57cd4f394 100644 --- a/modules/io/tests/test_mmcif_reader.cc +++ b/modules/io/tests/test_mmcif_reader.cc @@ -678,11 +678,9 @@ BOOST_AUTO_TEST_CASE(mmcif_refine_tests) IOProfile profile; MMCifReader mmcif_p(s, eh, profile); BOOST_REQUIRE_NO_THROW(mmcif_p.Parse()); - #if OST_DOUBLE_PRECISION - BOOST_CHECK_CLOSE(mmcif_p.GetInfo().GetResolution(), 2.0, 0.001); - #else - BOOST_CHECK_CLOSE(mmcif_p.GetInfo().GetResolution(), 2.0f, 0.001f); - #endif + BOOST_CHECK_CLOSE(mmcif_p.GetInfo().GetResolution(), Real(2), Real(0.001)); + BOOST_CHECK_CLOSE(mmcif_p.GetInfo().GetRFree(), Real(0.229), Real(0.01)); + BOOST_CHECK_CLOSE(mmcif_p.GetInfo().GetRWork(), Real(0.200), Real(0.01)); } BOOST_TEST_MESSAGE(" done."); BOOST_TEST_MESSAGE(" capturing fishy data lines..."); diff --git a/modules/io/tests/testfiles/mmcif/atom_site.mmcif b/modules/io/tests/testfiles/mmcif/atom_site.mmcif index 68b2fbb5769c6e735ec7e30cb7311f002f9b3346..9bd8159d6215e3bf3c1dac4a6fae03f0c73c2375 100644 --- a/modules/io/tests/testfiles/mmcif/atom_site.mmcif +++ b/modules/io/tests/testfiles/mmcif/atom_site.mmcif @@ -51,9 +51,11 @@ _citation_author.name _exptl.entry_id experiment1 _exptl.method 'Deep-fry' -_refine.entry_id '1BAR' -_refine.ls_d_res_high 2.0 -_refine.ls_d_res_low 1.5 +_refine.entry_id '1BAR' +_refine.ls_d_res_high 2.0 +_refine.ls_d_res_low 1.5 +_refine.ls_R_factor_R_work 0.200 +_refine.ls_R_factor_R_free 0.229 # biounit begin loop_