Index: src/Parser/Makefile.am
===================================================================
--- src/Parser/Makefile.am	(revision 83f17610150f59038d04ff05a300df1d76c5df81)
+++ src/Parser/Makefile.am	(revision 3ae731331613c6806f4a83a01d7417d215c6877a)
@@ -13,4 +13,5 @@
   MpqcParser.cpp \
   PcpParser.cpp \
+  PdbParser.cpp \
   TremoloParser.cpp \
   XyzParser.cpp
@@ -22,4 +23,5 @@
   MpqcParser.hpp \
   PcpParser.hpp \
+  PdbParser.hpp \
   TremoloParser.hpp \
   XyzParser.hpp
Index: src/Parser/PdbParser.cpp
===================================================================
--- src/Parser/PdbParser.cpp	(revision 3ae731331613c6806f4a83a01d7417d215c6877a)
+++ src/Parser/PdbParser.cpp	(revision 3ae731331613c6806f4a83a01d7417d215c6877a)
@@ -0,0 +1,519 @@
+/*
+ * Project: MoleCuilder
+ * Description: creates and alters molecular systems
+ * Copyright (C)  2010 University of Bonn. All rights reserved.
+ * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
+ */
+
+/*
+ * PdbParser.cpp
+ *
+ *  Created on: Aug 17, 2010
+ *      Author: heber
+ */
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "Helpers/MemDebug.hpp"
+
+#include "Helpers/Assert.hpp"
+#include "Helpers/Log.hpp"
+#include "Helpers/Verbose.hpp"
+#include "PdbParser.hpp"
+#include "World.hpp"
+#include "atom.hpp"
+#include "element.hpp"
+#include "bond.hpp"
+#include "periodentafel.hpp"
+#include "Descriptors/AtomIdDescriptor.hpp"
+#include <map>
+#include <vector>
+
+
+using namespace std;
+
+/**
+ * Constructor.
+ */
+PdbParser::PdbParser() {
+  knownKeys[" "] = TremoloKey::noKey; // with this we can detect invalid keys
+  knownKeys["x"] = TremoloKey::x;
+  knownKeys["u"] = TremoloKey::u;
+  knownKeys["F"] = TremoloKey::F;
+  knownKeys["stress"] = TremoloKey::stress;
+  knownKeys["Id"] = TremoloKey::Id;
+  knownKeys["neighbors"] = TremoloKey::neighbors;
+  knownKeys["imprData"] = TremoloKey::imprData;
+  knownKeys["GroupMeasureTypeNo"] = TremoloKey::GroupMeasureTypeNo;
+  knownKeys["Type"] = TremoloKey::Type;
+  knownKeys["extType"] = TremoloKey::extType;
+  knownKeys["name"] = TremoloKey::name;
+  knownKeys["resName"] = TremoloKey::resName;
+  knownKeys["chainID"] = TremoloKey::chainID;
+  knownKeys["resSeq"] = TremoloKey::resSeq;
+  knownKeys["occupancy"] = TremoloKey::occupancy;
+  knownKeys["tempFactor"] = TremoloKey::tempFactor;
+  knownKeys["segID"] = TremoloKey::segID;
+  knownKeys["Charge"] = TremoloKey::Charge;
+  knownKeys["charge"] = TremoloKey::charge;
+  knownKeys["GrpTypeNo"] = TremoloKey::GrpTypeNo;
+  knownKeys["torsion"] = TremoloKey::torsion;
+
+  // default behavior: use all possible keys on output
+  for (std::map<std::string, TremoloKey::atomDataKey>::iterator iter = knownKeys.begin(); iter != knownKeys.end(); ++iter)
+    usedFields.push_back(iter->first);
+}
+
+/**
+ * Destructor.
+ */
+PdbParser::~PdbParser() {
+  usedFields.clear();
+  additionalAtomData.clear();
+  atomIdMap.clear();
+  knownKeys.clear();
+}
+
+/**
+ * Loads atoms from a tremolo-formatted file.
+ *
+ * \param tremolo file
+ */
+void PdbParser::load(istream* file) {
+  string line;
+  string::size_type location;
+
+  usedFields.clear();
+  while (file->good()) {
+    std::getline(*file, line, '\n');
+    if (usedFields.empty()) {
+      location = line.find("ATOMDATA", 0);
+      if (location != string::npos) {
+       parseAtomDataKeysLine(line, location + 8);
+      }
+    }
+    if (line.length() > 0 && line.at(0) != '#') {
+      readAtomDataLine(line);
+    }
+  }
+
+  processNeighborInformation();
+  adaptImprData();
+  adaptTorsion();
+}
+
+/**
+ * Saves the World's current state into as a tremolo file.
+ *
+ * \param file where to save the state
+ */
+void PdbParser::save(ostream* file) {
+  DoLog(0) && (Log() << Verbose(0) << "Saving changes to tremolo." << std::endl);
+
+  vector<atom*>::iterator atomIt;
+  vector<string>::iterator it;
+
+  *file << "# ATOMDATA";
+  for (it=usedFields.begin(); it < usedFields.end(); it++) {
+    *file << "\t" << *it;
+  }
+  *file << endl;
+  vector<atom *> AtomList = World::getInstance().getAllAtoms();
+  for (atomIt = AtomList.begin(); atomIt != AtomList.end(); atomIt++) {
+    saveLine(file, *atomIt);
+  }
+}
+
+/**
+ * Sets the keys for which data should be written to the stream when save is
+ * called.
+ *
+ * \param string of field names with the same syntax as for an ATOMDATA line
+ *        but without the prexix "ATOMDATA"
+ */
+void PdbParser::setFieldsForSave(std::string atomDataLine) {
+  parseAtomDataKeysLine(atomDataLine, 0);
+}
+
+
+/**
+ * Writes one line of tremolo-formatted data to the provided stream.
+ *
+ * \param stream where to write the line to
+ * \param reference to the atom of which information should be written
+ */
+void PdbParser::saveLine(ostream* file, atom* currentAtom) {
+  vector<string>::iterator it;
+  TremoloKey::atomDataKey currentField;
+
+  for (it = usedFields.begin(); it != usedFields.end(); it++) {
+    currentField = knownKeys[it->substr(0, it->find("="))];
+    switch (currentField) {
+      case TremoloKey::x :
+        // for the moment, assume there are always three dimensions
+        *file << currentAtom->at(0) << "\t";
+        *file << currentAtom->at(1) << "\t";
+        *file << currentAtom->at(2) << "\t";
+        break;
+      case TremoloKey::u :
+        // for the moment, assume there are always three dimensions
+        *file << currentAtom->AtomicVelocity[0] << "\t";
+        *file << currentAtom->AtomicVelocity[1] << "\t";
+        *file << currentAtom->AtomicVelocity[2] << "\t";
+        break;
+      case TremoloKey::Type :
+        *file << currentAtom->getType()->getSymbol() << "\t";
+        break;
+      case TremoloKey::Id :
+        *file << currentAtom->getId() << "\t";
+        break;
+      case TremoloKey::neighbors :
+        writeNeighbors(file, atoi(it->substr(it->find("=") + 1, 1).c_str()), currentAtom);
+        break;
+      default :
+        *file << (additionalAtomData.find(currentAtom->getId()) != additionalAtomData.end()
+          ? additionalAtomData[currentAtom->getId()].get(currentField)
+          : defaultAdditionalData.get(currentField));
+        *file << "\t";
+        break;
+    }
+  }
+
+  *file << endl;
+}
+
+/**
+ * Writes the neighbor information of one atom to the provided stream.
+ *
+ * \param stream where to write neighbor information to
+ * \param number of neighbors
+ * \param reference to the atom of which to take the neighbor information
+ */
+void PdbParser::writeNeighbors(ostream* file, int numberOfNeighbors, atom* currentAtom) {
+  BondList::iterator currentBond = currentAtom->ListOfBonds.begin();
+  for (int i = 0; i < numberOfNeighbors; i++) {
+    *file << (currentBond != currentAtom->ListOfBonds.end()
+        ? (*currentBond)->GetOtherAtom(currentAtom)->getId() : 0) << "\t";
+  }
+}
+
+/**
+ * Stores keys from the ATOMDATA line.
+ *
+ * \param line to parse the keys from
+ * \param with which offset the keys begin within the line
+ */
+void PdbParser::parseAtomDataKeysLine(string line, int offset) {
+  string keyword;
+  stringstream lineStream;
+
+  lineStream << line.substr(offset);
+  usedFields.clear();
+  while (lineStream.good()) {
+    lineStream >> keyword;
+    if (knownKeys[keyword.substr(0, keyword.find("="))] == TremoloKey::noKey) {
+      // TODO: throw exception about unknown key
+      cout << "Unknown key: " << keyword << " is not part of the tremolo format specification." << endl;
+      break;
+    }
+    usedFields.push_back(keyword);
+  }
+}
+
+/**
+ * Reads one data line of a tremolo file and interprets it according to the keys
+ * obtained from the ATOMDATA line.
+ *
+ * \param line to parse as an atom
+ */
+void PdbParser::readAtomDataLine(string line) {
+  vector<string>::iterator it;
+  stringstream lineStream;
+  atom* newAtom = World::getInstance().createAtom();
+  TremoloAtomInfoContainer *atomInfo = NULL;
+  additionalAtomData[newAtom->getId()] = *(new TremoloAtomInfoContainer);
+  atomInfo = &additionalAtomData[newAtom->getId()];
+  TremoloKey::atomDataKey currentField;
+  string word;
+  int oldId;
+  double tmp;
+
+  lineStream << line;
+  for (it = usedFields.begin(); it < usedFields.end(); it++) {
+    currentField = knownKeys[it->substr(0, it->find("="))];
+    switch (currentField) {
+      case TremoloKey::x :
+        // for the moment, assume there are always three dimensions
+        for (int i=0;i<NDIM;i++) {
+          lineStream >> tmp;
+          newAtom->set(i, tmp);
+        }
+        break;
+      case TremoloKey::u :
+        // for the moment, assume there are always three dimensions
+        lineStream >> newAtom->AtomicVelocity[0];
+        lineStream >> newAtom->AtomicVelocity[1];
+        lineStream >> newAtom->AtomicVelocity[2];
+        break;
+      case TremoloKey::Type :
+        char type[3];
+        lineStream >> type;
+        newAtom->setType(World::getInstance().getPeriode()->FindElement(type));
+        ASSERT(newAtom->getType(), "Type was not set for this atom");
+        break;
+      case TremoloKey::Id :
+        lineStream >> oldId;
+        atomIdMap[oldId] = newAtom->getId();
+        break;
+      case TremoloKey::neighbors :
+        readNeighbors(&lineStream,
+            atoi(it->substr(it->find("=") + 1, 1).c_str()), newAtom->getId());
+        break;
+      default :
+        lineStream >> word;
+        atomInfo->set(currentField, word);
+        break;
+    }
+  }
+}
+
+/**
+ * Reads neighbor information for one atom from the input.
+ *
+ * \param stream where to read the information from
+ * \param number of neighbors to read
+ * \param world id of the atom the information belongs to
+ */
+void PdbParser::readNeighbors(stringstream* line, int numberOfNeighbors, int atomId) {
+  int neighborId = 0;
+  for (int i = 0; i < numberOfNeighbors; i++) {
+    *line >> neighborId;
+    // 0 is used to fill empty neighbor positions in the tremolo file.
+    if (neighborId > 0) {
+      additionalAtomData[atomId].neighbors.push_back(neighborId);
+    }
+  }
+}
+
+/**
+ * Checks whether the provided name is within the list of used fields.
+ *
+ * \param field name to check
+ *
+ * \return true if the field name is used
+ */
+bool PdbParser::isUsedField(string fieldName) {
+  bool fieldNameExists = false;
+  for (vector<string>::iterator usedField = usedFields.begin(); usedField != usedFields.end(); usedField++) {
+    if (usedField->substr(0, usedField->find("=")) == fieldName)
+      fieldNameExists = true;
+  }
+
+  return fieldNameExists;
+}
+
+
+/**
+ * Adds the collected neighbor information to the atoms in the world. The atoms
+ * are found by their current ID and mapped to the corresponding atoms with the
+ * Id found in the parsed file.
+ */
+void PdbParser::processNeighborInformation() {
+  if (!isUsedField("neighbors")) {
+    return;
+  }
+
+  for(map<int, TremoloAtomInfoContainer>::iterator currentInfo = additionalAtomData.begin();
+    currentInfo != additionalAtomData.end(); currentInfo++
+  ) {
+    for(vector<int>::iterator neighbor = currentInfo->second.neighbors.begin();
+      neighbor != currentInfo->second.neighbors.end(); neighbor++
+    ) {
+      World::getInstance().getAtom(AtomById(currentInfo->first))
+          ->addBond(World::getInstance().getAtom(AtomById(atomIdMap[*neighbor])));
+    }
+  }
+}
+
+/**
+ * Replaces atom IDs read from the file by the corresponding world IDs. All IDs
+ * IDs of the input string will be replaced; expected separating characters are
+ * "-" and ",".
+ *
+ * \param string in which atom IDs should be adapted
+ *
+ * \return input string with modified atom IDs
+ */
+string PdbParser::adaptIdDependentDataString(string data) {
+  // there might be no IDs
+  if (data == "-") {
+    return "-";
+  }
+
+  char separator;
+  int id;
+  stringstream line, result;
+  line << data;
+
+  line >> id;
+  result << atomIdMap[id];
+  while (line.good()) {
+    line >> separator >> id;
+    result << separator << atomIdMap[id];
+  }
+
+  return result.str();
+}
+
+/**
+ * Corrects the atom IDs in each imprData entry to the corresponding world IDs
+ * as they might differ from the originally read IDs.
+ */
+void PdbParser::adaptImprData() {
+  if (!isUsedField("imprData")) {
+    return;
+  }
+
+  for(map<int, TremoloAtomInfoContainer>::iterator currentInfo = additionalAtomData.begin();
+    currentInfo != additionalAtomData.end(); currentInfo++
+  ) {
+    currentInfo->second.imprData = adaptIdDependentDataString(currentInfo->second.imprData);
+  }
+}
+
+/**
+ * Corrects the atom IDs in each torsion entry to the corresponding world IDs
+ * as they might differ from the originally read IDs.
+ */
+void PdbParser::adaptTorsion() {
+  if (!isUsedField("torsion")) {
+    return;
+  }
+
+  for(map<int, TremoloAtomInfoContainer>::iterator currentInfo = additionalAtomData.begin();
+    currentInfo != additionalAtomData.end(); currentInfo++
+  ) {
+    currentInfo->second.torsion = adaptIdDependentDataString(currentInfo->second.torsion);
+  }
+}
+
+
+TremoloAtomInfoContainer::TremoloAtomInfoContainer() :
+  F("0"),
+  stress("0"),
+  imprData("-"),
+  GroupMeasureTypeNo("0"),
+  extType("-"),
+  name("-"),
+  resName("-"),
+  chainID("0"),
+  resSeq("0"),
+  occupancy("0"),
+  tempFactor("0"),
+  segID("0"),
+  Charge("0"),
+  charge("0"),
+  GrpTypeNo("0"),
+  torsion("-"),
+  neighbors(vector<int>(0, 5))
+{}
+
+void TremoloAtomInfoContainer::set(TremoloKey::atomDataKey key, string value) {
+  switch (key) {
+    case TremoloKey::F :
+      F = value;
+      break;
+    case TremoloKey::stress :
+      stress = value;
+     break;
+    case TremoloKey::imprData :
+      imprData = value;
+      break;
+    case TremoloKey::GroupMeasureTypeNo :
+      GroupMeasureTypeNo = value;
+      break;
+    case TremoloKey::extType :
+      extType = value;
+      break;
+    case TremoloKey::name :
+      name = value;
+      break;
+    case TremoloKey::resName :
+      resName = value;
+      break;
+    case TremoloKey::chainID :
+      chainID = value;
+      break;
+    case TremoloKey::resSeq :
+      resSeq = value;
+      break;
+    case TremoloKey::occupancy :
+      occupancy = value;
+      break;
+    case TremoloKey::tempFactor :
+      tempFactor = value;
+      break;
+    case TremoloKey::segID :
+      segID = value;
+      break;
+    case TremoloKey::Charge :
+      Charge = value;
+      break;
+    case TremoloKey::charge :
+      charge = value;
+      break;
+    case TremoloKey::GrpTypeNo :
+      GrpTypeNo = value;
+      break;
+    case TremoloKey::torsion :
+      torsion = value;
+      break;
+    default :
+      cout << "Unknown key: " << key << ", value: " << value << endl;
+      break;
+  }
+}
+
+string TremoloAtomInfoContainer::get(TremoloKey::atomDataKey key) {
+  switch (key) {
+    case TremoloKey::F :
+      return F;
+    case TremoloKey::stress :
+      return stress;
+    case TremoloKey::imprData :
+      return imprData;
+    case TremoloKey::GroupMeasureTypeNo :
+      return GroupMeasureTypeNo;
+    case TremoloKey::extType :
+      return extType;
+    case TremoloKey::name :
+      return name;
+    case TremoloKey::resName :
+      return resName;
+    case TremoloKey::chainID :
+      return chainID;
+    case TremoloKey::resSeq :
+      return resSeq;
+    case TremoloKey::occupancy :
+      return occupancy;
+    case TremoloKey::tempFactor :
+      return tempFactor;
+    case TremoloKey::segID :
+      return segID;
+    case TremoloKey::Charge :
+      return Charge;
+    case TremoloKey::charge :
+      return charge;
+    case TremoloKey::GrpTypeNo :
+      return GrpTypeNo;
+    case TremoloKey::torsion :
+      return torsion;
+    default :
+      cout << "Unknown key: " << key << endl;
+      return "";
+  }
+}
+
Index: src/Parser/PdbParser.hpp
===================================================================
--- src/Parser/PdbParser.hpp	(revision 3ae731331613c6806f4a83a01d7417d215c6877a)
+++ src/Parser/PdbParser.hpp	(revision 3ae731331613c6806f4a83a01d7417d215c6877a)
@@ -0,0 +1,125 @@
+/*
+ * PdbParser.hpp
+ *
+ *  Created on: Aug 17, 2010
+ *      Author: heber
+ */
+
+#ifndef PDBPARSER_HPP_
+#define PDBPARSER_HPP_
+
+#include <string>
+#include "Parser/FormatParser.hpp"
+
+/**
+ * Known keys for the ATOMDATA line.
+ */
+class TremoloKey {
+public:
+  enum atomDataKey {
+    noKey,
+    x,
+    u,
+    F,
+    stress,
+    Id,
+    neighbors,
+    imprData,
+    GroupMeasureTypeNo,
+    Type,
+    extType,
+    name,
+    resName,
+    chainID,
+    resSeq,
+    occupancy,
+    tempFactor,
+    segID,
+    Charge,
+    charge,
+    GrpTypeNo,
+    torsion
+  };
+};
+
+/**
+ * Holds tremolo-specific information which is not store in the atom class.
+ */
+class TremoloAtomInfoContainer {
+public:
+  TremoloAtomInfoContainer();
+  void set(TremoloKey::atomDataKey key, std::string value);
+  std::string get(TremoloKey::atomDataKey key);
+  std::string F;
+  std::string stress;
+  std::string imprData;
+  std::string GroupMeasureTypeNo;
+  std::string extType;
+  std::string name;
+  std::string resName;
+  std::string chainID;
+  std::string resSeq;
+  std::string occupancy;
+  std::string tempFactor;
+  std::string segID;
+  std::string Charge;
+  std::string charge;
+  std::string GrpTypeNo;
+  std::string torsion;
+  std::vector<int> neighbors;
+};
+
+/**
+ * Loads a tremolo file into the World and saves the World as a tremolo file.
+ */
+class PdbParser : public FormatParser
+{
+public:
+  PdbParser();
+  ~PdbParser();
+  void load(std::istream* file);
+  void save(std::ostream* file);
+  void setFieldsForSave(std::string atomDataLine);
+
+
+private:
+  void readAtomDataLine(string line);
+  void parseAtomDataKeysLine(string line, int offset);
+  void readNeighbors(std::stringstream* line, int numberOfNeighbors, int atomId);
+  void processNeighborInformation();
+  void adaptImprData();
+  void adaptTorsion();
+  std::string adaptIdDependentDataString(std::string data);
+  bool isUsedField(std::string fieldName);
+  void writeNeighbors(std::ostream* file, int numberOfNeighbors, atom* currentAtom);
+  void saveLine(std::ostream* file, atom* currentAtom);
+
+  /**
+   * Map to associate the known keys with numbers.
+   */
+  std::map<std::string, TremoloKey::atomDataKey> knownKeys;
+
+  /**
+   * Fields used in the tremolo file.
+   */
+  std::vector<std::string> usedFields;
+
+  /**
+   * Data which is currently not stored in atoms but was provided by the input
+   * file.
+   */
+  std::map<int, TremoloAtomInfoContainer> additionalAtomData;
+
+  /**
+   * Default additional atom data.
+   */
+  TremoloAtomInfoContainer defaultAdditionalData;
+
+  /**
+   * Maps original atom IDs received from the parsed file to atom IDs in the
+   * world.
+   */
+  std::map<int, int> atomIdMap;
+};
+
+#endif /* PDBPARSER_HPP_ */
