From 1e709c334434c68386bb88dc29e79101fcf5824f Mon Sep 17 00:00:00 2001 From: tobias <tobias@5a81b35b-ba03-0410-adc8-b2c5c5119f08> Date: Tue, 11 May 2010 13:53:58 +0000 Subject: [PATCH] - added unit tests for sdf file reader/writer - moved compare_files to base/test_utils - reorganized sdf file reader/writer git-svn-id: https://dng.biozentrum.unibas.ch/svn/openstructure/trunk@2236 5a81b35b-ba03-0410-adc8-b2c5c5119f08 --- modules/base/src/CMakeLists.txt | 3 +- modules/base/src/test_utils/compare_files.cc | 52 +++ modules/base/src/test_utils/compare_files.hh | 27 ++ modules/gfx/tests/CMakeLists.txt | 6 +- modules/gfx/tests/test_ent_pov_export.cc | 31 +- modules/io/src/mol/CMakeLists.txt | 4 + modules/io/src/mol/entity_io_sdf_handler.cc | 378 +----------------- modules/io/src/mol/entity_io_sdf_handler.hh | 24 -- modules/io/src/mol/sdf_reader.cc | 275 +++++++++++++ modules/io/src/mol/sdf_reader.hh | 67 ++++ modules/io/src/mol/sdf_writer.cc | 158 ++++++++ modules/io/src/mol/sdf_writer.hh | 61 +++ modules/io/tests/test_io_pdb.cc | 31 +- modules/io/tests/test_io_sdf.cc | 182 ++++++++- .../{test_in.sdf => sdf/compound.sdf} | 264 ++++++------ .../tests/testfiles/sdf/empty_dataheader.sdf | 48 +++ modules/io/tests/testfiles/sdf/multiple.sdf | 72 ++++ modules/io/tests/testfiles/sdf/properties.sdf | 48 +++ modules/io/tests/testfiles/sdf/simple.sdf | 18 + .../tests/testfiles/sdf/wrong_atomcount.sdf | 18 + .../testfiles/sdf/wrong_atomlinelength.sdf | 18 + .../io/tests/testfiles/sdf/wrong_atompos.sdf | 18 + .../testfiles/sdf/wrong_bondatomnumber.sdf | 18 + .../tests/testfiles/sdf/wrong_bondcount.sdf | 18 + .../testfiles/sdf/wrong_bondlinelength.sdf | 18 + .../io/tests/testfiles/sdf/wrong_bondtype.sdf | 18 + .../io/tests/testfiles/sdf/wrong_charge.sdf | 18 + .../tests/testfiles/sdf/wrong_dataheader.sdf | 48 +++ 28 files changed, 1352 insertions(+), 589 deletions(-) create mode 100644 modules/base/src/test_utils/compare_files.cc create mode 100644 modules/base/src/test_utils/compare_files.hh create mode 100644 modules/io/src/mol/sdf_reader.cc create mode 100644 modules/io/src/mol/sdf_reader.hh create mode 100644 modules/io/src/mol/sdf_writer.cc create mode 100644 modules/io/src/mol/sdf_writer.hh rename modules/io/tests/testfiles/{test_in.sdf => sdf/compound.sdf} (97%) create mode 100644 modules/io/tests/testfiles/sdf/empty_dataheader.sdf create mode 100644 modules/io/tests/testfiles/sdf/multiple.sdf create mode 100644 modules/io/tests/testfiles/sdf/properties.sdf create mode 100644 modules/io/tests/testfiles/sdf/simple.sdf create mode 100644 modules/io/tests/testfiles/sdf/wrong_atomcount.sdf create mode 100644 modules/io/tests/testfiles/sdf/wrong_atomlinelength.sdf create mode 100644 modules/io/tests/testfiles/sdf/wrong_atompos.sdf create mode 100644 modules/io/tests/testfiles/sdf/wrong_bondatomnumber.sdf create mode 100644 modules/io/tests/testfiles/sdf/wrong_bondcount.sdf create mode 100644 modules/io/tests/testfiles/sdf/wrong_bondlinelength.sdf create mode 100644 modules/io/tests/testfiles/sdf/wrong_bondtype.sdf create mode 100644 modules/io/tests/testfiles/sdf/wrong_charge.sdf create mode 100644 modules/io/tests/testfiles/sdf/wrong_dataheader.sdf diff --git a/modules/base/src/CMakeLists.txt b/modules/base/src/CMakeLists.txt index ecdc389db..c2d698cf9 100644 --- a/modules/base/src/CMakeLists.txt +++ b/modules/base/src/CMakeLists.txt @@ -8,6 +8,7 @@ units.cc string_ref.cc platform.cc message.cc +test_utils/compare_files.cc ) set(OST_BASE_HEADERS @@ -32,7 +33,7 @@ tri_matrix.hh ) module(NAME base SOURCES ${OST_BASE_SOURCES} - HEADERS generic_property_def.hh IN_DIR export_helper ${OST_BASE_HEADERS} + HEADERS generic_property_def.hh IN_DIR export_helper compare_files.hh IN_DIR test_utils ${OST_BASE_HEADERS} DEPENDS_ON geom HEADER_OUTPUT_DIR ost) diff --git a/modules/base/src/test_utils/compare_files.cc b/modules/base/src/test_utils/compare_files.cc new file mode 100644 index 000000000..ff5578299 --- /dev/null +++ b/modules/base/src/test_utils/compare_files.cc @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2010 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +#include <iostream> +#include <fstream> +#include "compare_files.hh" + +bool compare_files(const String& test, const String& gold_standard) +{ + std::ifstream test_stream(test.c_str()); + std::ifstream gold_stream(gold_standard.c_str()); + String test_line, gold_line; + while (true) { + bool test_end=std::getline(test_stream, test_line); + bool gold_end=std::getline(gold_stream, gold_line); + if (!(test_end || gold_end)) { + return true; + } + if (!test_end) { + std::cerr << gold_standard << " contains additional line(s):" + << std::endl << gold_line; + return false; + } + if (!gold_end) { + std::cerr << test << " contains additional line(s):" + << std::endl << test_line; + return false; + } + if (gold_line!=test_line) { + std::cerr << "line mismatch:" << std::endl << "test: " << test_line + << std::endl << "gold: " << gold_line; + return false; + } + } + return true; +} diff --git a/modules/base/src/test_utils/compare_files.hh b/modules/base/src/test_utils/compare_files.hh new file mode 100644 index 000000000..7f441ae69 --- /dev/null +++ b/modules/base/src/test_utils/compare_files.hh @@ -0,0 +1,27 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2010 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +#ifndef OST_COMPARE_FILES_HH +#define OST_COMPARE_FILES_HH + +#include <ost/base.hh> + +bool compare_files(const String& test, const String& gold_standard); + +#endif diff --git a/modules/gfx/tests/CMakeLists.txt b/modules/gfx/tests/CMakeLists.txt index a055e099e..fe6a3d670 100644 --- a/modules/gfx/tests/CMakeLists.txt +++ b/modules/gfx/tests/CMakeLists.txt @@ -4,10 +4,8 @@ set(OST_GFX_UNIT_TESTS ) if (ENABLE_IMG) list(APPEND OST_GFX_UNIT_TESTS test_map_octree.cc) - - ost_unittest(gfx "${OST_GFX_UNIT_TESTS}") - - target_link_libraries(gfx_tests ost_io) endif() +ost_unittest(gfx "${OST_GFX_UNIT_TESTS}") +target_link_libraries(gfx_tests ost_io) diff --git a/modules/gfx/tests/test_ent_pov_export.cc b/modules/gfx/tests/test_ent_pov_export.cc index 450051dc7..bfb72ec79 100644 --- a/modules/gfx/tests/test_ent_pov_export.cc +++ b/modules/gfx/tests/test_ent_pov_export.cc @@ -26,6 +26,7 @@ #include <ost/io/load_entity.hh> #include <ost/gfx/scene.hh> #include <ost/gfx/entity.hh> +#include <ost/test_utils/compare_files.hh> using boost::unit_test_framework::test_suite; using namespace ost; @@ -42,36 +43,6 @@ boost::shared_ptr<Entity> prepare_object(gfx::RenderMode::Type mode) return gfx_ent; } -bool compare_files(const String& test, const String& gold_standard) -{ - std::ifstream test_stream(test.c_str()); - std::ifstream gold_stream(gold_standard.c_str()); - String test_line, gold_line; - while (true) { - bool test_end=std::getline(test_stream, test_line); - bool gold_end=std::getline(gold_stream, gold_line); - if (!(test_end || gold_end)) { - return true; - } - if (!test_end) { - std::cerr << gold_standard << " contains additional line(s):" - << std::endl << gold_line; - return false; - } - if (!gold_end) { - std::cerr << test << " contains additional line(s):" - << std::endl << test_line; - return false; - } - if (gold_line!=test_line) { - std::cerr << "line mismatch:" << std::endl << "test: " << test_line - << std::endl << "gold: " << gold_line; - return false; - } - } - return true; -} - // The GfxView uses a std::map for efficient access to atoms. This however has // implications for the POV export. In general we can't assume that the atoms // are written in any particular order. That's why we first filter out all diff --git a/modules/io/src/mol/CMakeLists.txt b/modules/io/src/mol/CMakeLists.txt index 5cdf0462b..860b4df0d 100644 --- a/modules/io/src/mol/CMakeLists.txt +++ b/modules/io/src/mol/CMakeLists.txt @@ -6,6 +6,8 @@ entity_io_pdb_handler.cc pdb_io.cc pdb_writer.cc entity_io_sdf_handler.cc +sdf_reader.cc +sdf_writer.cc save_entity.cc load_entity.cc surface_io_msms_handler.cc @@ -26,6 +28,8 @@ pdb_reader.hh entity_io_pdb_handler.hh pdb_writer.hh entity_io_sdf_handler.hh +sdf_reader.hh +sdf_writer.hh save_entity.hh load_entity.hh surface_io_handler.hh diff --git a/modules/io/src/mol/entity_io_sdf_handler.cc b/modules/io/src/mol/entity_io_sdf_handler.cc index f9c49479f..72ec53cbc 100644 --- a/modules/io/src/mol/entity_io_sdf_handler.cc +++ b/modules/io/src/mol/entity_io_sdf_handler.cc @@ -16,392 +16,50 @@ // along with this library; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA //------------------------------------------------------------------------------ -#include <iostream> -#include <sstream> -#include <iomanip> +/* + Author: Tobias Schmidt + */ -#include <boost/filesystem/fstream.hpp> -#include <boost/filesystem/convenience.hpp> -#include <boost/algorithm/string.hpp> -#include <boost/lexical_cast.hpp> -#include <boost/format.hpp> #include <ost/log.hh> -#include <ost/conop/conop.hh> -#include <ost/io/io_exception.hh> +#include <ost/io/sdf_writer.hh> +#include <ost/io/sdf_reader.hh> + #include "entity_io_sdf_handler.hh" namespace ost { namespace io { -using boost::format; bool EntityIOSDFHandler::RequiresBuilder() const { return false; } -// import data from provided stream -void EntityIOSDFHandler::Import(mol::EntityHandle& ent, std::istream& instream) +void EntityIOSDFHandler::Import(mol::EntityHandle& ent, + std::istream& instream) { - String line; - mol::XCSEditor editor=ent.RequestXCSEditor(mol::BUFFERED_EDIT); - while (std::getline(instream,line)) { - ++line_num; - - if (line_num<=4) { - ParseAndAddHeader(line, line_num, ent, editor); - } else if (line_num<=atom_count_+4) { - ParseAndAddAtom(line, line_num, ent, true, editor); - } else if (line_num<=bond_count_+atom_count_+4) { - ParseAndAddBond(line, line_num, ent, editor); - } else if (boost::iequals(line.substr(0,2), "> ")) { - // parse data items - int data_header_start = line.find('<'); - String data_header = line.substr(data_header_start+1,line.rfind('>')-data_header_start-1); - if(data_header.empty()) { - String msg="Bad data line %d: Could not find data header"; - throw IOException(str(format(msg) % line_num)); - } - String data_value=""; - while(std::getline(instream,line) && !boost::iequals(line, "")) { - data_value.append(line); - } - curr_chain_.SetStringProp(data_header, data_value); - } else if (boost::iequals(line, "$$$$")) { - LOGN_MESSAGE("MOLECULE " << curr_chain_.GetName() << " (" << chain_count_ << ") added.") - NextMolecule(); - } - } - - LOGN_MESSAGE("imported " << chain_count_ << " chains, " << residue_count_ - << " residues, " << atom_count_ << " atoms"); + SDFReader reader(instream); + reader.Import(ent); } - - void EntityIOSDFHandler::Import(mol::EntityHandle& ent, const boost::filesystem::path& loc) { - ClearState(); - boost::filesystem::ifstream instream(loc); - if(!instream) throw IOException("could not open "+loc.string()); - this->Import(ent, instream); -} - -void EntityIOSDFHandler::ClearState() -{ - curr_chain_=mol::ChainHandle(); - curr_residue_=mol::ResidueHandle(); - chain_count_=0; - residue_count_=0; - atom_count_=0; - bond_count_=0; - line_num=0; -} - -void EntityIOSDFHandler::NextMolecule() -{ - residue_count_=0; - atom_count_=0; - bond_count_=0; - line_num=0; -} - -void EntityIOSDFHandler::ParseAndAddHeader(const String& line, int line_num, - mol::EntityHandle& ent, mol::XCSEditor& editor) -{ - LOGN_TRACE( "line: [" << line << "]" ); - format chain_fmter("%05i_%s"); - switch(line_num) - { - case 1: // title line - { - ++chain_count_; - String s_title=line; - String s_chain; - chain_fmter % chain_count_ % boost::trim_copy(s_title); - s_chain=chain_fmter.str(); - if(s_chain.empty()) { - String msg="Bad molecule name line %d: Line is empty"; - throw IOException(str(format(msg) % line_num)); - } - curr_chain_=editor.InsertChain(s_chain); - LOGN_DUMP("new chain " << s_chain); - - mol::ResidueKey rkey=boost::trim_copy(s_title); - mol::ResNum rnum(++residue_count_); - curr_residue_=editor.AppendResidue(curr_chain_, rkey, rnum); - LOGN_DUMP("new residue " << rkey << "(" << rnum << ")"); - break; - } - case 2: // user information line - break; - case 3: // comments line - break; - case 4: // counts line - { - String s_anum=line.substr(0,3); - try { - atom_count_=boost::lexical_cast<int>(boost::trim_copy(s_anum)); - } catch(boost::bad_lexical_cast&) { - String msg="Bad counts line %d: Can't convert number of atoms" - " '%s' to integral constant."; - throw IOException(str(format(msg) % line_num % s_anum)); - } - String s_bnum=line.substr(3,3); - try { - bond_count_=boost::lexical_cast<int>(boost::trim_copy(s_bnum)); - } catch(boost::bad_lexical_cast&) { - String msg="Bad counts line %d: Can't convert number of bonds" - " '%s' to integral constant."; - throw IOException(str(format(msg) % line_num % s_bnum)); - } - break; - } - } -} - -void EntityIOSDFHandler::ParseAndAddAtom(const String& line, int line_num, - mol::EntityHandle& ent, bool hetatm, - mol::XCSEditor& editor) -{ - - LOGN_TRACE( "line: [" << line << "]" ); - - if(line.length()<48 || line.length()>69) { - String msg="Bad atom line %d: Not correct number of characters on the" - " line: %i (should be between 48 and 69)"; - throw IOException(str(format(msg) % line_num % line.length())); - } - int anum = line_num-4; // start at 1 on fifth line since first four lines are header - String s_posx=line.substr(0,10); - String s_posy=line.substr(10,10); - String s_posz=line.substr(20,10); - String s_ele=line.substr(31,3); - String s_charge=line.substr(36,3); - - geom::Vec3 apos; - try { - apos=geom::Vec3(boost::lexical_cast<Real>(boost::trim_copy(s_posx)), - boost::lexical_cast<Real>(boost::trim_copy(s_posy)), - boost::lexical_cast<Real>(boost::trim_copy(s_posz))); - } catch(boost::bad_lexical_cast&) { - String msg="Bad atom line %d: Can't convert coordinates to " - "floating point numbers"; - throw IOException(str(format(msg) % line_num)); - } - - String ele=boost::trim_copy(s_ele); - String aname=boost::lexical_cast<String>(anum); - - mol::AtomProp aprop; - aprop.element=ele; - aprop.radius=conop::Conopology::Instance().GetDefaultAtomRadius(ele); - aprop.mass=conop::Conopology::Instance().GetDefaultAtomMass(ele); - aprop.is_hetatm=hetatm; - - try { - aprop.charge=boost::lexical_cast<Real>(boost::trim_copy(s_charge)); - if(aprop.charge != 0) { - aprop.charge=4-aprop.charge; - } //4-sdf_charge=real_charge if not 0 - } catch(boost::bad_lexical_cast&) { - String msg="Bad atom line %d: Can't convert charge" - " '%s' to integral constant."; - throw IOException(str(format(msg) % line_num % s_charge)); - } - - LOGN_DUMP("adding atom " << aname << " (" << s_ele << ") @" << apos); - - editor.InsertAtom(curr_residue_, aname,apos,aprop); -} - - -void EntityIOSDFHandler::ParseAndAddBond(const String& line, int line_num, - mol::EntityHandle& ent, mol::XCSEditor& editor) -{ - - LOGN_TRACE( "line: [" << line << "]" ); - - if(line.length()<18 || line.length()>21) { - String msg="Bad bond line %d: Not correct number of characters on the" - " line: %i (should be between 18 and 21)"; - throw IOException(str(format(msg) % line_num % line.length())); - } - - String s_first_name=line.substr(0,3); - String s_second_name=line.substr(3,3); - String s_type=line.substr(6,3); - String first_name, second_name; - unsigned char type; - mol::BondHandle bond; - - first_name=boost::trim_copy(s_first_name); - second_name=boost::trim_copy(s_second_name); - - try { - type=boost::lexical_cast<int>(boost::trim_copy(s_type)); - } catch(boost::bad_lexical_cast&) { - String msg="Bad bond line %d: Can't convert bond type number" - " '%s' to integral constant."; - throw IOException(str(format(msg) % line_num % s_type)); - } - - mol::AtomHandle first,second; - - first = ent.FindAtom(curr_chain_.GetName(), mol::ResNum(residue_count_), first_name); - second = ent.FindAtom(curr_chain_.GetName(), mol::ResNum(residue_count_), second_name); - - if(first.IsValid() && second.IsValid()) { - bond = editor.Connect(first, second); - bond.SetBondOrder(type); - } else { - String msg="Bad bond line %d: Can't find the atom names '%s', '%s'" - " in entity."; - throw IOException(str(format(msg) % line_num % first % second)); - } - - LOGN_DUMP("adding bond " << s_first_name << " " << s_second_name << " (" << s_type << ") "); -} - -namespace { - - using boost::format; - - class SDFAtomWriter : public mol::EntityVisitor { - public: - SDFAtomWriter(std::ostream& ostream, std::map<long, int>& atom_indices) - : ostr_(ostream), atom_indices_(atom_indices), counter_(0) { - atom_indices_.clear(); - } - private: - public: - virtual bool VisitAtom(const mol::AtomHandle& atom) { - atom_indices_[atom.GetHashCode()] = ++counter_; - ostr_ << format("%10.4f") % atom.GetPos()[0] - << format("%10.4f") % atom.GetPos()[1] - << format("%10.4f ") % atom.GetPos()[2] - << format("%-3s") % atom.GetElement() - << " 0 0 0 0 0 0" - << std::endl; - return true; - } - private: - std::ostream& ostr_; - std::map<long, int>& atom_indices_; - int counter_; - }; - - class SDFBondWriter : public mol::EntityVisitor { - public: - SDFBondWriter(std::ostream& ostream, std::map<long, int>& atom_indices) - : ostr_(ostream), atom_indices_(atom_indices), counter_(0) { - } - private: - public: - virtual bool VisitAtom(const mol::AtomHandle& atom) { - counter_++; - mol::AtomHandleList atoms = atom.GetBondPartners(); - mol::AtomHandleList::iterator atom_iter = atoms.begin(); - for(; atom_iter != atoms.end(); ++atom_iter) { - int atom_index = atom_indices_.find((*atom_iter).GetHashCode())->second; - if(atom_index > counter_) { - int type = 1; - mol::BondHandle bond = atom.FindBondToAtom(*atom_iter); - if(bond.IsValid()) type = bond.GetBondOrder(); - ostr_ << format("%3i") % counter_ - << format("%3i") % atom_index - << format("%3i") % type - << " 0 0 0" - << std::endl; - } - } - return true; - } - - private: - std::ostream& ostr_; - std::map<long, int>& atom_indices_; - int counter_; - }; - - class SDFWriter : public mol::EntityVisitor { - public: - SDFWriter(std::ostream& ostream) - : ostr_(ostream), counter_(0) { - } - private: - public: - virtual bool VisitChain(const mol::ChainHandle& chain) { - // print end of molecule line - if(counter_ != 0) { - ostr_ << "$$$$" << std::endl; - counter_ = 0; - atom_indices_.clear(); - } - // print header lines - ostr_ << chain.GetName() << std::endl; - ostr_ << std::endl; - ostr_ << std::endl; - - // print counts line - ostr_ << format("%3d") % chain.GetAtomCount() - << format("%3d") % chain.GetBondCount() - << " 0 0 0 0 0 0 0 0999 V2000" - << std::endl; - - // write atom block - SDFAtomWriter atom_writer(ostr_, atom_indices_); - mol::ChainHandle non_const_chain = chain; - non_const_chain.Apply(atom_writer); - - // write bond block - SDFBondWriter bond_writer(ostr_, atom_indices_); - non_const_chain.Apply(bond_writer); - - // write property block - //TODO: wirte property block - ostr_ << "M END" << std::endl; - - // write data block - std::map<String,GenericPropValue> prop_map = non_const_chain.GetPropMap(); - std::map<String,GenericPropValue>::iterator iter; - for(iter = prop_map.begin(); iter != prop_map.end(); ++iter) { - ostr_ << "> <" << (*iter).first << ">" << std::endl; - ostr_ << (*iter).second << std::endl; - ostr_ << std::endl; - } - - // write molecule endline - ostr_ << "$$$$" << std::endl; - - return true; - } - - - - private: - std::ostream& ostr_; - int counter_; - std::map<long,int> atom_indices_; - }; - + SDFReader reader(loc); + reader.Import(ent); } void EntityIOSDFHandler::Export(const mol::EntityView& ent, const boost::filesystem::path& loc) const { - boost::filesystem::ofstream outfile(loc); - if(!outfile) throw IOException("could not open "+loc.string()+" for writing"); - this->Export(ent, outfile); + SDFWriter writer(loc); + writer.Write(ent); } -// export data from entity view to provided stream void EntityIOSDFHandler::Export(const mol::EntityView& ent, std::ostream& outstream) const { - SDFWriter writer(outstream); - mol::EntityView non_const_view = ent; - non_const_view.Apply(writer); + SDFWriter writer(outstream); + writer.Write(ent); } namespace { @@ -436,16 +94,12 @@ bool EntityIOSDFHandler::ProvidesExport(const boost::filesystem::path& loc, return sdf_handler_is_responsible_for(loc, type); } - - mol::EntityHandle LoadSDF(const String& file_name) { mol::EntityHandle ent_handle=mol::CreateEntity(); EntityIOSDFHandler ent_io; ent_io.Import(ent_handle,file_name); - LOG_DUMP("running conopology" << std::endl); - return ent_handle; } diff --git a/modules/io/src/mol/entity_io_sdf_handler.hh b/modules/io/src/mol/entity_io_sdf_handler.hh index 1baa629d4..cebf2fa5e 100644 --- a/modules/io/src/mol/entity_io_sdf_handler.hh +++ b/modules/io/src/mol/entity_io_sdf_handler.hh @@ -20,7 +20,6 @@ #define OST_IO_ENTITY_IO_PLUGIN_SDF_H #include <ost/io/mol/entity_io_handler.hh> -#include <ost//mol/xcs_editor.hh> namespace ost { namespace io { @@ -45,29 +44,6 @@ public: static String GetFormatName() { return String("Sdf"); } static String GetFormatDescription() { return String("Structure-data format from Molecular Design Limited"); } - -private: - void ClearState(); - - void NextMolecule(); - - void ParseAndAddHeader(const String& line, int line_num, mol::EntityHandle& ent, - mol::XCSEditor& editor); - - void ParseAndAddAtom(const String& line, int line_num, mol::EntityHandle& ent, - bool hetatm, mol::XCSEditor& editor); - - void ParseAndAddBond(const String& line, int line_num, mol::EntityHandle& ent, - mol::XCSEditor& editor); - - mol::ChainHandle curr_chain_; - mol::ResidueHandle curr_residue_; - int chain_count_; - int residue_count_; - int atom_count_; - int bond_count_; - int line_num; - }; typedef EntityIOHandlerFactory<EntityIOSDFHandler> EntityIOSDFHandlerFactory; diff --git a/modules/io/src/mol/sdf_reader.cc b/modules/io/src/mol/sdf_reader.cc new file mode 100644 index 000000000..e2f0fabd2 --- /dev/null +++ b/modules/io/src/mol/sdf_reader.cc @@ -0,0 +1,275 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2010 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +/* + Author: Tobias Schmidt + */ + +#include <boost/algorithm/string.hpp> +#include <boost/format.hpp> +#include <boost/lexical_cast.hpp> + +#include <ost/conop/conop.hh> +#include <ost/io/io_exception.hh> +#include <ost/log.hh> +#include <ost/mol/xcs_editor.hh> + +#include "sdf_reader.hh" + +namespace ost { namespace io { + +using boost::format; + +SDFReader::SDFReader(const String& filename) + : infile_(filename), instream_(infile_) { + this->ClearState(); +} + +SDFReader::SDFReader(const boost::filesystem::path& loc) + : infile_(loc), instream_(infile_) { + this->ClearState(); +} + +SDFReader::SDFReader(std::istream& instream) + : infile_(), instream_(instream) { + this->ClearState(); +} + +// import data from provided stream +void SDFReader::Import(mol::EntityHandle& ent) +{ + String line; + mol::XCSEditor editor=ent.RequestXCSEditor(mol::BUFFERED_EDIT); + while (std::getline(instream_,line)) { + ++line_num; + + if (line_num<=4) { + ParseAndAddHeader(line, line_num, ent, editor); + } else if (line_num<=atom_count_+4) { + ParseAndAddAtom(line, line_num, ent, true, editor); + } else if (line_num<=bond_count_+atom_count_+4) { + ParseAndAddBond(line, line_num, ent, editor); + } else if (boost::iequals(line.substr(0,2), "> ")) { + // parse data items + int data_header_start = line.find('<'); + if(data_header_start==-1) { + String msg="Bad data line %d: Could not find start or end of header"; + throw IOException(str(format(msg) % line_num)); + } + String data_header = line.substr(data_header_start+1,line.rfind('>')-data_header_start-1); + if(data_header.empty()) { + String msg="Bad data line %d: Could not find data header"; + throw IOException(str(format(msg) % line_num)); + } + String data_value=""; + while(std::getline(instream_,line) && !boost::iequals(line, "")) { + data_value.append(line); + } + curr_chain_.SetStringProp(data_header, data_value); + } else if (boost::iequals(line, "$$$$")) { + LOGN_MESSAGE("MOLECULE " << curr_chain_.GetName() << " (" << chain_count_ << ") added.") + NextMolecule(); + } + } + + LOGN_MESSAGE("imported " << chain_count_ << " chains, " << residue_count_ + << " residues, " << atom_count_ << " atoms"); +} + +void SDFReader::ClearState() +{ + curr_chain_=mol::ChainHandle(); + curr_residue_=mol::ResidueHandle(); + chain_count_=0; + residue_count_=0; + atom_count_=0; + bond_count_=0; + line_num=0; +} + +void SDFReader::NextMolecule() +{ + residue_count_=0; + atom_count_=0; + bond_count_=0; + line_num=0; +} + +void SDFReader::ParseAndAddHeader(const String& line, int line_num, + mol::EntityHandle& ent, mol::XCSEditor& editor) +{ + LOGN_TRACE( "line: [" << line << "]" ); + format chain_fmter("%05i_%s"); + switch(line_num) + { + case 1: // title line + { + ++chain_count_; + String s_title=line; + String s_chain; + chain_fmter % chain_count_ % boost::trim_copy(s_title); + s_chain=chain_fmter.str(); + if(s_chain.empty()) { + String msg="Bad molecule name line %d: Line is empty"; + throw IOException(str(format(msg) % line_num)); + } + curr_chain_=editor.InsertChain(s_chain); + LOGN_DUMP("new chain " << s_chain); + + mol::ResidueKey rkey=boost::trim_copy(s_title); + mol::ResNum rnum(++residue_count_); + curr_residue_=editor.AppendResidue(curr_chain_, rkey, rnum); + LOGN_DUMP("new residue " << rkey << "(" << rnum << ")"); + break; + } + case 2: // user information line + break; + case 3: // comments line + break; + case 4: // counts line + { + String s_anum=line.substr(0,3); + try { + atom_count_=boost::lexical_cast<int>(boost::trim_copy(s_anum)); + } catch(boost::bad_lexical_cast&) { + String msg="Bad counts line %d: Can't convert number of atoms" + " '%s' to integral constant."; + throw IOException(str(format(msg) % line_num % s_anum)); + } + String s_bnum=line.substr(3,3); + try { + bond_count_=boost::lexical_cast<int>(boost::trim_copy(s_bnum)); + } catch(boost::bad_lexical_cast&) { + String msg="Bad counts line %d: Can't convert number of bonds" + " '%s' to integral constant."; + throw IOException(str(format(msg) % line_num % s_bnum)); + } + break; + } + } +} + +void SDFReader::ParseAndAddAtom(const String& line, int line_num, + mol::EntityHandle& ent, bool hetatm, + mol::XCSEditor& editor) +{ + + LOGN_TRACE( "line: [" << line << "]" ); + + if(line.length()<48 || line.length()>69) { + String msg="Bad atom line %d: Not correct number of characters on the" + " line: %i (should be between 48 and 69)"; + throw IOException(str(format(msg) % line_num % line.length())); + } + int anum = line_num-4; // start at 1 on fifth line since first four lines are header + String s_posx=line.substr(0,10); + String s_posy=line.substr(10,10); + String s_posz=line.substr(20,10); + String s_ele=line.substr(31,3); + String s_charge=line.substr(36,3); + + geom::Vec3 apos; + try { + apos=geom::Vec3(boost::lexical_cast<Real>(boost::trim_copy(s_posx)), + boost::lexical_cast<Real>(boost::trim_copy(s_posy)), + boost::lexical_cast<Real>(boost::trim_copy(s_posz))); + } catch(boost::bad_lexical_cast&) { + String msg="Bad atom line %d: Can't convert coordinates to " + "floating point numbers"; + throw IOException(str(format(msg) % line_num)); + } + + String ele=boost::trim_copy(s_ele); + String aname=boost::lexical_cast<String>(anum); + + mol::AtomProp aprop; + aprop.element=ele; + aprop.radius=conop::Conopology::Instance().GetDefaultAtomRadius(ele); + aprop.mass=conop::Conopology::Instance().GetDefaultAtomMass(ele); + aprop.is_hetatm=hetatm; + + try { + aprop.charge=boost::lexical_cast<Real>(boost::trim_copy(s_charge)); + if(aprop.charge != 0) { + aprop.charge=4-aprop.charge; + } //4-sdf_charge=real_charge if not 0 + } catch(boost::bad_lexical_cast&) { + String msg="Bad atom line %d: Can't convert charge" + " '%s' to integral constant."; + throw IOException(str(format(msg) % line_num % s_charge)); + } + + LOGN_DUMP("adding atom " << aname << " (" << s_ele << ") @" << apos); + + editor.InsertAtom(curr_residue_, aname,apos,aprop); +} + + +void SDFReader::ParseAndAddBond(const String& line, int line_num, + mol::EntityHandle& ent, mol::XCSEditor& editor) +{ + + LOGN_TRACE( "line: [" << line << "]" ); + + if(line.length()<18 || line.length()>21) { + String msg="Bad bond line %d: Not correct number of characters on the" + " line: %i (should be between 18 and 21)"; + throw IOException(str(format(msg) % line_num % line.length())); + } + + String s_first_name=line.substr(0,3); + String s_second_name=line.substr(3,3); + String s_type=line.substr(6,3); + String first_name, second_name; + unsigned char type; + mol::BondHandle bond; + + first_name=boost::trim_copy(s_first_name); + second_name=boost::trim_copy(s_second_name); + + try { + type=boost::lexical_cast<int>(boost::trim_copy(s_type)); + if (type<1 || type>8) { + String msg="Bad bond line %d: Bond type number" + " '%s' not within accepted range (1-8)."; + throw IOException(str(format(msg) % line_num % s_type)); + } + } catch(boost::bad_lexical_cast&) { + String msg="Bad bond line %d: Can't convert bond type number" + " '%s' to integral constant."; + throw IOException(str(format(msg) % line_num % s_type)); + } + + mol::AtomHandle first,second; + + first = ent.FindAtom(curr_chain_.GetName(), mol::ResNum(residue_count_), first_name); + second = ent.FindAtom(curr_chain_.GetName(), mol::ResNum(residue_count_), second_name); + + if(first.IsValid() && second.IsValid()) { + bond = editor.Connect(first, second); + bond.SetBondOrder(type); + } else { + String msg="Bad bond line %d: Can't find the atom names '%s', '%s'" + " in entity."; + throw IOException(str(format(msg) % line_num % first % second)); + } + + LOGN_DUMP("adding bond " << s_first_name << " " << s_second_name << " (" << s_type << ") "); +} + +}} diff --git a/modules/io/src/mol/sdf_reader.hh b/modules/io/src/mol/sdf_reader.hh new file mode 100644 index 000000000..0401e6ab7 --- /dev/null +++ b/modules/io/src/mol/sdf_reader.hh @@ -0,0 +1,67 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2010 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +/* + Author: Tobias Schmidt + */ +#ifndef OST_IO_SDF_READER_HH +#define OST_IO_SDF_READER_HH + +#include <boost/filesystem/fstream.hpp> +#include <ost/mol/mol.hh> +#include <ost/io/module_config.hh> + +namespace ost { namespace io { + +class DLLEXPORT_OST_IO SDFReader { +public: + SDFReader(const String& filename); + SDFReader(const boost::filesystem::path& loc); + SDFReader(std::istream& instream); + + bool HasNext(); + + void Import(mol::EntityHandle& ent); + +private: + void ClearState(); + void NextMolecule(); + + void ParseAndAddHeader(const String& line, int line_num, mol::EntityHandle& ent, + mol::XCSEditor& editor); + + void ParseAndAddAtom(const String& line, int line_num, mol::EntityHandle& ent, + bool hetatm, mol::XCSEditor& editor); + + void ParseAndAddBond(const String& line, int line_num, mol::EntityHandle& ent, + mol::XCSEditor& editor); + + mol::ChainHandle curr_chain_; + mol::ResidueHandle curr_residue_; + int chain_count_; + int residue_count_; + int atom_count_; + int bond_count_; + int line_num; + boost::filesystem::ifstream infile_; + std::istream& instream_; +}; + +}} + +#endif diff --git a/modules/io/src/mol/sdf_writer.cc b/modules/io/src/mol/sdf_writer.cc new file mode 100644 index 000000000..b6243b4a6 --- /dev/null +++ b/modules/io/src/mol/sdf_writer.cc @@ -0,0 +1,158 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2010 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +/* + Author: Tobias Schmidt + */ + +#include "sdf_writer.hh" + +namespace ost { namespace io { + +using boost::format; + +namespace { + + class SDFAtomWriter : public mol::EntityVisitor { + public: + SDFAtomWriter(std::ostream& ostream, std::map<long, int>& atom_indices) + : ostr_(ostream), atom_indices_(atom_indices), counter_(0) { + atom_indices_.clear(); + } + private: + public: + virtual bool VisitAtom(const mol::AtomHandle& atom) { + atom_indices_[atom.GetHashCode()] = ++counter_; + ostr_ << format("%10.4f") % atom.GetPos()[0] + << format("%10.4f") % atom.GetPos()[1] + << format("%10.4f ") % atom.GetPos()[2] + << format("%-3s") % atom.GetElement() + << " 0 0 0 0 0 0" + << std::endl; + return true; + } + private: + std::ostream& ostr_; + std::map<long, int>& atom_indices_; + int counter_; + }; + + class SDFBondWriter : public mol::EntityVisitor { + public: + SDFBondWriter(std::ostream& ostream, std::map<long, int>& atom_indices) + : ostr_(ostream), atom_indices_(atom_indices), counter_(0) { + } + private: + public: + virtual bool VisitAtom(const mol::AtomHandle& atom) { + counter_++; + mol::AtomHandleList atoms = atom.GetBondPartners(); + mol::AtomHandleList::iterator atom_iter = atoms.begin(); + for(; atom_iter != atoms.end(); ++atom_iter) { + int atom_index = atom_indices_.find((*atom_iter).GetHashCode())->second; + if(atom_index > counter_) { + int type = 1; + mol::BondHandle bond = atom.FindBondToAtom(*atom_iter); + if(bond.IsValid()) type = bond.GetBondOrder(); + ostr_ << format("%3i") % counter_ + << format("%3i") % atom_index + << format("%3i") % type + << " 0 0 0" + << std::endl; + } + } + return true; + } + + private: + std::ostream& ostr_; + std::map<long, int>& atom_indices_; + int counter_; + }; +} + +SDFWriter::SDFWriter(std::ostream& ostream) + : outfile_(), ostr_(ostream), counter_(0) { +} + +SDFWriter::SDFWriter(const String& filename) + : outfile_(filename.c_str()), ostr_(outfile_), counter_(0) { +} + +SDFWriter::SDFWriter(const boost::filesystem::path& filename) + : outfile_(filename.file_string().c_str()), ostr_(outfile_), counter_(0) { +} + +void SDFWriter::Write(const mol::EntityView& ent) { + mol::EntityView non_const_view = ent; + non_const_view.Apply(*this); +} + +void SDFWriter::Write(const mol::EntityHandle& ent) { + mol::EntityHandle non_const_handle = ent; + non_const_handle.Apply(*this); +} + +bool SDFWriter::VisitChain(const mol::ChainHandle& chain) { + // print end of molecule line + if(counter_ != 0) { + ostr_ << "$$$$" << std::endl; + counter_ = 0; + atom_indices_.clear(); + } + + // print header lines + ostr_ << chain.GetName().substr(6) << std::endl; + ostr_ << std::endl; + ostr_ << std::endl; + + // print counts line + ostr_ << format("%3d") % chain.GetAtomCount() + << format("%3d") % chain.GetBondCount() + << " 0 0 0 0 999 V2000" + << std::endl; + + // write atom block + SDFAtomWriter atom_writer(ostr_, atom_indices_); + mol::ChainHandle non_const_chain = chain; + non_const_chain.Apply(atom_writer); + + // write bond block + SDFBondWriter bond_writer(ostr_, atom_indices_); + non_const_chain.Apply(bond_writer); + + // write property block + //TODO: write property block + ostr_ << "M END" << std::endl; + + // write data block + std::map<String,GenericPropValue> prop_map = non_const_chain.GetPropMap(); + std::map<String,GenericPropValue>::iterator iter; + for(iter = prop_map.begin(); iter != prop_map.end(); ++iter) { + ostr_ << "> <" << (*iter).first << ">" << std::endl; + ostr_ << (*iter).second << std::endl; + ostr_ << std::endl; + } + + // write molecule endline + ostr_ << "$$$$" << std::endl; + + return true; +} + +}} diff --git a/modules/io/src/mol/sdf_writer.hh b/modules/io/src/mol/sdf_writer.hh new file mode 100644 index 000000000..62a365d49 --- /dev/null +++ b/modules/io/src/mol/sdf_writer.hh @@ -0,0 +1,61 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2010 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +/* + Author: Tobias Schmidt + */ +#ifndef OST_IO_SDF_WRITER_HH +#define OST_IO_SDF_WRITER_HH + +#include <iostream> +#include <sstream> +#include <iomanip> + +#include <boost/filesystem/fstream.hpp> +#include <boost/filesystem/convenience.hpp> +#include <boost/algorithm/string.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/format.hpp> +#include <ost/log.hh> +#include <ost/conop/conop.hh> +#include <ost/io/io_exception.hh> +#include <ost/mol/mol.hh> + +namespace ost { namespace io { + +class DLLEXPORT_OST_IO SDFWriter : public mol::EntityVisitor { +public: + SDFWriter(std::ostream& ostream); + SDFWriter(const String& filename); + SDFWriter(const boost::filesystem::path& filename); + + void Write(const mol::EntityView& ent); + void Write(const mol::EntityHandle& ent); + +private: + virtual bool VisitChain(const mol::ChainHandle& chain); + + std::ofstream outfile_; + std::ostream& ostr_; + int counter_; + std::map<long,int> atom_indices_; +}; + +}} + +#endif diff --git a/modules/io/tests/test_io_pdb.cc b/modules/io/tests/test_io_pdb.cc index 9be98cdba..54d7d49a9 100644 --- a/modules/io/tests/test_io_pdb.cc +++ b/modules/io/tests/test_io_pdb.cc @@ -16,6 +16,7 @@ // along with this library; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA //------------------------------------------------------------------------------ +#include <ost/test_utils/compare_files.hh> #include <ost/mol/mol.hh> #include <ost/conop/conop.hh> #include <ost/io/mol/entity_io_pdb_handler.hh> @@ -29,36 +30,6 @@ using boost::unit_test_framework::test_suite; using namespace ost; using namespace ost::io; - -bool compare_files(const String& test, const String& gold_standard) -{ - std::ifstream test_stream(test.c_str()); - std::ifstream gold_stream(gold_standard.c_str()); - String test_line, gold_line; - while (true) { - bool test_end=std::getline(test_stream, test_line); - bool gold_end=std::getline(gold_stream, gold_line); - if (!(test_end || gold_end)) { - return true; - } - if (!test_end) { - std::cerr << gold_standard << " contains additional line(s):" - << std::endl << gold_line; - return false; - } - if (!gold_end) { - std::cerr << test << " contains additional line(s):" - << std::endl << test_line; - return false; - } - if (gold_line!=test_line) { - std::cerr << "line mismatch:" << std::endl << "test: " << test_line - << std::endl << "gold: " << gold_line; - return false; - } - } - return true; -} BOOST_AUTO_TEST_SUITE( io ) diff --git a/modules/io/tests/test_io_sdf.cc b/modules/io/tests/test_io_sdf.cc index 71c773f39..19cdf7f49 100644 --- a/modules/io/tests/test_io_sdf.cc +++ b/modules/io/tests/test_io_sdf.cc @@ -16,33 +16,110 @@ // along with this library; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA //------------------------------------------------------------------------------ +#include <ost/test_utils/compare_files.hh> #include <ost/mol/mol.hh> #include <ost/io/mol/entity_io_sdf_handler.hh> +#include <ost/io/save_entity.hh> +#include <ost/io/io_exception.hh> #define BOOST_TEST_DYN_LINK #include <boost/test/unit_test.hpp> #include <boost/lexical_cast.hpp> #include <boost/algorithm/string.hpp> +using boost::unit_test_framework::test_suite; using namespace ost; using namespace ost::io; BOOST_AUTO_TEST_SUITE( io ) - -BOOST_AUTO_TEST_CASE(test_io_sdf) +BOOST_AUTO_TEST_CASE(test_sdf_import_handler) { - const String fname("testfiles/test_in.sdf"); + String fname("testfiles/sdf/compound.sdf"); mol::EntityHandle eh=mol::CreateEntity(); EntityIOSDFHandler sdfh; - // check format BOOST_CHECK(EntityIOSDFHandler::ProvidesImport("","sdf")); BOOST_CHECK(EntityIOSDFHandler::ProvidesImport(fname)); BOOST_CHECK(EntityIOSDFHandler::ProvidesImport("test_in.SDF")); + BOOST_CHECK(EntityIOSDFHandler::ProvidesExport("","sdf")); + BOOST_CHECK(EntityIOSDFHandler::ProvidesExport(fname)); + BOOST_CHECK(EntityIOSDFHandler::ProvidesExport("test_in.SDF")); + + sdfh.Import(eh,"testfiles/sdf/compound.sdf"); +} + +BOOST_AUTO_TEST_CASE(simple_sdf) +{ + mol::EntityHandle eh=mol::CreateEntity(); + EntityIOSDFHandler sdfh; + sdfh.Import(eh,"testfiles/sdf/simple.sdf"); + + // check compounds/atoms/bonds count + BOOST_CHECK_EQUAL(eh.GetChainCount(), 1); + BOOST_CHECK_EQUAL(eh.GetAtomCount(), 6); + BOOST_CHECK_EQUAL(eh.GetBondCount(), 6); + BOOST_CHECK_CLOSE(eh.GetMass(), 121.545502, 1e-4); + + // check atom/bond types + mol::AtomHandle ah=eh.GetAtomList()[0]; + mol::AtomHandle ah2=eh.GetAtomList()[5]; + + BOOST_CHECK_EQUAL(ah.GetElement(), "N"); + BOOST_CHECK_EQUAL(ah2.GetElement(), "Cl"); + BOOST_CHECK_CLOSE(ah.GetRadius(), 1.55, 1e-2); + BOOST_CHECK_CLOSE(ah2.GetRadius(), 1.75, 1e-2); + BOOST_CHECK_CLOSE(ah.GetMass(), 14.0067, 1e-4); + BOOST_CHECK_CLOSE(ah2.GetMass(), 35.453, 1e-3); + BOOST_CHECK_EQUAL(ah.GetBondCount(), 3); + BOOST_CHECK_EQUAL(ah2.GetBondCount(), 1); + BOOST_CHECK_EQUAL(ah.GetCharge(), 1); + BOOST_CHECK_EQUAL(ah2.GetCharge(), 0); + + mol::BondHandle bh=ah.GetBondList()[0]; + BOOST_CHECK_EQUAL(bh.GetBondOrder(), 2); +} + +BOOST_AUTO_TEST_CASE(multiple_sdf) +{ + mol::EntityHandle eh=mol::CreateEntity(); + EntityIOSDFHandler sdfh; + sdfh.Import(eh,"testfiles/sdf/multiple.sdf"); + + // check number of compounds + BOOST_CHECK_EQUAL(eh.GetChainCount(), 4); +} + +BOOST_AUTO_TEST_CASE(properties_sdf) +{ + mol::EntityHandle eh=mol::CreateEntity(); + EntityIOSDFHandler sdfh; + sdfh.Import(eh,"testfiles/sdf/properties.sdf"); + + // check number of compounds + mol::ChainHandleList chl=eh.GetChainList(); + int count=1; + for (mol::ChainHandleList::iterator i=chl.begin();i!=chl.end();++i,count++) + { + BOOST_REQUIRE(i->HasProp("prop_one")); + BOOST_REQUIRE(i->HasProp("prop_two")); + BOOST_CHECK_EQUAL(i->GetStringProp("prop_one"), + boost::lexical_cast<std::string>(count)); + BOOST_CHECK_EQUAL(i->GetStringProp("prop_two"), + boost::lexical_cast<std::string>(count*(-2))); + } +} + +BOOST_AUTO_TEST_CASE(read_sdf) +{ + const String fname("testfiles/sdf/compound.sdf"); + + mol::EntityHandle eh=mol::CreateEntity(); + EntityIOSDFHandler sdfh; + // check import - sdfh.Import(eh,"testfiles/test_in.sdf"); + sdfh.Import(eh,"testfiles/sdf/compound.sdf"); // check atoms/bonds BOOST_CHECK_EQUAL(eh.GetChainCount(), 4); @@ -50,7 +127,7 @@ BOOST_AUTO_TEST_CASE(test_io_sdf) BOOST_CHECK_EQUAL(eh.GetBondCount(), 188); // check molecule name - mol::ChainHandle ch=eh.FindChain("00003_Displayed atoms"); + mol::ChainHandle ch=eh.FindChain("00003_Test Ligand"); BOOST_CHECK(ch.IsValid()); // check properties @@ -60,4 +137,97 @@ BOOST_AUTO_TEST_CASE(test_io_sdf) 0.543804f); } +BOOST_AUTO_TEST_CASE(write_sdf) +{ + // this scope is required to force the writer stream to be closed before + // opening the file again in compare_files. Avoids a race condition. + { + mol::EntityHandle eh=mol::CreateEntity(); + EntityIOSDFHandler sdfh; + sdfh.Import(eh,"testfiles/sdf/compound.sdf"); + SaveEntity(eh, "testfiles/sdf/compound-out.sdf"); + } + BOOST_CHECK(compare_files("testfiles/sdf/compound.sdf", + "testfiles/sdf/compound-out.sdf")); +} + +BOOST_AUTO_TEST_CASE(wrong_atomcount_error_sdf) +{ + mol::EntityHandle eh=mol::CreateEntity(); + EntityIOSDFHandler sdfh; + BOOST_CHECK_THROW(sdfh.Import(eh,"testfiles/sdf/wrong_atomcount.sdf"), IOException); +} + +BOOST_AUTO_TEST_CASE(wrong_bondcount_error_sdf) +{ + mol::EntityHandle eh=mol::CreateEntity(); + EntityIOSDFHandler sdfh; + BOOST_CHECK_THROW(sdfh.Import(eh,"testfiles/sdf/wrong_bondcount.sdf"), IOException); +} + +BOOST_AUTO_TEST_CASE(wrong_atomlinelength_error_sdf) +{ + mol::EntityHandle eh=mol::CreateEntity(); + EntityIOSDFHandler sdfh; + + BOOST_CHECK_THROW(sdfh.Import(eh,"testfiles/sdf/wrong_atomlinelength.sdf"), IOException); +} + +BOOST_AUTO_TEST_CASE(wrong_atompos_error_sdf) +{ + mol::EntityHandle eh=mol::CreateEntity(); + EntityIOSDFHandler sdfh; + + BOOST_CHECK_THROW(sdfh.Import(eh,"testfiles/sdf/wrong_atompos.sdf"), IOException); +} + +BOOST_AUTO_TEST_CASE(wrong_charge_error_sdf) +{ + mol::EntityHandle eh=mol::CreateEntity(); + EntityIOSDFHandler sdfh; + + BOOST_CHECK_THROW(sdfh.Import(eh,"testfiles/sdf/wrong_charge.sdf"), IOException); +} + +BOOST_AUTO_TEST_CASE(wrong_bondlinelength_error_sdf) +{ + mol::EntityHandle eh=mol::CreateEntity(); + EntityIOSDFHandler sdfh; + + BOOST_CHECK_THROW(sdfh.Import(eh,"testfiles/sdf/wrong_bondlinelength.sdf"), IOException); +} + +BOOST_AUTO_TEST_CASE(wrong_bondtype_error_sdf) +{ + mol::EntityHandle eh=mol::CreateEntity(); + EntityIOSDFHandler sdfh; + + BOOST_CHECK_THROW(sdfh.Import(eh,"testfiles/sdf/wrong_bondtype.sdf"), IOException); +} + +BOOST_AUTO_TEST_CASE(wrong_bondatomnumber_error_sdf) +{ + mol::EntityHandle eh=mol::CreateEntity(); + EntityIOSDFHandler sdfh; + + BOOST_CHECK_THROW(sdfh.Import(eh,"testfiles/sdf/wrong_bondatomnumber.sdf"), IOException); +} + +BOOST_AUTO_TEST_CASE(wrong_dataheader_error_sdf) +{ + mol::EntityHandle eh=mol::CreateEntity(); + EntityIOSDFHandler sdfh; + + BOOST_CHECK_THROW(sdfh.Import(eh,"testfiles/sdf/wrong_dataheader.sdf"), IOException); +} + +BOOST_AUTO_TEST_CASE(empty_dataheader_error_sdf) +{ + mol::EntityHandle eh=mol::CreateEntity(); + EntityIOSDFHandler sdfh; + + BOOST_CHECK_THROW(sdfh.Import(eh,"testfiles/sdf/empty_dataheader.sdf"), IOException); +} + + BOOST_AUTO_TEST_SUITE_END() diff --git a/modules/io/tests/testfiles/test_in.sdf b/modules/io/tests/testfiles/sdf/compound.sdf similarity index 97% rename from modules/io/tests/testfiles/test_in.sdf rename to modules/io/tests/testfiles/sdf/compound.sdf index 9d7bdcfc1..66ddbb589 100644 --- a/modules/io/tests/testfiles/test_in.sdf +++ b/modules/io/tests/testfiles/sdf/compound.sdf @@ -1,7 +1,7 @@ -Displayed atoms - 3D - Structure written by MMmdl. - 45 47 0 0 1 0 999 V2000 +Test Ligand + + + 45 47 0 0 0 0 999 V2000 35.9455 5.9021 22.1706 C 0 0 0 0 0 0 34.6074 5.5226 22.4445 O 0 0 0 0 0 0 33.9561 6.2475 23.4088 C 0 0 0 0 0 0 @@ -95,32 +95,29 @@ Displayed atoms 26 27 1 0 0 0 27 45 1 0 0 0 M END +> <i_i_glide_confnum> +2 + > <i_i_glide_lignum> 1 -> <r_i_docking_score> --8.84426 +> <i_i_glide_posenum> +352 -> <r_i_glide_gscore> +> <r_i_docking_score> -8.84426 -> <r_i_glide_lipo> --2.84534 - -> <r_i_glide_hbond> --0.960751 - -> <r_i_glide_metal> --0 +> <r_i_glide_ecoul> +-16.1644 -> <r_i_glide_rewards> --0.799851 +> <r_i_glide_einternal> +6.78671 -> <r_i_glide_evdw> --46.0502 +> <r_i_glide_emodel> +-96.9661 -> <r_i_glide_ecoul> --16.1644 +> <r_i_glide_energy> +-62.2146 > <r_i_glide_erotb> 0.517993 @@ -128,38 +125,41 @@ M END > <r_i_glide_esite> -0.0291388 -> <r_i_glide_emodel> --96.9661 +> <r_i_glide_evdw> +-46.0502 -> <r_i_glide_energy> --62.2146 +> <r_i_glide_gscore> +-8.84426 -> <r_i_glide_einternal> -6.78671 +> <r_i_glide_hbond> +-0.960751 > <r_i_glide_ligand_efficiency> -0.327565 +> <r_i_glide_ligand_efficiency_ln> +-2.0588 + > <r_i_glide_ligand_efficiency_sa> -0.982695 -> <r_i_glide_ligand_efficiency_ln> --2.0588 +> <r_i_glide_lipo> +-2.84534 -> <i_i_glide_confnum> -2 +> <r_i_glide_metal> +-0 -> <i_i_glide_posenum> -352 +> <r_i_glide_rewards> +-0.799851 > <r_i_glide_rmsd> 0.6819 $$$$ -Displayed atoms - 3D - Structure written by MMmdl. - 45 47 0 0 1 0 999 V2000 +Test Ligand + + + 45 47 0 0 0 0 999 V2000 34.3938 4.9895 21.4537 C 0 0 0 0 0 0 34.9786 5.7318 22.5298 O 0 0 0 0 0 0 34.1450 6.3862 23.4047 C 0 0 0 0 0 0 @@ -253,32 +253,29 @@ Displayed atoms 26 27 1 0 0 0 27 45 1 0 0 0 M END +> <i_i_glide_confnum> +14 + > <i_i_glide_lignum> 1 -> <r_i_docking_score> --8.79327 +> <i_i_glide_posenum> +302 -> <r_i_glide_gscore> +> <r_i_docking_score> -8.79327 -> <r_i_glide_lipo> --2.69167 - -> <r_i_glide_hbond> --0.966475 - -> <r_i_glide_metal> --0 +> <r_i_glide_ecoul> +-16.9687 -> <r_i_glide_rewards> --0.777126 +> <r_i_glide_einternal> +5.76514 -> <r_i_glide_evdw> --46.4187 +> <r_i_glide_emodel> +-98.4298 -> <r_i_glide_ecoul> --16.9687 +> <r_i_glide_energy> +-63.3874 > <r_i_glide_erotb> 0.517993 @@ -286,38 +283,41 @@ M END > <r_i_glide_esite> -0.00975737 -> <r_i_glide_emodel> --98.4298 +> <r_i_glide_evdw> +-46.4187 -> <r_i_glide_energy> --63.3874 +> <r_i_glide_gscore> +-8.79327 -> <r_i_glide_einternal> -5.76514 +> <r_i_glide_hbond> +-0.966475 > <r_i_glide_ligand_efficiency> -0.325677 +> <r_i_glide_ligand_efficiency_ln> +-2.04693 + > <r_i_glide_ligand_efficiency_sa> -0.97703 -> <r_i_glide_ligand_efficiency_ln> --2.04693 +> <r_i_glide_lipo> +-2.69167 -> <i_i_glide_confnum> -14 +> <r_i_glide_metal> +-0 -> <i_i_glide_posenum> -302 +> <r_i_glide_rewards> +-0.777126 > <r_i_glide_rmsd> 0.605551 $$$$ -Displayed atoms - 3D - Structure written by MMmdl. - 45 47 0 0 1 0 999 V2000 +Test Ligand + + + 45 47 0 0 0 0 999 V2000 36.2241 5.1749 22.8554 C 0 0 0 0 0 0 35.0609 5.8871 22.4479 O 0 0 0 0 0 0 34.2768 6.4601 23.4276 C 0 0 0 0 0 0 @@ -411,32 +411,29 @@ Displayed atoms 26 27 1 0 0 0 27 45 1 0 0 0 M END +> <i_i_glide_confnum> +1 + > <i_i_glide_lignum> 1 -> <r_i_docking_score> --8.70173 +> <i_i_glide_posenum> +177 -> <r_i_glide_gscore> +> <r_i_docking_score> -8.70173 -> <r_i_glide_lipo> --2.74283 - -> <r_i_glide_hbond> --0.97397 - -> <r_i_glide_metal> --0 +> <r_i_glide_ecoul> +-15.8862 -> <r_i_glide_rewards> --0.764823 +> <r_i_glide_einternal> +1.84397 -> <r_i_glide_evdw> --46.5538 +> <r_i_glide_emodel> +-99.0481 -> <r_i_glide_ecoul> --15.8862 +> <r_i_glide_energy> +-62.44 > <r_i_glide_erotb> 0.517993 @@ -444,38 +441,41 @@ M END > <r_i_glide_esite> -0.0274759 -> <r_i_glide_emodel> --99.0481 +> <r_i_glide_evdw> +-46.5538 -> <r_i_glide_energy> --62.44 +> <r_i_glide_gscore> +-8.70173 -> <r_i_glide_einternal> -1.84397 +> <r_i_glide_hbond> +-0.97397 > <r_i_glide_ligand_efficiency> -0.322286 +> <r_i_glide_ligand_efficiency_ln> +-2.02562 + > <r_i_glide_ligand_efficiency_sa> -0.966858 -> <r_i_glide_ligand_efficiency_ln> --2.02562 +> <r_i_glide_lipo> +-2.74283 -> <i_i_glide_confnum> -1 +> <r_i_glide_metal> +-0 -> <i_i_glide_posenum> -177 +> <r_i_glide_rewards> +-0.764823 > <r_i_glide_rmsd> 0.543804 $$$$ -Displayed atoms - 3D - Structure written by MMmdl. - 45 47 0 0 1 0 999 V2000 +Test Ligand + + + 45 47 0 0 0 0 999 V2000 36.1312 5.0238 22.8745 C 0 0 0 0 0 0 35.3492 6.1234 22.4285 O 0 0 0 0 0 0 34.5144 6.6833 23.3611 C 0 0 0 0 0 0 @@ -569,32 +569,29 @@ Displayed atoms 26 27 1 0 0 0 27 45 1 0 0 0 M END +> <i_i_glide_confnum> +9 + > <i_i_glide_lignum> 1 -> <r_i_docking_score> --8.69162 +> <i_i_glide_posenum> +294 -> <r_i_glide_gscore> +> <r_i_docking_score> -8.69162 -> <r_i_glide_lipo> --2.92829 - -> <r_i_glide_hbond> --0.870172 - -> <r_i_glide_metal> --0 +> <r_i_glide_ecoul> +-14.7519 -> <r_i_glide_rewards> --0.764823 +> <r_i_glide_einternal> +5.89466 -> <r_i_glide_evdw> --48.432 +> <r_i_glide_emodel> +-97.7232 -> <r_i_glide_ecoul> --14.7519 +> <r_i_glide_energy> +-63.1839 > <r_i_glide_erotb> 0.517993 @@ -602,29 +599,32 @@ M END > <r_i_glide_esite> -0.0119369 -> <r_i_glide_emodel> --97.7232 +> <r_i_glide_evdw> +-48.432 -> <r_i_glide_energy> --63.1839 +> <r_i_glide_gscore> +-8.69162 -> <r_i_glide_einternal> -5.89466 +> <r_i_glide_hbond> +-0.870172 > <r_i_glide_ligand_efficiency> -0.321912 +> <r_i_glide_ligand_efficiency_ln> +-2.02327 + > <r_i_glide_ligand_efficiency_sa> -0.965735 -> <r_i_glide_ligand_efficiency_ln> --2.02327 +> <r_i_glide_lipo> +-2.92829 -> <i_i_glide_confnum> -9 +> <r_i_glide_metal> +-0 -> <i_i_glide_posenum> -294 +> <r_i_glide_rewards> +-0.764823 > <r_i_glide_rmsd> 0.463026 diff --git a/modules/io/tests/testfiles/sdf/empty_dataheader.sdf b/modules/io/tests/testfiles/sdf/empty_dataheader.sdf new file mode 100644 index 000000000..9de4a7b63 --- /dev/null +++ b/modules/io/tests/testfiles/sdf/empty_dataheader.sdf @@ -0,0 +1,48 @@ +Simple Ligand 1 + + Teststructure + 6 6 0 0 1 0 999 V2000 + 0.0000 0.0000 0.0000 N 0 3 0 0 0 0 + 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 + 0.0000 1.0000 0.0000 O 0 0 0 0 0 0 + 1.0000 1.0000 0.0000 S 0 0 0 0 0 0 + 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 + -1.0000 -1.0000 0.0000 Cl 0 0 0 0 0 0 + 1 2 2 0 0 0 + 1 3 1 0 0 0 + 1 6 1 0 0 0 + 2 4 1 0 0 0 + 3 4 1 0 0 0 + 4 5 3 0 0 0 +M END +> <> +1 + +> <prop_two> +-2 + +$$$$ +Simple Ligand 2 + + Teststructure + 6 6 0 0 1 0 999 V2000 + 0.0000 0.0000 0.0000 N 0 3 0 0 0 0 + 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 + 0.0000 1.0000 0.0000 O 0 0 0 0 0 0 + 1.0000 1.0000 0.0000 S 0 0 0 0 0 0 + 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 + -1.0000 -1.0000 0.0000 Cl 0 0 0 0 0 0 + 1 2 2 0 0 0 + 1 3 1 0 0 0 + 1 6 1 0 0 0 + 2 4 1 0 0 0 + 3 4 1 0 0 0 + 4 5 3 0 0 0 +M END +> <prop_one> +2 + +> <prop_two> +-4 + +$$$$ diff --git a/modules/io/tests/testfiles/sdf/multiple.sdf b/modules/io/tests/testfiles/sdf/multiple.sdf new file mode 100644 index 000000000..7570f2d4d --- /dev/null +++ b/modules/io/tests/testfiles/sdf/multiple.sdf @@ -0,0 +1,72 @@ +Simple Ligand 1 + + Teststructure + 6 6 0 0 1 0 999 V2000 + 0.0000 0.0000 0.0000 N 0 3 0 0 0 0 + 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 + 0.0000 1.0000 0.0000 O 0 0 0 0 0 0 + 1.0000 1.0000 0.0000 S 0 0 0 0 0 0 + 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 + -1.0000 -1.0000 0.0000 Cl 0 0 0 0 0 0 + 1 2 2 0 0 0 + 1 3 1 0 0 0 + 1 6 1 0 0 0 + 2 4 1 0 0 0 + 3 4 1 0 0 0 + 4 5 3 0 0 0 +M END +$$$$ +Simple Ligand 2 + + Teststructure + 6 6 0 0 1 0 999 V2000 + 0.0000 0.0000 0.0000 N 0 3 0 0 0 0 + 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 + 0.0000 1.0000 0.0000 O 0 0 0 0 0 0 + 1.0000 1.0000 0.0000 S 0 0 0 0 0 0 + 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 + -1.0000 -1.0000 0.0000 Cl 0 0 0 0 0 0 + 1 2 2 0 0 0 + 1 3 1 0 0 0 + 1 6 1 0 0 0 + 2 4 1 0 0 0 + 3 4 1 0 0 0 + 4 5 3 0 0 0 +M END +$$$$ +Simple Ligand 3 + + Teststructure + 6 6 0 0 1 0 999 V2000 + 0.0000 0.0000 0.0000 N 0 3 0 0 0 0 + 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 + 0.0000 1.0000 0.0000 O 0 0 0 0 0 0 + 1.0000 1.0000 0.0000 S 0 0 0 0 0 0 + 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 + -1.0000 -1.0000 0.0000 Cl 0 0 0 0 0 0 + 1 2 2 0 0 0 + 1 3 1 0 0 0 + 1 6 1 0 0 0 + 2 4 1 0 0 0 + 3 4 1 0 0 0 + 4 5 3 0 0 0 +M END +$$$$ +Simple Ligand 4 + + Teststructure + 6 6 0 0 1 0 999 V2000 + 0.0000 0.0000 0.0000 N 0 3 0 0 0 0 + 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 + 0.0000 1.0000 0.0000 O 0 0 0 0 0 0 + 1.0000 1.0000 0.0000 S 0 0 0 0 0 0 + 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 + -1.0000 -1.0000 0.0000 Cl 0 0 0 0 0 0 + 1 2 2 0 0 0 + 1 3 1 0 0 0 + 1 6 1 0 0 0 + 2 4 1 0 0 0 + 3 4 1 0 0 0 + 4 5 3 0 0 0 +M END +$$$$ diff --git a/modules/io/tests/testfiles/sdf/properties.sdf b/modules/io/tests/testfiles/sdf/properties.sdf new file mode 100644 index 000000000..edaf39129 --- /dev/null +++ b/modules/io/tests/testfiles/sdf/properties.sdf @@ -0,0 +1,48 @@ +Simple Ligand 1 + + Teststructure + 6 6 0 0 1 0 999 V2000 + 0.0000 0.0000 0.0000 N 0 3 0 0 0 0 + 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 + 0.0000 1.0000 0.0000 O 0 0 0 0 0 0 + 1.0000 1.0000 0.0000 S 0 0 0 0 0 0 + 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 + -1.0000 -1.0000 0.0000 Cl 0 0 0 0 0 0 + 1 2 2 0 0 0 + 1 3 1 0 0 0 + 1 6 1 0 0 0 + 2 4 1 0 0 0 + 3 4 1 0 0 0 + 4 5 3 0 0 0 +M END +> <prop_one> +1 + +> <prop_two> +-2 + +$$$$ +Simple Ligand 2 + + Teststructure + 6 6 0 0 1 0 999 V2000 + 0.0000 0.0000 0.0000 N 0 3 0 0 0 0 + 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 + 0.0000 1.0000 0.0000 O 0 0 0 0 0 0 + 1.0000 1.0000 0.0000 S 0 0 0 0 0 0 + 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 + -1.0000 -1.0000 0.0000 Cl 0 0 0 0 0 0 + 1 2 2 0 0 0 + 1 3 1 0 0 0 + 1 6 1 0 0 0 + 2 4 1 0 0 0 + 3 4 1 0 0 0 + 4 5 3 0 0 0 +M END +> <prop_one> +2 + +> <prop_two> +-4 + +$$$$ diff --git a/modules/io/tests/testfiles/sdf/simple.sdf b/modules/io/tests/testfiles/sdf/simple.sdf new file mode 100644 index 000000000..beeb1acdd --- /dev/null +++ b/modules/io/tests/testfiles/sdf/simple.sdf @@ -0,0 +1,18 @@ +Simple Ligand + + Teststructure + 6 6 0 0 1 0 999 V2000 + 0.0000 0.0000 0.0000 N 0 3 0 0 0 0 + 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 + 0.0000 1.0000 0.0000 O 0 0 0 0 0 0 + 1.0000 1.0000 0.0000 S 0 0 0 0 0 0 + 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 + -1.0000 -1.0000 0.0000 Cl 0 0 0 0 0 0 + 1 2 2 0 0 0 + 1 3 1 0 0 0 + 1 6 1 0 0 0 + 2 4 1 0 0 0 + 3 4 1 0 0 0 + 4 5 3 0 0 0 +M END +$$$$ diff --git a/modules/io/tests/testfiles/sdf/wrong_atomcount.sdf b/modules/io/tests/testfiles/sdf/wrong_atomcount.sdf new file mode 100644 index 000000000..ff9049fac --- /dev/null +++ b/modules/io/tests/testfiles/sdf/wrong_atomcount.sdf @@ -0,0 +1,18 @@ +Simple Ligand + + Teststructure + i 6 0 0 1 0 999 V2000 + 0.0000 0.0000 0.0000 N 0 3 0 0 0 0 + 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 + 0.0000 1.0000 0.0000 O 0 0 0 0 0 0 + 1.0000 1.0000 0.0000 S 0 0 0 0 0 0 + 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 + -1.0000 -1.0000 0.0000 Cl 0 0 0 0 0 0 + 1 2 2 0 0 0 + 1 3 1 0 0 0 + 1 6 1 0 0 0 + 2 4 1 0 0 0 + 3 4 1 0 0 0 + 4 5 3 0 0 0 +M END +$$$$ diff --git a/modules/io/tests/testfiles/sdf/wrong_atomlinelength.sdf b/modules/io/tests/testfiles/sdf/wrong_atomlinelength.sdf new file mode 100644 index 000000000..42f30f1a5 --- /dev/null +++ b/modules/io/tests/testfiles/sdf/wrong_atomlinelength.sdf @@ -0,0 +1,18 @@ +Simple Ligand + + Teststructure + 6 6 0 0 1 0 999 V2000 + 0.0000 0.0000 0.0000 N 0 3 0 0 0 0 + 1.0000 0.0000 0.0000 C 0 0 + 0.0000 1.0000 0.0000 O 0 0 0 0 0 0 + 1.0000 1.0000 0.0000 S 0 0 0 0 0 0 + 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 + -1.0000 -1.0000 0.0000 Cl 0 0 0 0 0 0 + 1 2 2 0 0 0 + 1 3 1 0 0 0 + 1 6 1 0 0 0 + 2 4 1 0 0 0 + 3 4 1 0 0 0 + 4 5 3 0 0 0 +M END +$$$$ diff --git a/modules/io/tests/testfiles/sdf/wrong_atompos.sdf b/modules/io/tests/testfiles/sdf/wrong_atompos.sdf new file mode 100644 index 000000000..50d5268a0 --- /dev/null +++ b/modules/io/tests/testfiles/sdf/wrong_atompos.sdf @@ -0,0 +1,18 @@ +Simple Ligand + + Teststructure + 6 6 0 0 1 0 999 V2000 + 0.0000 0.0000 0.0000 N 0 3 0 0 0 0 + 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 +0.0000 1.0000 0.0000 O 0 0 0 0 0 0 + 1.0000 1.0000 0.0000 S 0 0 0 0 0 0 + 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 + -1.0000 -1.0000 0.0000 Cl 0 0 0 0 0 0 + 1 2 2 0 0 0 + 1 3 1 0 0 0 + 1 6 1 0 0 0 + 2 4 1 0 0 0 + 3 4 1 0 0 0 + 4 5 3 0 0 0 +M END +$$$$ diff --git a/modules/io/tests/testfiles/sdf/wrong_bondatomnumber.sdf b/modules/io/tests/testfiles/sdf/wrong_bondatomnumber.sdf new file mode 100644 index 000000000..590827c4d --- /dev/null +++ b/modules/io/tests/testfiles/sdf/wrong_bondatomnumber.sdf @@ -0,0 +1,18 @@ +Simple Ligand + + Teststructure + 6 6 0 0 1 0 999 V2000 + 0.0000 0.0000 0.0000 N 0 3 0 0 0 0 + 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 + 0.0000 1.0000 0.0000 O 0 0 0 0 0 0 + 1.0000 1.0000 0.0000 S 0 0 0 0 0 0 + 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 + -1.0000 -1.0000 0.0000 Cl 0 0 0 0 0 0 + 1 2 2 0 0 0 + 1 3 1 0 0 0 + 1 8 1 0 0 0 + 2 4 1 0 0 0 + 3 4 1 0 0 0 + 4 5 3 0 0 0 +M END +$$$$ diff --git a/modules/io/tests/testfiles/sdf/wrong_bondcount.sdf b/modules/io/tests/testfiles/sdf/wrong_bondcount.sdf new file mode 100644 index 000000000..3d6194d1b --- /dev/null +++ b/modules/io/tests/testfiles/sdf/wrong_bondcount.sdf @@ -0,0 +1,18 @@ +Simple Ligand + + Teststructure + 6 i 0 0 1 0 999 V2000 + 0.0000 0.0000 0.0000 N 0 3 0 0 0 0 + 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 + 0.0000 1.0000 0.0000 O 0 0 0 0 0 0 + 1.0000 1.0000 0.0000 S 0 0 0 0 0 0 + 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 + -1.0000 -1.0000 0.0000 Cl 0 0 0 0 0 0 + 1 2 2 0 0 0 + 1 3 1 0 0 0 + 1 6 1 0 0 0 + 2 4 1 0 0 0 + 3 4 1 0 0 0 + 4 5 3 0 0 0 +M END +$$$$ diff --git a/modules/io/tests/testfiles/sdf/wrong_bondlinelength.sdf b/modules/io/tests/testfiles/sdf/wrong_bondlinelength.sdf new file mode 100644 index 000000000..5be46a393 --- /dev/null +++ b/modules/io/tests/testfiles/sdf/wrong_bondlinelength.sdf @@ -0,0 +1,18 @@ +Simple Ligand + + Teststructure + 6 6 0 0 1 0 999 V2000 + 0.0000 0.0000 0.0000 N 0 3 0 0 0 0 + 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 + 0.0000 1.0000 0.0000 O 0 0 0 0 0 0 + 1.0000 1.0000 0.0000 S 0 0 0 0 0 0 + 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 + -1.0000 -1.0000 0.0000 Cl 0 0 0 0 0 0 + 1 2 2 + 1 3 1 0 0 0 + 1 6 1 0 0 0 + 2 4 1 0 0 0 + 3 4 1 0 0 0 + 4 5 3 0 0 0 +M END +$$$$ diff --git a/modules/io/tests/testfiles/sdf/wrong_bondtype.sdf b/modules/io/tests/testfiles/sdf/wrong_bondtype.sdf new file mode 100644 index 000000000..432c10464 --- /dev/null +++ b/modules/io/tests/testfiles/sdf/wrong_bondtype.sdf @@ -0,0 +1,18 @@ +Simple Ligand + + Teststructure + 6 6 0 0 1 0 999 V2000 + 0.0000 0.0000 0.0000 N 0 3 0 0 0 0 + 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 + 0.0000 1.0000 0.0000 O 0 0 0 0 0 0 + 1.0000 1.0000 0.0000 S 0 0 0 0 0 0 + 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 + -1.0000 -1.0000 0.0000 Cl 0 0 0 0 0 0 + 1 2 2 0 0 0 + 1 3 1 0 0 0 + 1 6 -1 0 0 0 + 2 4 1 0 0 0 + 3 4 1 0 0 0 + 4 5 3 0 0 0 +M END +$$$$ diff --git a/modules/io/tests/testfiles/sdf/wrong_charge.sdf b/modules/io/tests/testfiles/sdf/wrong_charge.sdf new file mode 100644 index 000000000..01dba009e --- /dev/null +++ b/modules/io/tests/testfiles/sdf/wrong_charge.sdf @@ -0,0 +1,18 @@ +Simple Ligand + + Teststructure + 6 6 0 0 1 0 999 V2000 + 0.0000 0.0000 0.0000 N 0 3 0 0 0 0 + 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 + 0.0000 1.0000 0.0000 O 0 0 0 0 0 0 + 1.0000 1.0000 0.0000 S 0 i 0 0 0 0 + 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 + -1.0000 -1.0000 0.0000 Cl 0 0 0 0 0 0 + 1 2 2 0 0 0 + 1 3 1 0 0 0 + 1 6 1 0 0 0 + 2 4 1 0 0 0 + 3 4 1 0 0 0 + 4 5 3 0 0 0 +M END +$$$$ diff --git a/modules/io/tests/testfiles/sdf/wrong_dataheader.sdf b/modules/io/tests/testfiles/sdf/wrong_dataheader.sdf new file mode 100644 index 000000000..b895448e6 --- /dev/null +++ b/modules/io/tests/testfiles/sdf/wrong_dataheader.sdf @@ -0,0 +1,48 @@ +Simple Ligand 1 + + Teststructure + 6 6 0 0 1 0 999 V2000 + 0.0000 0.0000 0.0000 N 0 3 0 0 0 0 + 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 + 0.0000 1.0000 0.0000 O 0 0 0 0 0 0 + 1.0000 1.0000 0.0000 S 0 0 0 0 0 0 + 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 + -1.0000 -1.0000 0.0000 Cl 0 0 0 0 0 0 + 1 2 2 0 0 0 + 1 3 1 0 0 0 + 1 6 1 0 0 0 + 2 4 1 0 0 0 + 3 4 1 0 0 0 + 4 5 3 0 0 0 +M END +> prop_one> +1 + +> <prop_two> +-2 + +$$$$ +Simple Ligand 2 + + Teststructure + 6 6 0 0 1 0 999 V2000 + 0.0000 0.0000 0.0000 N 0 3 0 0 0 0 + 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 + 0.0000 1.0000 0.0000 O 0 0 0 0 0 0 + 1.0000 1.0000 0.0000 S 0 0 0 0 0 0 + 2.0000 2.0000 0.0000 C 0 0 0 0 0 0 + -1.0000 -1.0000 0.0000 Cl 0 0 0 0 0 0 + 1 2 2 0 0 0 + 1 3 1 0 0 0 + 1 6 1 0 0 0 + 2 4 1 0 0 0 + 3 4 1 0 0 0 + 4 5 3 0 0 0 +M END +> <prop_one> +2 + +> <prop_two> +-4 + +$$$$ -- GitLab