From 361753cfda4f9627ef22df4db3cc3da22d54e6a6 Mon Sep 17 00:00:00 2001 From: ansgar <ansgar@5a81b35b-ba03-0410-adc8-b2c5c5119f08> Date: Tue, 20 Apr 2010 05:28:13 +0000 Subject: [PATCH] refactored PDB flags functionality into global state removed sequential atom list functionality (superseded by atom index) added atom index (automatically incremented during creation and loading) coord group uses index sorted atom list instead on relying on the atom order in entity added coordinate format mae import added various debug output git-svn-id: https://dng.biozentrum.unibas.ch/svn/openstructure/trunk@2056 5a81b35b-ba03-0410-adc8-b2c5c5119f08 --- modules/io/pymod/__init__.py | 36 +- modules/io/pymod/export_pdb_io.cc | 32 +- modules/io/pymod/wrap_io.cc | 4 + modules/io/src/io_manager.cc | 2 + modules/io/src/mol/CMakeLists.txt | 25 +- modules/io/src/mol/dcd_io.cc | 32 +- modules/io/src/mol/entity_io_crd_handler.cc | 3 - modules/io/src/mol/entity_io_mae_handler.cc | 345 ++++++++++++++++++++ modules/io/src/mol/entity_io_mae_handler.hh | 83 +++++ modules/io/src/mol/entity_io_pdb_handler.cc | 7 +- modules/io/src/mol/pdb_io.hh | 41 ++- modules/io/src/mol/pdb_reader.cc | 70 ++-- modules/io/src/mol/pdb_reader.hh | 15 +- modules/io/src/mol/pdb_writer.cc | 30 +- modules/io/src/mol/pdb_writer.hh | 3 - modules/mol/base/pymod/export_atom.cc | 2 + modules/mol/base/src/atom_base.cc | 6 + modules/mol/base/src/atom_base.hh | 5 +- modules/mol/base/src/coord_frame.hh | 9 +- modules/mol/base/src/coord_source.cc | 5 +- modules/mol/base/src/impl/atom_impl.cc | 6 +- modules/mol/base/src/impl/atom_impl.hh | 8 +- modules/mol/base/src/impl/entity_impl.cc | 7 +- modules/mol/base/src/impl/entity_impl.hh | 3 + modules/mol/base/src/in_mem_coord_source.cc | 4 +- modules/mol/base/tests/test_entity.cc | 2 + 26 files changed, 628 insertions(+), 157 deletions(-) create mode 100755 modules/io/src/mol/entity_io_mae_handler.cc create mode 100755 modules/io/src/mol/entity_io_mae_handler.hh diff --git a/modules/io/pymod/__init__.py b/modules/io/pymod/__init__.py index 82ab97c27..996ff1ffc 100644 --- a/modules/io/pymod/__init__.py +++ b/modules/io/pymod/__init__.py @@ -52,21 +52,27 @@ def LoadPDB(filename, restrict_chains="", no_hetatms=False, flags|=PDB.NO_HETATMS if join_spread_atom_records: flags|=PDB.JOIN_SPREAD_ATOM_RECORDS - reader.SetFlags(flags) - if load_multi: - ent_list=[] - while reader.HasNext(): - ent=mol.CreateEntity() - reader.Import(ent, restrict_chains) - conop_inst.ConnectAll(builder, ent, 0) - ent_list.append(ent) - return ent_list - else: - ent=mol.CreateEntity() - if reader.HasNext(): - reader.Import(ent, restrict_chains) - conop_inst.ConnectAll(builder, ent, 0) - return ent + try: + PDB.PushFlags(PDB.Flags() | flags) + if load_multi: + ent_list=[] + while reader.HasNext(): + ent=mol.CreateEntity() + reader.Import(ent, restrict_chains) + conop_inst.ConnectAll(builder, ent, 0) + ent_list.append(ent) + PDB.PopFlags() + return ent_list + else: + ent=mol.CreateEntity() + if reader.HasNext(): + reader.Import(ent, restrict_chains) + conop_inst.ConnectAll(builder, ent, 0) + PDB.PopFlags() + return ent + except: + PDB.PopFlags() + raise def SavePDB(models, filename): """ diff --git a/modules/io/pymod/export_pdb_io.cc b/modules/io/pymod/export_pdb_io.cc index 6cc80b813..fe2a3a75f 100644 --- a/modules/io/pymod/export_pdb_io.cc +++ b/modules/io/pymod/export_pdb_io.cc @@ -31,26 +31,38 @@ BOOST_PYTHON_FUNCTION_OVERLOADS(load_PDB_ov, LoadPDB, 1, 2) void (PDBWriter::*write_a)(const mol::EntityHandle&)=&PDBWriter::Write; void (PDBWriter::*write_b)(const mol::EntityView&)=&PDBWriter::Write; + +namespace { + void push_flags(unsigned int x) {PDB::PushFlags(x);} + unsigned int flags() {return PDB::Flags();} + void pop_flags() {PDB::PopFlags();} +} + void export_pdb_io() { - enum_<PDB::Type>("PDB") - .value("NO_HETATMS", PDB::NO_HETATMS) - .value("SKIP_FAULTY_RECORDS", PDB::SKIP_FAULTY_RECORDS) - .value("WRITE_MULTIPLE_MODELS", PDB::WRITE_MULTIPLE_MODELS) - .value("JOIN_SPREAD_ATOM_RECORDS", PDB::JOIN_SPREAD_ATOM_RECORDS) - .value("SEQUENTIAL_ATOM_IMPORT", PDB::SEQUENTIAL_ATOM_IMPORT) - ; + { + scope pdb_scope=class_<PDB>("PDB",no_init) + .def("PushFlags",&PDB::PushFlags) + .staticmethod("PushFlags") + .def("Flags",&PDB::Flags) + .staticmethod("Flags") + .def("PopFlags",&PDB::PopFlags) + .staticmethod("PopFlags") + ; + pdb_scope.attr("NO_HETATMS")=PDB::NO_HETATMS; + pdb_scope.attr("SKIP_FAULTY_RECORDS")=PDB::SKIP_FAULTY_RECORDS; + pdb_scope.attr("WRITE_MULTIPLE_MODELS")=PDB::WRITE_MULTIPLE_MODELS; + pdb_scope.attr("JOIN_SPREAD_ATOM_RECORDS")=PDB::JOIN_SPREAD_ATOM_RECORDS; + } + class_<PDBReader, boost::noncopyable>("PDBReader", init<String>()) .def("HasNext", &PDBReader::HasNext) .def("Import", &PDBReader::Import, X_import(args("entity", "restrict_chains"))) - .def("SetFlags", &PDBReader::SetFlags) - .def("GetSequentialAtoms", &PDBReader::GetSequentialAtoms) ; class_<PDBWriter, boost::noncopyable>("PDBWriter", init<String>()) .def("Write", write_a) .def("Write", write_b) - .def("SetFlags", &PDBWriter::SetFlags) ; } diff --git a/modules/io/pymod/wrap_io.cc b/modules/io/pymod/wrap_io.cc index 79920189e..b04d3ac78 100644 --- a/modules/io/pymod/wrap_io.cc +++ b/modules/io/pymod/wrap_io.cc @@ -28,6 +28,7 @@ using namespace boost::python; #include <ost/io/seq/save.hh> #include <ost/io/mol/entity_io_pdb_handler.hh> #include <ost/io/mol/entity_io_crd_handler.hh> +#include <ost/io/mol/entity_io_mae_handler.hh> #include <ost/io/mol/entity_io_sdf_handler.hh> #include <ost/io/mol/pdb_reader.hh> #include <ost/io/mol/dcd_io.hh> @@ -120,6 +121,9 @@ BOOST_PYTHON_MODULE(_io) def("LoadCHARMMTraj",load_dcd3); def("LoadCHARMMTraj",load_dcd4); def("SaveCHARMMTraj",SaveCHARMMTraj,save_charmm_trj_ov()); + + def("LoadMAE", &LoadMAE); + export_pdb_io(); #if OST_IMG_ENABLED export_map_io(); diff --git a/modules/io/src/io_manager.cc b/modules/io/src/io_manager.cc index 23ab54bd2..b03169d8c 100644 --- a/modules/io/src/io_manager.cc +++ b/modules/io/src/io_manager.cc @@ -20,6 +20,7 @@ #include <ost/io/mol/entity_io_pdb_handler.hh> #include <ost/io/mol/entity_io_crd_handler.hh> #include <ost/io/mol/entity_io_sdf_handler.hh> +#include <ost/io/mol/entity_io_mae_handler.hh> #include <ost/io/seq/fasta_io_handler.hh> #include <ost/io/seq/promod_io_handler.hh> #include <ost/io/mol/surface_io_msms_handler.hh> @@ -43,6 +44,7 @@ IOManager::IOManager() RegisterFactory(EntityIOHandlerFactoryBaseP(new EntityIOPDBHandlerFactory)); RegisterFactory(EntityIOHandlerFactoryBaseP(new EntityIOCRDHandlerFactory)); RegisterFactory(EntityIOHandlerFactoryBaseP(new EntityIOSDFHandlerFactory)); + RegisterFactory(EntityIOHandlerFactoryBaseP(new EntityIOMAEHandlerFactory)); RegisterFactory(SequenceIOHandlerFactoryBasePtr(new FastaIOHandlerFactory)); RegisterFactory(SequenceIOHandlerFactoryBasePtr(new ClustalIOHandlerFactory)); RegisterFactory(SequenceIOHandlerFactoryBasePtr(new PromodIOHandlerFactory)); diff --git a/modules/io/src/mol/CMakeLists.txt b/modules/io/src/mol/CMakeLists.txt index b3fd346b6..772a0c89c 100644 --- a/modules/io/src/mol/CMakeLists.txt +++ b/modules/io/src/mol/CMakeLists.txt @@ -1,32 +1,35 @@ set(OST_IO_MOL_SOURCES +dcd_io.cc entity_io_crd_handler.cc -pdb_reader.cc +entity_io_mae_handler.cc entity_io_pdb_handler.cc -pdb_writer.cc entity_io_sdf_handler.cc -save_entity.cc load_entity.cc -surface_io_msms_handler.cc load_surface.cc -dcd_io.cc +pdb_io.cc +pdb_reader.cc +pdb_writer.cc +save_entity.cc star_parser.cc +surface_io_msms_handler.cc PARENT_SCOPE ) set(OST_IO_MOL_HEADERS -star_parser.hh dcd_io.hh +entity_io_handler.hh entity_io_crd_handler.hh +entity_io_mae_handler.hh +entity_io_pdb_handler.hh +entity_io_sdf_handler.hh +load_entity.hh +load_surface.hh pdb_io.hh -entity_io_handler.hh pdb_reader.hh -entity_io_pdb_handler.hh pdb_writer.hh -entity_io_sdf_handler.hh save_entity.hh -load_entity.hh surface_io_handler.hh -load_surface.hh +star_parser.hh surface_io_msms_handler.hh PARENT_SCOPE ) diff --git a/modules/io/src/mol/dcd_io.cc b/modules/io/src/mol/dcd_io.cc index efe9f1dfb..6fd936c42 100644 --- a/modules/io/src/mol/dcd_io.cc +++ b/modules/io/src/mol/dcd_io.cc @@ -22,6 +22,8 @@ */ #include <fstream> +#include <algorithm> + #include <boost/iostreams/filter/gzip.hpp> #include <boost/filesystem/convenience.hpp> @@ -58,12 +60,20 @@ struct DCDHeader { int t_atom_count,f_atom_count, atom_count; }; -mol::CoordGroupHandle load_dcd(const mol::AtomHandleList& alist, +bool less_index(const mol::AtomHandle& a1, const mol::AtomHandle& a2) +{ + return a1.GetIndex()<a2.GetIndex(); +} + +mol::CoordGroupHandle load_dcd(const mol::AtomHandleList& alist2, const String& trj_fn, unsigned int stride) { Profile profile_load("LoadCHARMMTraj"); + mol::AtomHandleList alist(alist2); + std::sort(alist.begin(),alist.end(),less_index); + bool gap_flag = true; boost::filesystem::path trj_f(trj_fn); @@ -121,7 +131,7 @@ mol::CoordGroupHandle load_dcd(const mol::AtomHandleList& alist, header.f_atom_count=header.icntrl[8]; header.atom_count=header.t_atom_count-header.f_atom_count; - LOGN_MESSAGE("LoadCHARMMTraj: " << header.num << " trajectories with " + LOGN_DEBUG("LoadCHARMMTraj: " << header.num << " trajectories with " << header.atom_count << " atoms (" << header.f_atom_count << " fixed) each"); @@ -136,7 +146,8 @@ mol::CoordGroupHandle load_dcd(const mol::AtomHandleList& alist, std::vector<geom::Vec3> clist(header.t_atom_count); std::vector<float> xlist(header.t_atom_count); - for(int i=0;i<header.num;++i) { + int i=0; + for(;i<header.num;++i) { if(skip_flag) ff.seekg(14*4,std::ios_base::cur); // read each frame if(!ff) { @@ -169,9 +180,9 @@ mol::CoordGroupHandle load_dcd(const mol::AtomHandleList& alist, for(uint j=0;j<clist.size();++j) { clist[j].SetZ(xlist[j]); } - if(i%stride) { - cg.AddFrame(clist); - } + + cg.AddFrame(clist); + } ff.get(); @@ -179,6 +190,9 @@ mol::CoordGroupHandle load_dcd(const mol::AtomHandleList& alist, LOGN_VERBOSE("LoadCHARMMTraj: unexpected trailing file data, bytes read: " << ff.tellg()); } + + LOGN_VERBOSE("Loaded " << cg.GetFrameCount() << " frames with " << cg.GetAtomCount() << " atoms each"); + return cg; } @@ -188,6 +202,7 @@ mol::CoordGroupHandle LoadCHARMMTraj(const String& crd_fn, const String& trj_fn, unsigned int stride) { + if(stride==0) stride=1; boost::filesystem::path crd_f(crd_fn); // first the coordinate reference file @@ -197,21 +212,18 @@ mol::CoordGroupHandle LoadCHARMMTraj(const String& crd_fn, std::vector<mol::AtomHandle> alist; if(boost::filesystem::extension(crd_f)==".pdb") { PDBReader reader(crd_f); - reader.SetFlags(PDB::SEQUENTIAL_ATOM_IMPORT); LOGN_MESSAGE("importing coordinate data"); reader.Import(ent); - alist = reader.GetSequentialAtoms(); } else if (boost::filesystem::extension(crd_f)==".crd") { CRDReader reader(crd_f); LOGN_MESSAGE("importing coordinate data"); reader.Import(ent); - alist = reader.GetSequentialAtoms(); } else { throw(IOException("unsupported coordinate file format")); } conop::Conopology::Instance().ConnectAll(builder,ent); - return load_dcd(alist,trj_fn,stride); + return load_dcd(ent.GetAtomList(),trj_fn,stride); } diff --git a/modules/io/src/mol/entity_io_crd_handler.cc b/modules/io/src/mol/entity_io_crd_handler.cc index ce4a1679b..cfbb7efcc 100644 --- a/modules/io/src/mol/entity_io_crd_handler.cc +++ b/modules/io/src/mol/entity_io_crd_handler.cc @@ -43,9 +43,6 @@ namespace ost { namespace io { using boost::format; -String FORMAT_NAME_STRING; -String FORMAT_DESCRIPTION_STRING; - CRDReader::CRDReader(const boost::filesystem::path& loc): sequential_atom_list_(), curr_chain_(), diff --git a/modules/io/src/mol/entity_io_mae_handler.cc b/modules/io/src/mol/entity_io_mae_handler.cc new file mode 100755 index 000000000..e41fa029c --- /dev/null +++ b/modules/io/src/mol/entity_io_mae_handler.cc @@ -0,0 +1,345 @@ +//------------------------------------------------------------------------------ +// 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: Ansgar Philippsen + */ +#include <iostream> +#include <sstream> +#include <iomanip> +#include <vector> +#include <string> + +#include <ctype.h> + +#include <boost/iostreams/filter/gzip.hpp> +#include <boost/filesystem/convenience.hpp> +#include <boost/algorithm/string.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/format.hpp> +#include <boost/regex.hpp> + +#include <ost/log.hh> +#include <ost/conop/conop.hh> +#include <ost/mol/xcs_editor.hh> +#include <ost/profile.hh> + +#include <ost/io/io_exception.hh> +#include <ost/io/swap_util.hh> + +#include "entity_io_mae_handler.hh" + +namespace ost { namespace io { + +using boost::format; + + namespace { + + std::vector<std::string> tokenize(const std::string& line) + { + std::vector<std::string> nrvo; + bool in_string=false; + int p0=0; + for(int p1=1;p1<line.size();++p1) { + if(in_string) { + if(line[p1]=='"') { + in_string=false; + nrvo.push_back(line.substr(p0,p1-p0)); + ++p1; + p0=p1; + while(isspace(line[p1]) and p1<line.size()) {++p0;++p1;} + --p0; --p1; + } + } else { + if(isspace(line[p1])) { + nrvo.push_back(line.substr(p0+1,p1-p0-1)); + ++p1; + p0=p1; + while(isspace(line[p1]) and p1<line.size()) {++p0;++p1;} + --p0; --p1; + } else if(line[p1]=='"') { + in_string=true; + p0=p1+1; + } + } + } + return nrvo; + } + + } + +MAEReader::MAEReader(const boost::filesystem::path& loc): + curr_chain_(), + curr_residue_(), + chain_count_(0), + residue_count_(0), + atom_count_(0), + infile_(loc), + in_() +{ + if (boost::iequals(".gz", boost::filesystem::extension(loc))) { + in_.push(boost::iostreams::gzip_decompressor()); + } + in_.push(infile_); + if(!infile_) throw IOException("could not open "+loc.string()); +} + +void MAEReader::Import(mol::EntityHandle& ent) +{ + Profile profile_import("MAEReader::Import"); + + static const boost::regex r_ct_block("f_m_ct +\\{"); + static const boost::regex r_atom_block("m_atom\\[.*\\] +\\{"); + static const boost::regex r_delim(":::"); + + String line; + bool in_ct_block=false; + bool in_atom_block=false; + bool parsing_atoms=false; + bool debug=true; + std::vector<std::string> prop_list; + int i_atom_name=-1; + int i_atom_xpos=-1; + int i_atom_ypos=-1; + int i_atom_zpos=-1; + int i_res_name=-1; + int i_res_num=-1; + int i_chain_name=-1; + + mol::XCSEditor editor=ent.RequestXCSEditor(mol::BUFFERED_EDIT); + + while(std::getline(in_,line)) { + line = boost::trim_copy(line); + if(in_ct_block) { + if(in_atom_block) { + if(parsing_atoms) { + if(boost::regex_match(line,r_delim)) { + std::cerr << "stopping atom parsing" << std::endl; + parsing_atoms=false; + } else { + // parsing atom line + std::vector<std::string> tokens=tokenize(line); + add_atom(ent,editor, + tokens[i_atom_name], + tokens[i_atom_xpos], + tokens[i_atom_ypos], + tokens[i_atom_zpos], + tokens[i_res_name], + tokens[i_res_num], + tokens[i_chain_name]); + } + } else { // not parsing atoms + if(boost::regex_match(line,r_delim)) { + if(i_atom_name==-1 || + i_atom_xpos==-1 || + i_atom_ypos==-1 || + i_atom_zpos==-1 || + i_res_name==-1 || + i_res_num==-1 || + i_chain_name==-1) { + throw IOException("missing atom prop"); + } + std::cerr << "starting atom parsing" << std::endl; + parsing_atoms=true; + } else if(line[0]=='}') { + std::cerr << "exiting atom block" << std::endl; + in_atom_block=false; + } else { + // parsing property line + int pid=prop_list.size(); + prop_list.push_back(line); + std::cerr << "found property '" << prop_list.back() << "'" << std::endl; + if(line=="s_m_pdb_atom_name") i_atom_name=pid; + else if(line=="r_m_x_coord") i_atom_xpos=pid; + else if(line=="r_m_y_coord") i_atom_ypos=pid; + else if(line=="r_m_z_coord") i_atom_zpos=pid; + else if(line=="s_m_pdb_residue_name") i_res_name=pid; + else if(line=="i_m_residue_number") i_res_num=pid; + else if(line=="s_m_pdb_segment_name") i_chain_name=pid; + } + } + } else { // not in atom block + if(boost::regex_match(line,r_atom_block)) { + std::cerr << "entering atom block" << std::endl; + in_atom_block=true; + } else if(line[0]=='}') { + std::cerr << "exiting ct block" << std::endl; + in_ct_block=false; + } + } + } else { // not in ct block + if(boost::regex_match(line,r_ct_block)) { + std::cerr << "entering ct block" << std::endl; + in_ct_block=true; + } + } + } + + LOGN_MESSAGE("imported " << chain_count_ << " chains, " << residue_count_ + << " residues, " << atom_count_ << " atoms"); +} + + +void MAEReader::add_atom(mol::EntityHandle ent, + mol::XCSEditor& editor, + const std::string& aname, + const std::string& s_axpos, + const std::string& s_aypos, + const std::string& s_azpos, + const std::string& rname, + const std::string& s_rnum, + const std::string& cname) +{ + std::string ele = aname.substr(0,1); + int irnum = boost::lexical_cast<int>(s_rnum); + geom::Vec3 apos(boost::lexical_cast<Real>(s_axpos), + boost::lexical_cast<Real>(s_aypos), + boost::lexical_cast<Real>(s_azpos)); + + mol::ResidueKey rkey(rname); + + // some postprocessing + LOGN_TRACE( "cname: [" << cname << "]" ); + + mol::ResNum rnum(irnum); + + // determine chain and residue update + bool update_chain=false; + bool update_residue=false; + if(!curr_chain_) { + update_chain=true; + update_residue=true; + } else if(curr_chain_.GetName()!=cname) { + update_chain=true; + update_residue=true; + } + + if(!curr_residue_) { + update_residue=true; + } else if(curr_residue_.GetNumber()!=rnum) { + update_residue=true; + } + + if(update_chain) { + if (!(curr_chain_=ent.FindChain(cname))) { + LOGN_DUMP("new chain " << cname); + curr_chain_=editor.InsertChain(cname); + ++chain_count_; + } + } + + if(update_residue) { + if (!(curr_residue_=curr_chain_.FindResidue(rnum))) { + LOGN_DUMP("new residue " << rkey << " " << rnum); + curr_residue_=editor.AppendResidue(curr_chain_, rkey, rnum); + assert(curr_residue_.IsValid()); + ++residue_count_; + } + } + + // finally add atom + LOGN_DUMP("adding atom " << aname << " (" << ele << ") @" << apos); + mol::AtomProp aprop; + aprop.element=ele; + aprop.radius=conop::Conopology::Instance().GetDefaultAtomRadius(ele); + aprop.is_hetatm=false; + aprop.b_factor=0.0; + aprop.occupancy=1.0; + mol::AtomHandle ah = editor.InsertAtom(curr_residue_, aname, apos, aprop); +} + + + + +bool EntityIOMAEHandler::RequiresBuilder() const +{ + return true; +} + +void EntityIOMAEHandler::Import(mol::EntityHandle& ent, + const boost::filesystem::path& loc) +{ + MAEReader reader(loc); + reader.Import(ent); +} + +void EntityIOMAEHandler::Export(const mol::EntityView& ent, + const boost::filesystem::path& loc) const +{ +} + +namespace { + +bool mae_handler_is_responsible_for(const boost::filesystem::path& loc, + const String& type) { + if(type=="auto") { + String match_suf_string=loc.string(); + std::transform(match_suf_string.begin(),match_suf_string.end(),match_suf_string.begin(),tolower); + if( detail::FilenameEndsWith(match_suf_string,".mae") || detail::FilenameEndsWith(match_suf_string,".mae.gz") ) { + return true; + } + } else if(type=="mae") { + return true; + } + + return false; +} + +} + +bool EntityIOMAEHandler::ProvidesImport(const boost::filesystem::path& loc, + const String& type) +{ + return mae_handler_is_responsible_for(loc, type); +} + +bool EntityIOMAEHandler::ProvidesExport(const boost::filesystem::path& loc, + const String& type) +{ + return false; +} + +mol::EntityHandle LoadMAE(const String& file_name) +{ + Profile profile_load("LoadMAE"); + conop::BuilderP builder = conop::Conopology::Instance().GetBuilder(); + MAEReader reader(file_name); + mol::EntityHandle ent=mol::CreateEntity(); + mol::XCSEditor editor=ent.RequestXCSEditor(mol::BUFFERED_EDIT); + reader.Import(ent); + conop::Conopology::Instance().ConnectAll(builder,ent); + return ent; +} + + +void EntityIOMAEHandler::Import(mol::EntityHandle& ent, + std::istream& stream) +{ + throw IOException("MAE format does not support import from stream"); +} + + +void EntityIOMAEHandler::Export(const mol::EntityView& ent, + std::ostream& stream) const +{ + throw IOException("MAE format does not support export to stream"); +} + +}} // ns + + diff --git a/modules/io/src/mol/entity_io_mae_handler.hh b/modules/io/src/mol/entity_io_mae_handler.hh new file mode 100755 index 000000000..3924bd143 --- /dev/null +++ b/modules/io/src/mol/entity_io_mae_handler.hh @@ -0,0 +1,83 @@ +//------------------------------------------------------------------------------ +// 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_IO_ENTITY_IO_PLUGIN_MAE_H +#define OST_IO_ENTITY_IO_PLUGIN_MAE_H + +#include <ost/io/mol/entity_io_handler.hh> + +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/filesystem/fstream.hpp> + +namespace ost { namespace io { + +class DLLEXPORT_OST_IO MAEReader { +public: + MAEReader(const boost::filesystem::path& loc); + + void Import(mol::EntityHandle& ent); + +private: + + void add_atom(mol::EntityHandle ent, + mol::XCSEditor& editor,const std::string& s_aname, + const std::string& s_axpos, + const std::string& s_aypos, + const std::string& s_azpos, + const std::string& s_rname, + const std::string& s_rnum, + const std::string& s_cname); + + mol::ChainHandle curr_chain_; + mol::ResidueHandle curr_residue_; + int chain_count_; + int residue_count_; + int atom_count_; + boost::filesystem::ifstream infile_; + boost::iostreams::filtering_stream<boost::iostreams::input> in_; +}; + +class DLLEXPORT_OST_IO EntityIOMAEHandler: public EntityIOHandler { +public: + virtual void Import(mol::EntityHandle& ent, const boost::filesystem::path& loc); + + virtual void Export(const mol::EntityView& ent, + const boost::filesystem::path& loc) const; + + virtual void Import(mol::EntityHandle& ent, std::istream& stream); + + virtual void Export(const mol::EntityView& ent, std::ostream& stream) const; + + static bool ProvidesImport(const boost::filesystem::path& loc, + const String& format="auto"); + static bool ProvidesExport(const boost::filesystem::path& loc, + const String& format="auto"); + virtual bool RequiresBuilder() const; + + static String GetFormatName() { return String("Mae"); } + static String GetFormatDescription() { return String("MAEstro coordinate file format"); } +}; + + +typedef EntityIOHandlerFactory<EntityIOMAEHandler> EntityIOMAEHandlerFactory; + +mol::EntityHandle DLLEXPORT_OST_IO LoadMAE(const String& file_name); + +}} // ns + +#endif diff --git a/modules/io/src/mol/entity_io_pdb_handler.cc b/modules/io/src/mol/entity_io_pdb_handler.cc index ca64835e7..99b8ea495 100644 --- a/modules/io/src/mol/entity_io_pdb_handler.cc +++ b/modules/io/src/mol/entity_io_pdb_handler.cc @@ -50,9 +50,12 @@ void EntityIOPDBHandler::Export(const mol::EntityView& ent, { PDBWriter writer(loc); if (boost::iequals(boost::filesystem::extension(loc), ".pqr")) { - writer.SetFlags(PDB::PQR_FORMAT); + PDB::PushFlags(PDB::Flags() | PDB::PQR_FORMAT); + writer.Write(ent); + PDB::PopFlags(); + } else { + writer.Write(ent); } - writer.Write(ent); } void EntityIOPDBHandler::Import(mol::EntityHandle& ent, diff --git a/modules/io/src/mol/pdb_io.hh b/modules/io/src/mol/pdb_io.hh index 140db87e3..d9f3bc78e 100644 --- a/modules/io/src/mol/pdb_io.hh +++ b/modules/io/src/mol/pdb_io.hh @@ -19,22 +19,32 @@ #ifndef OST_IO_PDB_IO_HH #define OST_IO_PDB_IO_HH +#include <stack> + namespace ost { namespace io { /// \brief flags that incluence the behaviour of the PDBReader and PDBWriter struct PDB { - typedef enum { + + struct S { + static S& I(); + std::stack<unsigned int> fstack; + }; + /// \brief skip faulty records - /// /// This flag tells the PDB loader to ignore faulty records. By default, /// faulty records abort import. - SKIP_FAULTY_RECORDS=1, + static const unsigned int SKIP_FAULTY_RECORDS; + /// \brief do not import HETATM records - NO_HETATMS=2, + static const unsigned int NO_HETATMS; + /// \brief enable writing of multiple models - WRITE_MULTIPLE_MODELS=4, + static const unsigned int WRITE_MULTIPLE_MODELS; + /// \brief enable for PQR - PQR_FORMAT=8, + static const unsigned int PQR_FORMAT; + /// \brief Join atom records into one residue, even if the atom records /// are not sequential. /// @@ -57,20 +67,15 @@ struct PDB { /// /// By default, the atom 550 will start a new residue instead of being /// joined with atoms 43-48 into one residue. - JOIN_SPREAD_ATOM_RECORDS=16, - //// \brief keep track of the order of atom records - /// - /// This option is mostly useful in combination with - /// PDB::JOIN_SPREAD_ATOM_RECORDS and CoordGroups. - /// - /// The atoms are accessible via PDBReader::GetSequentialAtoms() - SEQUENTIAL_ATOM_IMPORT=32, + static const unsigned int JOIN_SPREAD_ATOM_RECORDS; + /// \brief only import C-alpha atoms - CALPHA_ONLY=64 - } Type; -}; + static const unsigned int CALPHA_ONLY; -typedef unsigned int PDBFlags; + static void PushFlags(unsigned int flags); + static unsigned int Flags(); + static void PopFlags(); +}; }} diff --git a/modules/io/src/mol/pdb_reader.cc b/modules/io/src/mol/pdb_reader.cc index ec0dbaccb..1ea6f6da8 100644 --- a/modules/io/src/mol/pdb_reader.cc +++ b/modules/io/src/mol/pdb_reader.cc @@ -62,19 +62,19 @@ mol::ResNum to_res_num(int num, char ins_code) } PDBReader::PDBReader(std::istream& instream): - infile_(), instream_(instream), flags_(0) + infile_(), instream_(instream) { this->Init(boost::filesystem::path("")); } PDBReader::PDBReader(const String& filename) - : infile_(filename), instream_(infile_), flags_(0) + : infile_(filename), instream_(infile_) { this->Init(boost::filesystem::path(filename)); } PDBReader::PDBReader(const boost::filesystem::path& loc): - infile_(loc), instream_(infile_), flags_(0) + infile_(loc), instream_(infile_) { this->Init(loc); } @@ -106,7 +106,7 @@ bool PDBReader::HasNext() while (std::getline(in_, curr_line_) && ++line_num_) { StringRef curr_line(curr_line_.c_str(), curr_line_.length()); if (IEquals(curr_line.substr(0, 6), StringRef("ATOM ", 6)) || - (!(flags_ & PDB::NO_HETATMS) && + (!(PDB::Flags() & PDB::NO_HETATMS) && IEquals(curr_line.substr(0, 6),StringRef("HETATM ", 6))) || IEquals(curr_line.substr(0, 6),StringRef("ANISOU ", 6)) || IEquals(curr_line.substr(0, 6), StringRef("SHEET ", 6)) || @@ -123,6 +123,8 @@ bool PDBReader::HasNext() void PDBReader::Import(mol::EntityHandle& ent, const String& restrict_chains) { + LOGN_DEBUG("PDBReader: current flags: " << PDB::Flags()); + Profile profile_import("PDBReader::Import"); this->ClearState(); // first read curr_line and then read next... @@ -171,7 +173,7 @@ void PDBReader::Import(mol::EntityHandle& ent, continue; } if (IEquals(curr_line.substr(0, 6), StringRef("HETATM", 6))) { - if (flags_ & PDB::NO_HETATMS) + if (PDB::Flags() & PDB::NO_HETATMS) continue; LOGN_TRACE("processing HETATM entry"); this->ParseAndAddAtom(curr_line, line_num_, ent, @@ -250,17 +252,6 @@ void PDBReader::ClearState() hard_end_=false; helix_list_.clear(); strand_list_.clear(); - sequential_atom_list_.clear(); -} - -std::vector<mol::AtomHandle> PDBReader::GetSequentialAtoms() const -{ - return sequential_atom_list_; -} - -void PDBReader::SetFlags(PDBFlags flags) -{ - flags_=flags; } bool PDBReader::ParseAtomIdent(const StringRef& line, int line_num, @@ -276,7 +267,7 @@ bool PDBReader::ParseAtomIdent(const StringRef& line, int line_num, std::pair<bool, int> a_num=line.substr(6, 5).ltrim().to_int(); if (!a_num.first) { - if (flags_ & PDB::SKIP_FAULTY_RECORDS) { + if (PDB::Flags() & PDB::SKIP_FAULTY_RECORDS) { return false; } throw IOException(str(format("invalid atom number on line %d") %line_num)); @@ -286,7 +277,7 @@ bool PDBReader::ParseAtomIdent(const StringRef& line, int line_num, res_name=line.substr(17, 3).trim(); std::pair<bool, int> res_num=line.substr(22, 4).ltrim().to_int();; if (!res_num.first) { - if (flags_ & PDB::SKIP_FAULTY_RECORDS) { + if (PDB::Flags() & PDB::SKIP_FAULTY_RECORDS) { return false; } throw IOException(str(format("invalid res number on line %d") % line_num)); @@ -311,7 +302,7 @@ void PDBReader::ParseAnisou(const StringRef& line, int line_num, for (int i=0;i<6; ++i) { std::pair<bool, int> result=line.substr(29+i*7, 6).to_int(); if (!result.first) { - if (flags_ & PDB::SKIP_FAULTY_RECORDS) { + if (PDB::Flags() & PDB::SKIP_FAULTY_RECORDS) { return; } throw IOException(str(format("invalid ANISOU record on line %d")%line_num)); @@ -320,7 +311,7 @@ void PDBReader::ParseAnisou(const StringRef& line, int line_num, } String aname(atom_name.str()); if (!curr_residue_.IsValid()) { - if (flags_ & PDB::SKIP_FAULTY_RECORDS) { + if (PDB::Flags() & PDB::SKIP_FAULTY_RECORDS) { return; } const char* fmt_str="invalid ANISOU record for inexistent atom on line %d"; @@ -328,7 +319,7 @@ void PDBReader::ParseAnisou(const StringRef& line, int line_num, } mol::AtomHandle atom=curr_residue_.FindAtom(aname); if (!atom.IsValid()) { - if (flags_ & PDB::SKIP_FAULTY_RECORDS) { + if (PDB::Flags() & PDB::SKIP_FAULTY_RECORDS) { return; } const char* fmt_str="invalid ANISOU record for inexistent atom on line %d"; @@ -367,7 +358,7 @@ void PDBReader::ParseAndAddAtom(const StringRef& line, int line_num, for (int i=0;i<3; ++i) { std::pair<bool, float> result=line.substr(30+i*8, 8).ltrim().to_float(); if (!result.first) { - if (flags_ & PDB::SKIP_FAULTY_RECORDS) { + if (PDB::Flags() & PDB::SKIP_FAULTY_RECORDS) { return; } throw IOException(str(format("invalid coordinate on line %d")%line_num)); @@ -432,24 +423,31 @@ void PDBReader::ParseAndAddAtom(const StringRef& line, int line_num, } if(update_chain) { - if (!(curr_chain_=ent.FindChain(s_chain))) { + curr_chain_=mol::ChainHandle(); +#if 0 + // TODO: should this depend on JOIN_SPREAD as well? + if (PDB::Flags() & PDB::JOIN_SPREAD_ATOM_RECORDS) { + curr_chain_=ent.FindChain(s_chain); + } +#else + curr_chain_=ent.FindChain(s_chain); +#endif + if(!curr_chain_.IsValid()) { LOGN_DUMP("new chain " << s_chain); curr_chain_=editor.InsertChain(s_chain); ++chain_count_; } + assert(curr_chain_.IsValid()); } if(update_residue) { - if (flags_ & PDB::JOIN_SPREAD_ATOM_RECORDS) { + curr_residue_=mol::ResidueHandle(); + if (PDB::Flags() & PDB::JOIN_SPREAD_ATOM_RECORDS) { curr_residue_=curr_chain_.FindResidue(res_num); - if (!curr_residue_.IsValid()) { - LOGN_DUMP("new residue " << res_name << " " << res_num); - curr_residue_=editor.AppendResidue(curr_chain_, res_name.str(), res_num); - ++residue_count_; - } - } else { + } + if (!curr_residue_.IsValid()) { LOGN_DUMP("new residue " << res_name << " " << res_num); curr_residue_=editor.AppendResidue(curr_chain_, res_name.str(), res_num); - ++residue_count_; + ++residue_count_; } assert(curr_residue_.IsValid()); } @@ -493,16 +491,22 @@ void PDBReader::ParseAndAddAtom(const StringRef& line, int line_num, } else { mol::AtomHandle ah=editor.InsertAltAtom(curr_residue_, aname, String(1, alt_loc), apos, aprop); - if (flags_ & PDB::SEQUENTIAL_ATOM_IMPORT) { + /* + for now, this is not needed - the cg will use an global atom id sorted + list insteadx + if (PDB::Flags() & PDB::SEQUENTIAL_ATOM_IMPORT) { sequential_atom_list_.push_back(ah); } + */ ++atom_count_; } } else { mol::AtomHandle ah = editor.InsertAtom(curr_residue_, aname, apos, aprop); - if (flags_ & PDB::SEQUENTIAL_ATOM_IMPORT) { + /* + if (PDB::Flags() & PDB::SEQUENTIAL_ATOM_IMPORT) { sequential_atom_list_.push_back(ah); } + */ ++atom_count_; } } diff --git a/modules/io/src/mol/pdb_reader.hh b/modules/io/src/mol/pdb_reader.hh index 5c85e23a1..6d9f715c6 100644 --- a/modules/io/src/mol/pdb_reader.hh +++ b/modules/io/src/mol/pdb_reader.hh @@ -47,17 +47,7 @@ public: bool HasNext(); void Import(mol::EntityHandle& ent, - const String& restrict_chains=""); - void SetFlags(PDBFlags flags); - - /// \brief get list of atoms - /// - /// The atom handles reflect the order of atom records in the PDb files. This - /// is used to synchronize PDB and coordgroup io. - /// - /// By default, the atom list is empty, The PDB::SEQUENTIAL_ATOM_IMPORT flag - /// must be set. - std::vector<mol::AtomHandle> GetSequentialAtoms() const; + const String& restrict_chains=""); private: void ClearState(); @@ -90,8 +80,7 @@ private: std::istream& instream_; boost::iostreams::filtering_stream<boost::iostreams::input> in_; String curr_line_; - std::vector<mol::AtomHandle> sequential_atom_list_; - PDBFlags flags_; + // this needs to be set to true for reading pqr // file (i.e. pdb formatted file with charges in occupacy // column, and radii in b-factor column) diff --git a/modules/io/src/mol/pdb_writer.cc b/modules/io/src/mol/pdb_writer.cc index 9251f42b2..a6b32d396 100644 --- a/modules/io/src/mol/pdb_writer.cc +++ b/modules/io/src/mol/pdb_writer.cc @@ -123,27 +123,20 @@ private: PDBWriter::PDBWriter(std::ostream& stream): outfile_(), outstream_(stream) -{ - -} +{} PDBWriter::PDBWriter(const boost::filesystem::path& filename): - outfile_(filename.file_string().c_str()), outstream_(outfile_), mol_count_(0), - flags_(0) -{ - -} + outfile_(filename.file_string().c_str()), outstream_(outfile_), mol_count_(0) +{} PDBWriter::PDBWriter(const String& filename): - outfile_(filename.c_str()), outstream_(outfile_), mol_count_(0), flags_(0) -{ - -} + outfile_(filename.c_str()), outstream_(outfile_), mol_count_(0) +{} void PDBWriter::WriteModelLeader() { ++mol_count_; - if (flags_ & PDB::WRITE_MULTIPLE_MODELS) { + if (PDB::Flags() & PDB::WRITE_MULTIPLE_MODELS) { outstream_ << "MODEL " << mol_count_ << std::endl; } else if (mol_count_>1) { throw IOException("Please enable the PDB::WRITE_MULTIPLE_MODELS flag to " @@ -153,7 +146,7 @@ void PDBWriter::WriteModelLeader() void PDBWriter::WriteModelTrailer() { - if (flags_ & PDB::WRITE_MULTIPLE_MODELS) { + if (PDB::Flags() & PDB::WRITE_MULTIPLE_MODELS) { outstream_ << "ENDMDL" << std::endl; } } @@ -163,18 +156,13 @@ void PDBWriter::WriteModel(H ent) { this->WriteModelLeader(); PDBWriterImpl writer(outstream_); - if (flags_ & PDB::PQR_FORMAT) { + if (PDB::Flags() & PDB::PQR_FORMAT) { writer.SetIsPQR(true); } ent.Apply(writer); this->WriteModelTrailer(); } -void PDBWriter::SetFlags(PDBFlags flags) -{ - flags_=flags; -} - void PDBWriter::Write(const mol::EntityView& ent) { this->WriteModel(ent); @@ -199,7 +187,7 @@ void PDBWriter::Write(const mol::AtomHandleList& atoms) } last_chain=(*i).GetResidue().GetChain(); } - write_atom(outstream_, *i, counter, flags_ & PDB::PQR_FORMAT); + write_atom(outstream_, *i, counter, PDB::Flags() & PDB::PQR_FORMAT); } this->WriteModelTrailer(); } diff --git a/modules/io/src/mol/pdb_writer.hh b/modules/io/src/mol/pdb_writer.hh index 83f2f923e..971890eeb 100644 --- a/modules/io/src/mol/pdb_writer.hh +++ b/modules/io/src/mol/pdb_writer.hh @@ -42,8 +42,6 @@ public: PDBWriter(const boost::filesystem::path& filename); PDBWriter(std::ostream& outstream); - void SetFlags(PDBFlags flags); - void Write(const mol::EntityView& ent); void Write(const mol::EntityHandle& ent); @@ -59,7 +57,6 @@ private: std::ofstream outfile_; std::ostream& outstream_; int mol_count_; - PDBFlags flags_; }; }} diff --git a/modules/mol/base/pymod/export_atom.cc b/modules/mol/base/pymod/export_atom.cc index 52983f3ae..ccebbfb0a 100644 --- a/modules/mol/base/pymod/export_atom.cc +++ b/modules/mol/base/pymod/export_atom.cc @@ -46,6 +46,7 @@ void export_Atom() .def("GetProp", &AtomBase::GetProp, return_value_policy<copy_const_reference>()) .def("SetProp", &AtomBase::SetProp, args("prop")) + .def("GetIndex", &AtomBase::GetIndex) .add_property("prop", make_function(&AtomBase::GetProp, return_value_policy<copy_const_reference>())) @@ -56,6 +57,7 @@ void export_Atom() make_function(&AtomBase::GetName, return_value_policy<copy_const_reference>()), &AtomBase::SetName) + .add_property("index",&AtomBase::GetIndex) ; generic_prop_def<AtomBase>(atom_base); diff --git a/modules/mol/base/src/atom_base.cc b/modules/mol/base/src/atom_base.cc index 95141733f..9a8cfb1fc 100644 --- a/modules/mol/base/src/atom_base.cc +++ b/modules/mol/base/src/atom_base.cc @@ -156,5 +156,11 @@ int AtomBase::GetIntProperty(Prop::ID prop_id) const return Impl()->GetIntProperty(prop_id); } +unsigned long AtomBase::GetIndex() const +{ + this->CheckValidity(); + return Impl()->GetIndex(); +} + }} // ns diff --git a/modules/mol/base/src/atom_base.hh b/modules/mol/base/src/atom_base.hh index 0a17ce250..3b10fb8ca 100644 --- a/modules/mol/base/src/atom_base.hh +++ b/modules/mol/base/src/atom_base.hh @@ -116,7 +116,10 @@ public: /// \brief Get int property by id int GetIntProperty(Prop::ID prop_id) const; -public: + + /// \brief Get the internal index + unsigned long GetIndex() const; + /// \brief get atom implementation. /// /// Intended for internal use. diff --git a/modules/mol/base/src/coord_frame.hh b/modules/mol/base/src/coord_frame.hh index 4a04ca4e4..017a58865 100644 --- a/modules/mol/base/src/coord_frame.hh +++ b/modules/mol/base/src/coord_frame.hh @@ -29,17 +29,10 @@ namespace ost { namespace mol { -class CoordFrame; - +typedef std::vector<geom::Vec3> CoordFrame; typedef boost::shared_ptr<CoordFrame> CoordFramePtr; typedef std::vector<CoordFramePtr> CoordFrameList; -class DLLEXPORT_OST_MOL CoordFrame : public std::vector<geom::Vec3> { -public: - CoordFrame() {} - CoordFrame(Real ts) {} -}; - }} #endif diff --git a/modules/mol/base/src/coord_source.cc b/modules/mol/base/src/coord_source.cc index a8d95ff1a..b25a91755 100644 --- a/modules/mol/base/src/coord_source.cc +++ b/modules/mol/base/src/coord_source.cc @@ -20,6 +20,7 @@ /* Author: Marco Biasini */ +#include <ost/log.hh> #include <ost/mol/atom_handle.hh> #include <ost/mol/xcs_editor.hh> #include <ost/mol/in_mem_coord_source.hh> @@ -53,10 +54,12 @@ CoordSource::~CoordSource() void CoordSource::CopyFrame(uint frame_id) { if (atoms_.empty()) { + LOGN_DEBUG("atom list empty, ignored"); return; } CoordFramePtr frame=this->GetFrame(frame_id); if (!frame) { + LOGN_DEBUG("invalid frame given, ignored"); return; } assert(frame->size()==atoms_.size()); @@ -64,7 +67,7 @@ void CoordSource::CopyFrame(uint frame_id) CoordFrame::const_iterator c=frame->begin(); for (AtomHandleList::iterator i=atoms_.begin(), e=atoms_.end(); i!=e; ++i, ++c) { - edi.SetAtomPos(*i, *c); + edi.SetAtomPos(*i, *c); } } diff --git a/modules/mol/base/src/impl/atom_impl.cc b/modules/mol/base/src/impl/atom_impl.cc index d8e37b25c..cb3ecf87a 100644 --- a/modules/mol/base/src/impl/atom_impl.cc +++ b/modules/mol/base/src/impl/atom_impl.cc @@ -40,7 +40,8 @@ AtomImpl::AtomImpl(const EntityImplPtr& e, const ResidueImplPtr& r, const String& n, const geom::Vec3& p, - const AtomProp& prop): + const AtomProp& prop, + unsigned long index): res_(r), name_(n), pos_(p), @@ -48,7 +49,8 @@ AtomImpl::AtomImpl(const EntityImplPtr& e, prim_connector_(), connector_list_(), fragment_(), - state_(0) + state_(0), + index_(index) { EntityHandle ent = this->GetEntity(); geom::Mat4 transf_matrix = ent.GetTransformationMatrix(); diff --git a/modules/mol/base/src/impl/atom_impl.hh b/modules/mol/base/src/impl/atom_impl.hh index 3db9ff520..f3c2cc1c0 100644 --- a/modules/mol/base/src/impl/atom_impl.hh +++ b/modules/mol/base/src/impl/atom_impl.hh @@ -50,7 +50,8 @@ class AtomImpl: public GenericPropertyContainerImpl, public boost::enable_shared_from_this<AtomImpl> { public: AtomImpl(const EntityImplPtr& ent, const ResidueImplPtr& res, - const String& name, const geom::Vec3& pos, const AtomProp& prop); + const String& name, const geom::Vec3& pos, const AtomProp& prop, + unsigned long index); ~AtomImpl(); void Apply(EntityVisitor& h); @@ -137,6 +138,9 @@ public: Real GetFloatProperty(Prop::ID prop_id) const; int GetIntProperty(Prop::ID prop_id) const; + + unsigned long GetIndex() const {return index_;} + void SetIndex(unsigned long index) {index_=index;} private: ResidueImplW res_; @@ -171,6 +175,8 @@ private: unsigned int mask = 0x1<<bit; return (state_ & mask)!=0; } + + unsigned long index_; }; /// \internal diff --git a/modules/mol/base/src/impl/entity_impl.cc b/modules/mol/base/src/impl/entity_impl.cc index e17a5a76d..4806c7cbd 100644 --- a/modules/mol/base/src/impl/entity_impl.cc +++ b/modules/mol/base/src/impl/entity_impl.cc @@ -76,7 +76,8 @@ EntityImpl::EntityImpl(): xcs_editor_count_(0), ics_editor_count_(0), dirty_flags_(DisableICS), - name_("") + name_(""), + next_index_(0L) { } @@ -350,9 +351,9 @@ AtomImplPtr EntityImpl::CreateAtom(const ResidueImplPtr& rp, { #if MAKE_SHARED_AVAILABLE AtomImplPtr ap=boost::make_shared<AtomImpl>(shared_from_this(), rp, name, - pos, prop); + pos, prop,next_index_++); #else - AtomImplPtr ap(new AtomImpl(shared_from_this(), rp, name, pos, prop)); + AtomImplPtr ap(new AtomImpl(shared_from_this(), rp, name, pos, prop,next_index_++)); #endif if (identity_transf_ == false) { geom::Vec3 transformed_pos = geom::Vec3(transformation_matrix_*geom::Vec4(pos)); diff --git a/modules/mol/base/src/impl/entity_impl.hh b/modules/mol/base/src/impl/entity_impl.hh index 4042e9297..ebe32704b 100644 --- a/modules/mol/base/src/impl/entity_impl.hh +++ b/modules/mol/base/src/impl/entity_impl.hh @@ -268,6 +268,9 @@ private: int ics_editor_count_; int dirty_flags_; String name_; + + unsigned long next_index_; + template <bool always_true> EntityView do_selection(const EntityHandle&, const Query&, QueryFlags) const; }; diff --git a/modules/mol/base/src/in_mem_coord_source.cc b/modules/mol/base/src/in_mem_coord_source.cc index 98417d159..089c667bd 100644 --- a/modules/mol/base/src/in_mem_coord_source.cc +++ b/modules/mol/base/src/in_mem_coord_source.cc @@ -27,8 +27,8 @@ void InMemCoordSource::AddFrame(const CoordFramePtr& frame) void InMemCoordSource::AddFrame(const std::vector<geom::Vec3>& coords) { - frames_.push_back(CoordFramePtr(new CoordFrame(0.0))); - frames_.back()->insert(frames_.back()->end(), coords.begin(), coords.end()); + CoordFramePtr fp(new CoordFrame(coords)); + frames_.push_back(fp); } }} diff --git a/modules/mol/base/tests/test_entity.cc b/modules/mol/base/tests/test_entity.cc index 8deba9b01..050442294 100644 --- a/modules/mol/base/tests/test_entity.cc +++ b/modules/mol/base/tests/test_entity.cc @@ -95,10 +95,12 @@ BOOST_AUTO_TEST_CASE(entity_creator) AtomHandle atom1 = e.InsertAtom(res, "X1",geom::Vec3()); BOOST_CHECK(res==atom1.GetResidue()); BOOST_CHECK(atom1.GetName()=="X1"); + BOOST_CHECK(atom1.GetIndex()==0); AtomHandle atom2 = e.InsertAtom(res, "X2",geom::Vec3()); BOOST_CHECK(res==atom2.GetResidue()); BOOST_CHECK(atom2.GetName()=="X2"); + BOOST_CHECK(atom2.GetIndex()==1); BondHandle bond = e.Connect(atom1, atom2); -- GitLab