diff --git a/modules/io/pymod/export_omf_io.cc b/modules/io/pymod/export_omf_io.cc index b50392dc09ce99de19489f493d1908d681501cd8..fb98237b0ffbb2e5c6e5cd6d00ceceeefde080dd 100644 --- a/modules/io/pymod/export_omf_io.cc +++ b/modules/io/pymod/export_omf_io.cc @@ -73,6 +73,7 @@ void export_omf_io() { .def("GetAU", &OMF::GetAU) .def("GetAUChain", &OMF::GetAUChain) .def("GetBU", &OMF::GetBU) + .def("GetName", &OMF::GetName) .def("GetChainNames", &wrap_get_chain_names) .def("GetPositions", &OMF::GetPositions, return_value_policy<reference_existing_object>(),(arg("cname"))) .def("GetBFactors", &OMF::GetBFactors, return_value_policy<reference_existing_object>(),(arg("cname"))) diff --git a/modules/io/src/mol/omf.cc b/modules/io/src/mol/omf.cc index ddaf3d59114f1cd6157ef31ef0b0cfc294a276ab..973595161ed6295631bf6e26593d9984b81b7d1e 100644 --- a/modules/io/src/mol/omf.cc +++ b/modules/io/src/mol/omf.cc @@ -808,6 +808,26 @@ namespace{ RunLengthEncoding(transformed_sec_structures, run_length_encoded); Dump(stream, run_length_encoded); } + + void DumpName(std::ostream& stream, const String& name) { + if(name.size() > std::numeric_limits<uint8_t>::max()) { + std::stringstream ss; + ss << "Max name size that can be dumped is "; + ss << std::numeric_limits<uint8_t>::max << ". "; + ss << "got: "<<name<<std::endl; + throw ost::Error(ss.str()); + } + uint8_t size = name.size(); + stream.write(reinterpret_cast<char*>(&size), sizeof(uint8_t)); + stream.write(reinterpret_cast<const char*>(&name[0]), size*sizeof(char)); + } + + void LoadName(std::istream& stream, String& name) { + uint8_t size; + stream.read(reinterpret_cast<char*>(&size), sizeof(uint8_t)); + name.resize(size); + stream.read(reinterpret_cast<char*>(&name[0]), size*sizeof(uint8_t)); + } } @@ -3358,7 +3378,9 @@ OMFPtr OMF::FromEntity(const ost::mol::EntityHandle& ent, uint8_t options) { OMFPtr omf(new OMF); + omf->name_ = ent.GetName(); omf->options_ = options; + omf->version_ = OMF_VERSION; ////////////////////////////////////////////////////////////////////////////// // Generate kind of a "mini compound library"... Eeach unique residue gets // @@ -3538,6 +3560,7 @@ String OMF::ToString() const { ost::mol::EntityHandle OMF::GetAU() const{ ost::mol::EntityHandle ent = mol::CreateEntity(); + ent.SetName(name_); ost::mol::XCSEditor ed = ent.EditXCS(mol::BUFFERED_EDIT); for(auto it = chain_data_.begin(); it!=chain_data_.end(); ++it) { @@ -3563,6 +3586,9 @@ ost::mol::EntityHandle OMF::GetAUChain(const String& name) const{ throw ost::Error("No chain of name " + name); } ost::mol::EntityHandle ent = mol::CreateEntity(); + std::stringstream ss; + ss << name_ << " " << name; + ent.SetName(ss.str()); ost::mol::XCSEditor ed = ent.EditXCS(mol::BUFFERED_EDIT); ost::mol::ChainHandle ch = ed.InsertChain(name); this->FillChain(ch, ed, chain_data_.at(name)); @@ -3576,6 +3602,9 @@ ost::mol::EntityHandle OMF::GetBU(int bu_idx) const{ const BioUnitDefinition& bu = biounit_definitions_[bu_idx]; ost::mol::EntityHandle ent = mol::CreateEntity(); + std::stringstream ss; + ss << name_ << " " << bu_idx; + ent.SetName(ss.str()); ost::mol::XCSEditor ed = ent.EditXCS(mol::BUFFERED_EDIT); std::vector<String> au_chain_names; @@ -3634,9 +3663,10 @@ void OMF::ToStream(std::ostream& stream) const { // We set it to the current version... // If you loaded a structure from a previous version and you dump it again, // the version will be updated. - uint32_t version = OMF_VERSION; + uint32_t version = version_; stream.write(reinterpret_cast<char*>(&version), sizeof(uint32_t)); stream.write(reinterpret_cast<const char*>(&options_), sizeof(uint8_t)); + DumpName(stream, name_); if(OptionSet(DEFAULT_PEPLIB)) { // no need to dump the residue definitions from default lib @@ -3678,6 +3708,7 @@ void OMF::FromStream(std::istream& stream) { if(version_ > 1) { stream.read(reinterpret_cast<char*>(&options_), sizeof(uint8_t)); + LoadName(stream, name_); } if(OptionSet(DEFAULT_PEPLIB)) { diff --git a/modules/io/src/mol/omf.hh b/modules/io/src/mol/omf.hh index e049e53482d65124b85c26e8a1b3b969c767c858..f5bb8b9966b0b5c74d9d114f745f212c16b52799 100644 --- a/modules/io/src/mol/omf.hh +++ b/modules/io/src/mol/omf.hh @@ -190,6 +190,9 @@ public: // data access without requirement of generating a full // OpenStructure entity + + String GetName() const { return name_; } + std::vector<String> GetChainNames() const; const geom::Vec3List& GetPositions(const String& cname) const; @@ -210,6 +213,7 @@ private: const ChainDataPtr data, geom::Mat4 transform = geom::Mat4()) const; + String name_; std::vector<ResidueDefinition> residue_definitions_; std::vector<BioUnitDefinition> biounit_definitions_; std::map<String, ChainDataPtr> chain_data_; diff --git a/modules/io/tests/test_io_omf.py b/modules/io/tests/test_io_omf.py index 840d9f42d75794620b8e45b312a90ed826f2b232..1ed14044a23919d8f9624254a7d270db2d815a8d 100644 --- a/modules/io/tests/test_io_omf.py +++ b/modules/io/tests/test_io_omf.py @@ -78,7 +78,13 @@ def compare_bonds(ent1, ent2): def compare_ent(ent1, ent2, at_occupancy_thresh = 0.01, at_bfactor_thresh = 0.01, at_dist_thresh = 0.001, skip_ss=False, skip_cnames = False, skip_bonds = False, - skip_rnums=False): + skip_rnums=False, bu_idx = None): + if bu_idx is not None: + if ent1.GetName() + ' ' + str(bu_idx) != ent2.GetName(): + return False + else: + if ent1.GetName() != ent2.GetName(): + return False chain_names_one = [ch.GetName() for ch in ent1.chains] chain_names_two = [ch.GetName() for ch in ent2.chains] if skip_cnames: @@ -109,6 +115,7 @@ class TestOMF(unittest.TestCase): self.ent = ent self.seqres = seqres self.info = info + self.ent.SetName("This is a name 123") def test_AU(self): omf = io.OMF.FromMMCIF(self.ent, self.info) @@ -220,15 +227,15 @@ class TestOMF(unittest.TestCase): # - skip_bonds: Thats qualified atom name based. PDBize used rnums # and insertion codes for waters... # - skip_rnums: Again, insertion codes for waters... - self.assertTrue(compare_ent(omf_loaded.GetBU(0), - info.GetBioUnits()[0].PDBize(ent), + self.assertTrue(compare_ent(info.GetBioUnits()[0].PDBize(ent), + omf_loaded.GetBU(0), skip_cnames=True, skip_bonds=True, - skip_rnums=True)) + skip_rnums=True, bu_idx = 0)) - self.assertTrue(compare_ent(omf_loaded.GetBU(1), - info.GetBioUnits()[1].PDBize(ent), + self.assertTrue(compare_ent(info.GetBioUnits()[1].PDBize(ent), + omf_loaded.GetBU(1), skip_cnames=True, skip_bonds=True, - skip_rnums=True)) + skip_rnums=True, bu_idx = 1)) # no check for the full guy... problem: PDBize throws all water # molecules in the same chain, whereas OMF keeps them separate