diff --git a/modules/io/doc/mmcif.rst b/modules/io/doc/mmcif.rst index 83f3b7c44c7173817442861881566a6ed0b786ed..dbe649b3284490a4e7775881496b2904a75f7259 100644 --- a/modules/io/doc/mmcif.rst +++ b/modules/io/doc/mmcif.rst @@ -31,6 +31,8 @@ The following categories of a mmCIF file are considered by the reader: * ``exptl``: Goes into :class:`MMCifInfo` as :attr:`~MMCifInfo.method`. * ``refine``: Goes into :class:`MMCifInfo` as :attr:`~MMCifInfo.resolution`, :attr:`~MMCifInfo.r_free` and :attr:`~MMCifInfo.r_work`. +* ``em_3d_reconstruction``: Goes into :class:`MMCifInfo` as + :attr:`~MMCifInfo.em_resolution`. * ``pdbx_struct_assembly``: Used for :class:`MMCifInfoBioUnit`. * ``pdbx_struct_assembly_gen``: Used for :class:`MMCifInfoBioUnit`. * ``pdbx_struct_oper_list``: Used for :class:`MMCifInfoBioUnit`. @@ -140,12 +142,22 @@ of the annotation available. .. attribute:: resolution - Stores the resolution of the crystal structure. Set to 0 if no value in + Stores the resolution of the crystal structure, obtained from the + ``refine.ls_d_res_high`` data item. Set to 0 if no value in loaded mmCIF file. Also available as :meth:`GetResolution`. May also be modified by :meth:`SetResolution`. + .. attribute:: em_resolution + + Stores the resolution of the EM reconstruction, obtained from the + ``em_3d_reconstruction.resolution`` data item. Set to 0 if no value + in loaded mmCIF file. + + Also available as :meth:`GetEMResolution`. May also be modified by + :meth:`SetEMResolution`. + .. attribute:: r_free Stores the R-free value of the crystal structure. Set to 0 if no value in diff --git a/modules/io/pymod/export_mmcif_io.cc b/modules/io/pymod/export_mmcif_io.cc index f08315a4978499bfef95d2fe014a2c9e4fe74b49..bd892405f7bddb281a16cef43f68d6a981efa66c 100644 --- a/modules/io/pymod/export_mmcif_io.cc +++ b/modules/io/pymod/export_mmcif_io.cc @@ -507,6 +507,8 @@ void export_mmcif_io() .def("GetMethod", &MMCifInfo::GetMethod) .def("SetResolution", &MMCifInfo::SetResolution) .def("GetResolution", &MMCifInfo::GetResolution) + .def("SetEMResolution", &MMCifInfo::SetEMResolution) + .def("GetEMResolution", &MMCifInfo::GetEMResolution) .def("SetRFree", &MMCifInfo::SetRFree) .def("GetRFree", &MMCifInfo::GetRFree) .def("SetRWork", &MMCifInfo::SetRWork) @@ -545,6 +547,8 @@ void export_mmcif_io() .add_property("method", &MMCifInfo::GetMethod, &MMCifInfo::SetMethod) .add_property("resolution", &MMCifInfo::GetResolution, &MMCifInfo::SetResolution) + .add_property("em_resolution", &MMCifInfo::GetEMResolution, + &MMCifInfo::SetEMResolution) .add_property("r_free", &MMCifInfo::GetRFree, &MMCifInfo::SetRFree) .add_property("r_work", &MMCifInfo::GetRWork, &MMCifInfo::SetRWork) .add_property("operations", make_function(&MMCifInfo::GetOperations, diff --git a/modules/io/src/mol/mmcif_info.hh b/modules/io/src/mol/mmcif_info.hh index 5114b4d9e1526d382e765d39b05d69171c7d64cc..054ecb3a626b57910ac710359434a1aeef8be04b 100644 --- a/modules/io/src/mol/mmcif_info.hh +++ b/modules/io/src/mol/mmcif_info.hh @@ -989,7 +989,8 @@ typedef std::map<String, MMCifEntityDesc> MMCifEntityDescMap; class DLLEXPORT_OST_IO MMCifInfo { public: /// \brief Create an info object. - MMCifInfo(): exptl_method_(""), resolution_(0), r_free_(0), r_work_(0) { } + MMCifInfo(): exptl_method_(""), resolution_(0), em_resolution_(0), r_free_(0), + r_work_(0) { } /// \brief Add an item to the list of citations /// @@ -1037,6 +1038,16 @@ public: /// \return experiment resolution Real GetResolution() const { return resolution_; } + /// \brief Set EM resolution. + /// + /// \param res EM experiment resolution + void SetEMResolution(Real res) { em_resolution_ = res; } + + /// \brief Get EM resolution. + /// + /// \return EM experiment resolution + Real GetEMResolution() const { return em_resolution_; } + /// \brief Set R-free value. /// /// \param res experiment R-free value @@ -1226,6 +1237,7 @@ private: // members String exptl_method_; Real resolution_; + Real em_resolution_; Real r_free_; Real r_work_; MMCifInfoStructDetails struct_details_; ///< mmCIF struct category diff --git a/modules/io/src/mol/mmcif_reader.cc b/modules/io/src/mol/mmcif_reader.cc index 9ad17290f263753625b45c7f26e485a03fe05b0d..90970daa3c8cd963fb99deaddf8dcb0907e64550 100644 --- a/modules/io/src/mol/mmcif_reader.cc +++ b/modules/io/src/mol/mmcif_reader.cc @@ -397,7 +397,12 @@ bool MMCifReader::OnBeginLoop(const StarLoopDesc& header) this->TryStoreIdx(EPS_MON_ID, "mon_id", header); this->TryStoreIdx(EPS_NUM, "num", header); cat_available = true; - } + } else if (header.GetCategory() == "em_3d_reconstruction") { + category_ = EM_3D_RECONSTRUCTION; + // optional items + indices_[EM_RESOLUTION] = header.GetIndex("resolution"); + cat_available = true; + } category_counts_[category_]++; return cat_available; } @@ -1025,6 +1030,14 @@ void MMCifReader::ParseRefine(const std::vector<StringRef>& columns) } } +void MMCifReader::ParseEm3DReconstruction(const std::vector<StringRef>& columns) +{ + StringRef col = columns[indices_[EM_RESOLUTION]]; + if (col.size()!=1 || (col[0]!='?' && col[0]!='.')) { + info_.SetEMResolution(this->TryGetReal(col, "em_3d_reconstruction.resolution")); + } +} + void MMCifReader::ParsePdbxStructAssembly(const std::vector<StringRef>& columns) { MMCifPSAEntry psa; @@ -1652,6 +1665,10 @@ void MMCifReader::OnDataRow(const StarLoopDesc& header, LOG_TRACE("processing entity_poly_seq entry"); this->ParseEntityPolySeq(columns); break; + case EM_3D_RECONSTRUCTION: + LOG_TRACE("processing em_3d_reconstruction entry"); + this->ParseEm3DReconstruction(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 43f6cc220a8db607af23f8884edf20a35e407b71..e0b4c4c0b664e66dce8fd67ce6ea176d8bbd3064 100644 --- a/modules/io/src/mol/mmcif_reader.hh +++ b/modules/io/src/mol/mmcif_reader.hh @@ -343,6 +343,11 @@ protected: /// \param columns data row void ParseEntityPolySeq(const std::vector<StringRef>& columns); + /// \brief Fetch mmCIF entity_poly_seq information + /// + /// \param columns data row + void ParseEm3DReconstruction(const std::vector<StringRef>& columns); + /// \struct types of secondary structure typedef enum { MMCIF_HELIX, @@ -607,6 +612,11 @@ private: EPS_NUM } EntityPolySeqItems; + /// \enum items of the entity_poly_seq category + typedef enum { + EM_RESOLUTION + } Em3DReconstructionItems; + /// \enum categories of the mmcif format typedef enum { ATOM_SITE, @@ -633,6 +643,7 @@ private: PDBX_ENTITY_BRANCH, PDBX_ENTITY_BRANCH_LINK, ENTITY_POLY_SEQ, + EM_3D_RECONSTRUCTION, DONT_KNOW } MMCifCategory; diff --git a/modules/io/tests/test_io_mmcif.py b/modules/io/tests/test_io_mmcif.py index a1b21770993e27e37adbd15d258f99e9ce831316..37e9ac6b03cd7bf034f947504473fca74fbbe66f 100644 --- a/modules/io/tests/test_io_mmcif.py +++ b/modules/io/tests/test_io_mmcif.py @@ -61,6 +61,7 @@ class TestMMCifInfo(unittest.TestCase): i = io.MMCifInfo() i.SetMethod('Deep-Fry') i.SetResolution(2.0) + i.SetEMResolution(3.0) i.AddCitation(c) s.append('Bar') i.AddAuthorsToCitation('ID', s) @@ -74,6 +75,7 @@ class TestMMCifInfo(unittest.TestCase): self.assertEqual(i.GetMethod(), 'Deep-Fry') self.assertEqual(i.GetResolution(), 2.0) + self.assertEqual(i.GetEMResolution(), 3.0) def test_mmcifinfo_biounit(self):