diff --git a/modules/io/pymod/wrap_io.cc b/modules/io/pymod/wrap_io.cc
index 789efe111ba32661c5e0a3da15fb6901e55bbb9c..1e2b5186906a5f94cd11526f9837aa74c6af5fca 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_pqr_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>
@@ -113,6 +114,7 @@ BOOST_PYTHON_MODULE(_ost_io)
                                            arg("detect_swap")=true,arg("swap_bytes")=false))
 ;
   def("LoadMAE", &LoadMAE);
+  def("LoadPQR", &LoadPQR);
 
   export_pdb_io();
   export_mmcif_io();
diff --git a/modules/io/src/mol/CMakeLists.txt b/modules/io/src/mol/CMakeLists.txt
index cb80b67a9600ed5ec3f98e19a5669dcb4b1f1a1b..e7b729cb67c2361636103b86e1cb02f225db4c66 100644
--- a/modules/io/src/mol/CMakeLists.txt
+++ b/modules/io/src/mol/CMakeLists.txt
@@ -1,5 +1,6 @@
 set(OST_IO_MOL_SOURCES
 entity_io_crd_handler.cc	
+entity_io_pqr_handler.cc	
 entity_io_mae_handler.cc	
 pdb_reader.cc
 entity_io_pdb_handler.cc	
@@ -29,6 +30,7 @@ mmcif_info.hh
 io_profile.hh
 dcd_io.hh
 entity_io_crd_handler.hh
+entity_io_pqr_handler.hh
 entity_io_mae_handler.hh
 entity_io_mmcif_handler.hh
 entity_io_handler.hh
diff --git a/modules/io/src/mol/entity_io_pqr_handler.cc b/modules/io/src/mol/entity_io_pqr_handler.cc
new file mode 100644
index 0000000000000000000000000000000000000000..5d2941c3351d9f9dd5bae11606044d742dc115bd
--- /dev/null
+++ b/modules/io/src/mol/entity_io_pqr_handler.cc
@@ -0,0 +1,339 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 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 <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/tokenizer.hpp>
+
+#include <ost/log.hh>
+#include <ost/conop/conop.hh>
+#include <ost/mol/xcs_editor.hh>
+#include <ost/profile.hh>
+#include <ost/boost_filesystem_helper.hh>
+
+#include <ost/io/io_exception.hh>
+#include <ost/io/swap_util.hh>
+
+#include "entity_io_pqr_handler.hh"
+
+namespace ost { namespace io {
+
+using boost::format;
+
+/// \brief Reader for PQR file format, used in APBS
+PQRReader::PQRReader(const boost::filesystem::path& loc):
+  sequential_atom_list_(),
+  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());
+}
+
+/// \brief Returns an vector containing all atom handles as observed in the file
+std::vector<mol::AtomHandle> PQRReader::GetSequentialAtoms() const
+{
+  return sequential_atom_list_;
+}
+
+/// \brief Performes file import
+void PQRReader::Import(mol::EntityHandle& ent)
+{
+  Profile profile_import("PQRReader::Import");
+
+  String line;
+  while(std::getline(in_,line)) {
+    if(line.substr(0,4)=="ATOM") {
+      ParseAndAddAtom(line,ent);
+    }
+  }
+
+  LOG_INFO("imported " << chain_count_ << " chains, " << residue_count_
+                << " residues, " << atom_count_ << " atoms");  
+}
+
+/// \brief Parsing for standard format
+void PQRReader::ParseAndAddAtom(const String& line, mol::EntityHandle& ent)
+{
+  static bool auto_chain=false;
+  static boost::char_separator<char> sep(" ");
+  mol::XCSEditor editor=ent.EditXCS(mol::BUFFERED_EDIT);
+
+  //int anum = boost::lexical_cast<int>(boost::trim_copy(line.substr(0,5)));
+  String aname = boost::trim_copy(line.substr(12,4));
+  String ele = aname.substr(0,1);
+  String rname = boost::trim_copy(line.substr(17,3));
+  int irnum = boost::lexical_cast<int>(boost::trim_copy(line.substr(22,4)));
+  String s_chain = boost::trim_copy(line.substr(21,1));
+
+  // space separated x y z charge rad at column 30+
+  Real ax=0.0,ay=0.0,az=0.0,ac=0.0,ar=0.0;
+  try {
+    std::string tmp(line.substr(30,std::string::npos));
+    boost::tokenizer<boost::char_separator<char> > tok(tmp,sep);
+    boost::tokenizer<boost::char_separator<char> >::iterator tit=tok.begin();
+    ax=boost::lexical_cast<Real>(*tit); ++tit;
+    ay=boost::lexical_cast<Real>(*tit); ++tit;
+    az=boost::lexical_cast<Real>(*tit); ++tit;
+    ac=boost::lexical_cast<Real>(*tit); ++tit;
+    ar=boost::lexical_cast<Real>(*tit); ++tit;
+  } catch (boost::bad_lexical_cast& e) {
+    return;
+  }
+  
+  geom::Vec3 apos(ax,ay,az);
+
+  mol::ResidueKey rkey(rname);
+  
+  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;
+    if(s_chain.empty()) {
+      s_chain="A";
+      auto_chain=true;
+    }
+  } else {
+    if(auto_chain) {
+      if(curr_residue_) {
+        if(rnum<curr_residue_.GetNumber()) {
+          update_chain=true;
+          update_residue=true;
+          std::ostringstream tmp;
+          tmp << static_cast<char>(65+chain_count_);
+          s_chain=tmp.str();
+        }
+      }
+    } else if(curr_chain_.GetName()!=s_chain) {
+      update_chain=true;
+      update_residue=true;
+    }  
+  }
+
+  if(!curr_residue_) {
+    update_residue=true;
+  } else if(curr_residue_.GetNumber()!=rnum) {
+    update_residue=true;
+  }
+
+  if(update_chain) {  
+    LOG_DEBUG("new chain " << s_chain);      
+    curr_chain_=editor.InsertChain(s_chain);
+    ++chain_count_;      
+  }
+
+  if(update_residue) {
+    LOG_DEBUG("new residue " << rkey << " " << rnum);
+    curr_residue_=editor.AppendResidue(curr_chain_, rkey, rnum);
+    assert(curr_residue_.IsValid());
+    ++residue_count_;
+  }
+
+  // finally add atom
+  LOG_DEBUG("adding atom " << aname << " (" << ele << ") @" << apos);
+  mol::AtomHandle ah = editor.InsertAtom(curr_residue_, aname, apos, ele);
+  ah.SetRadius(ar);
+  ah.SetCharge(ac);
+  sequential_atom_list_.push_back(ah);
+  ++atom_count_;
+}
+
+PQRWriter::PQRWriter(std::ostream& ostream, bool ext) :
+     outfile_(), outstream_(ostream), ext_(ext), atom_count_(0), res_count_(0)
+{}
+
+PQRWriter::PQRWriter(const boost::filesystem::path& filename, bool ext) :
+  outfile_(BFPathToString(filename).c_str()),
+  outstream_(outfile_), ext_(ext), atom_count_(0), res_count_(0)
+{}
+
+PQRWriter::PQRWriter(const String& filename, bool ext) :
+  outfile_(filename.c_str()), outstream_(outfile_), ext_(ext), atom_count_(0),
+  res_count_(0)
+{}
+
+/// \brief Write header containing standard title and atom count/format row
+void PQRWriter::WriteHeader(const mol::EntityView& ent)
+{
+}
+
+void PQRWriter::Init()
+{
+  res_count_ = 0;
+}
+
+void PQRWriter::Write(const mol::EntityView& ent)
+{
+  if (!outstream_) {
+    throw IOException("Can't write PQR file. Bad output stream");
+  }
+  this->Init();
+  mol::EntityView non_const_view = ent;
+  this->WriteHeader(non_const_view);
+  non_const_view.Apply(*this);
+}
+
+void PQRWriter::Write(const mol::EntityHandle& ent)
+{
+  if (!outstream_) {
+    throw IOException("Can't write PQR file. Bad output stream");
+  }
+  this->Init();
+  mol::EntityView non_const_view = ent.CreateFullView();
+  this->WriteHeader(non_const_view);
+  non_const_view.Apply(*this);
+}
+
+
+bool PQRWriter::VisitResidue(const mol::ResidueHandle& r)
+{
+  res_count_++;
+  return true;
+}
+
+bool PQRWriter::VisitAtom(const mol::AtomHandle& atom)
+{
+  atom_count_++;
+  String e_name=atom.GetEntity().GetName();
+  if (e_name=="") {
+    e_name="MOL";
+  }
+	
+  mol::ResidueHandle res=atom.GetResidue();
+/*
+  outstream_  << format("%5i") % atom_count_
+              << format("%5i") % res_count_ << " "
+	            << format("%-4s") % res.GetKey() << " "
+              << format("%-4s") % atom.GetName()
+              << format("%10.5f") % atom.GetPos().x
+              << format("%10.5f") % atom.GetPos().y
+              << format("%10.5f") % atom.GetPos().z << " "
+              << format("%-4s") % res.GetChain().GetName() << " "
+              << format("%-5i") % res.GetNumber() << " "
+              << format("%8.5f") % atom.GetBFactor()
+              << std::endl;
+              */
+ 
+  return true;
+}
+
+bool EntityIOPQRHandler::RequiresBuilder() const
+{
+  return true;
+}
+
+void EntityIOPQRHandler::Import(mol::EntityHandle& ent,
+                                const boost::filesystem::path& loc)
+{
+  PQRReader reader(loc);
+  reader.Import(ent);
+}
+
+void EntityIOPQRHandler::Export(const mol::EntityView& ent,
+                                std::ostream& stream) const
+{
+  PQRWriter writer(stream);
+  writer.Write(ent);
+}
+
+void EntityIOPQRHandler::Export(const mol::EntityView& ent,
+                                const boost::filesystem::path& loc) const
+{
+  PQRWriter writer(loc);
+  writer.Write(ent);
+}
+
+namespace {
+
+bool pqr_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,".pqr") || detail::FilenameEndsWith(match_suf_string,".pqr.gz") ) {
+      return true;
+    }
+  } else if(type=="pqr") {
+    return true;
+  }
+
+  return false;
+}
+
+}
+
+bool EntityIOPQRHandler::ProvidesImport(const boost::filesystem::path& loc,
+                                        const String& type)
+{
+  return pqr_handler_is_responsible_for(loc, type);
+}
+
+bool EntityIOPQRHandler::ProvidesExport(const boost::filesystem::path& loc,
+                                        const String& type)
+{
+  return pqr_handler_is_responsible_for(loc, type);
+}
+
+mol::EntityHandle LoadPQR(const String& file_name) 
+{
+  Profile profile_load("LoadPQR");
+  conop::BuilderP builder = conop::Conopology::Instance().GetBuilder();  
+  PQRReader reader(file_name);
+  mol::EntityHandle ent=mol::CreateEntity();
+  mol::XCSEditor editor=ent.EditXCS(mol::BUFFERED_EDIT);
+  reader.Import(ent);
+  conop::Conopology::Instance().ConnectAll(builder,ent);    
+  return ent;
+}
+
+
+void EntityIOPQRHandler::Import(mol::EntityHandle& ent, 
+                                std::istream& stream)
+{
+  throw IOException("PQR format does not support import from stream");
+}
+
+
+
+
+}} // ns
+
+
diff --git a/modules/io/src/mol/entity_io_pqr_handler.hh b/modules/io/src/mol/entity_io_pqr_handler.hh
new file mode 100644
index 0000000000000000000000000000000000000000..0b48e50be3a448d0ec2d7069b74e953a4b11c0cb
--- /dev/null
+++ b/modules/io/src/mol/entity_io_pqr_handler.hh
@@ -0,0 +1,115 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 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
+*/
+
+#ifndef OST_IO_ENTITY_IO_PLUGIN_PQR_H
+#define OST_IO_ENTITY_IO_PLUGIN_PQR_H
+
+#include <ost/mol/entity_handle.hh>
+#include <ost/mol/chain_handle.hh>
+#include <ost/mol/residue_handle.hh>
+#include <ost/mol/entity_visitor.hh>
+#include <ost/io/mol/entity_io_handler.hh>
+
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/filesystem/fstream.hpp>
+
+namespace ost { namespace io {
+
+/// \brief CHARMM coordinate file import
+class DLLEXPORT_OST_IO PQRReader {
+public:
+  PQRReader(const boost::filesystem::path& loc);
+  
+  void Import(mol::EntityHandle& ent);
+
+  std::vector<mol::AtomHandle> GetSequentialAtoms() const;
+
+private:
+
+  void ParseAndAddAtom(const String& line, mol::EntityHandle& h);
+  void ParseAndAddAtomExpanded(const String& line, mol::EntityHandle& h);
+
+  std::vector<mol::AtomHandle> sequential_atom_list_;
+  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_;
+};
+
+/// \brief CHARMM coordinate file export
+class DLLEXPORT_OST_IO PQRWriter : public mol::EntityVisitor {
+public:
+  PQRWriter(const String& filename, bool ext=false);
+  PQRWriter(const boost::filesystem::path& filename, bool ext=false);
+  PQRWriter(std::ostream& outstream, bool ext=false);
+
+  void Write(const mol::EntityView& ent);
+  void Write(const mol::EntityHandle& ent);
+
+  virtual bool VisitAtom(const mol::AtomHandle& atom);
+  virtual bool VisitResidue(const mol::ResidueHandle& r);
+
+  void WriteHeader(const mol::EntityView& ent);
+
+private:
+  void Init();
+
+  std::ofstream   outfile_;
+  std::ostream&   outstream_;
+  bool ext_;
+  int atom_count_;
+  int atom_total_;
+  int res_count_;
+};
+
+class DLLEXPORT_OST_IO EntityIOPQRHandler: 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("Crd"); }
+  static String GetFormatDescription() { return String("CARD format file used by the Charmm software package"); }
+};
+
+
+typedef EntityIOHandlerFactory<EntityIOPQRHandler> EntityIOPQRHandlerFactory;
+
+mol::EntityHandle DLLEXPORT_OST_IO LoadPQR(const String& file_name);
+
+}} // ns
+
+#endif