Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Parser/TremoloParser.cpp

    r23fd43 rca331c  
    4141
    4242#include <algorithm>
     43#include <boost/lambda/lambda.hpp>
    4344#include <boost/lexical_cast.hpp>
    4445#include <boost/tokenizer.hpp>
     
    4748#include <map>
    4849#include <sstream>
     50#include <string>
    4951#include <vector>
     52
     53#include <boost/assign/list_of.hpp> // for 'map_list_of()'
     54#include <boost/assert.hpp>
    5055
    5156// declare specialized static variables
     
    5459const ParserTypes FormatParserTrait<tremolo>::type = tremolo;
    5560
     61// static instances
     62std::map<std::string, TremoloKey::atomDataKey> FormatParser<tremolo>::knownKeys =
     63    boost::assign::map_list_of("x",TremoloKey::x)
     64    ("u",TremoloKey::u)
     65    ("F",TremoloKey::F)
     66    ("stress",TremoloKey::stress)
     67    ("Id",TremoloKey::Id)
     68    ("neighbors",TremoloKey::neighbors)
     69    ("imprData",TremoloKey::imprData)
     70    ("GroupMeasureTypeNo",TremoloKey::GroupMeasureTypeNo)
     71    ("type",TremoloKey::type)
     72    ("extType",TremoloKey::extType)
     73    ("name",TremoloKey::name)
     74    ("resName",TremoloKey::resName)
     75    ("chainID",TremoloKey::chainID)
     76    ("resSeq",TremoloKey::resSeq)
     77    ("occupancy",TremoloKey::occupancy)
     78    ("tempFactor",TremoloKey::tempFactor)
     79    ("segID",TremoloKey::segID)
     80    ("Charge",TremoloKey::Charge)
     81    ("charge",TremoloKey::charge)
     82    ("GrpTypeNo",TremoloKey::GrpTypeNo)
     83    ("torsion",TremoloKey::torsion)
     84    (" ",TremoloKey::noKey); // with this we can detect invalid keys
     85
    5686/**
    5787 * Constructor.
     
    6090  FormatParser_common(NULL)
    6191{
    62   knownKeys["x"] = TremoloKey::x;
    63   knownKeys["u"] = TremoloKey::u;
    64   knownKeys["F"] = TremoloKey::F;
    65   knownKeys["stress"] = TremoloKey::stress;
    66   knownKeys["Id"] = TremoloKey::Id;
    67   knownKeys["neighbors"] = TremoloKey::neighbors;
    68   knownKeys["imprData"] = TremoloKey::imprData;
    69   knownKeys["GroupMeasureTypeNo"] = TremoloKey::GroupMeasureTypeNo;
    70   knownKeys["type"] = TremoloKey::type;
    71   knownKeys["extType"] = TremoloKey::extType;
    72   knownKeys["name"] = TremoloKey::name;
    73   knownKeys["resName"] = TremoloKey::resName;
    74   knownKeys["chainID"] = TremoloKey::chainID;
    75   knownKeys["resSeq"] = TremoloKey::resSeq;
    76   knownKeys["occupancy"] = TremoloKey::occupancy;
    77   knownKeys["tempFactor"] = TremoloKey::tempFactor;
    78   knownKeys["segID"] = TremoloKey::segID;
    79   knownKeys["Charge"] = TremoloKey::Charge;
    80   knownKeys["charge"] = TremoloKey::charge;
    81   knownKeys["GrpTypeNo"] = TremoloKey::GrpTypeNo;
    82   knownKeys["torsion"] = TremoloKey::torsion;
    83   knownKeys[" "] = TremoloKey::noKey; // with this we can detect invalid keys
    84 
    8592  createKnownTypesByIdentity();
    8693
     
    9299}
    93100
     101
    94102/**
    95103 * Destructor.
     
    99107  usedFields_save.clear();
    100108  additionalAtomData.clear();
    101   knownKeys.clear();
    102109}
    103110
     
    182189}
    183190
     191struct usedFieldsWeakComparator
     192{
     193  /** Special comparator regards "neighbors=4" and "neighbors=2" as equal
     194   *
     195   * \note This one is used for making usedFields unique, i.e. throwing out the "smaller"
     196   * neighbors.
     197   */
     198  bool operator()(const std::string &a, const std::string &b) const
     199  {
     200    // only compare up to first equality sign
     201    return (a.substr(0, a.find_first_of('=')) == b.substr(0, b.find_first_of('=')));
     202  }
     203};
     204
     205struct usedFieldsSpecialOrderer
     206{
     207  /** Special string comparator that regards "neighbors=4" < "neighbors=2" as true and
     208   * the other way round as false.
     209   *
     210   * Here, we implement the operator "\a < \b" in a special way to allow the
     211   * above.
     212   *
     213   * \note This one is used for sorting usedFields in preparation for making it unique.
     214   */
     215  bool operator()(const std::string &a, const std::string &b) const
     216  {
     217    // only compare up to first equality sign
     218    size_t a_equality = a.find_first_of('=');
     219    size_t b_equality = b.find_first_of('=');
     220    // if key before equality is not equal, return whether it is smaller or not
     221    if (a.substr(0, a_equality) != b.substr(0, b_equality)) {
     222      return a.substr(0, a_equality) < b.substr(0, b_equality);
     223    } else { // now we know that the key before equality is the same in either string
     224      // if one of them has no equality, the one with equality must go before
     225      if ((a_equality != std::string::npos) && (b_equality == std::string::npos))
     226        return true;
     227      if ((a_equality == std::string::npos) && (b_equality != std::string::npos))
     228        return false;
     229      // if both don't have equality (and the token before is equal), it is not "<" but "=="
     230      if ((a_equality == std::string::npos) && (b_equality == std::string::npos))
     231        return false;
     232      // if now both have equality sign, the larger value after it, must come first
     233      return a.substr(a_equality, std::string::npos) > b.substr(b_equality, std::string::npos);
     234    }
     235  }
     236};
     237
    184238/** Helper function to make \given fields unique while preserving the order of first appearance.
    185239 *
     
    191245 * @param fields usedFields to make unique while preserving order of appearance
    192246 */
    193 void FormatParser< tremolo >::makeUsedFieldsUnique(usedFields_t &fields)
     247void FormatParser< tremolo >::makeUsedFieldsUnique(usedFields_t &fields) const
    194248{
    195249  // std::unique only removes if predecessor is equal, not over whole range, hence do it manually
    196   usedFields_t temp_fields(usedFields_save);
    197   std::sort(temp_fields.begin(), temp_fields.end());
     250  usedFields_t temp_fields(fields);
     251  usedFieldsSpecialOrderer SpecialOrderer;
     252  usedFieldsWeakComparator WeakComparator;
     253  std::sort(temp_fields.begin(), temp_fields.end(), SpecialOrderer);
    198254  usedFields_t::iterator it =
    199       std::unique(temp_fields.begin(), temp_fields.end()); // skips all duplicates in the vector
     255      std::unique(temp_fields.begin(), temp_fields.end(), WeakComparator);
    200256  temp_fields.erase(it, temp_fields.end());
    201   usedFields_t usedfields(usedFields_save);
    202   usedFields_save.clear();
    203   usedFields_save.reserve(temp_fields.size());
     257  usedFields_t usedfields(fields);
     258  fields.clear();
     259  fields.reserve(temp_fields.size());
    204260  // now go through each usedFields entry, check if in temp_fields and remove there on first occurence
    205261  for (usedFields_t::const_iterator iter = usedfields.begin();
     
    208264        std::find(temp_fields.begin(), temp_fields.end(), *iter);
    209265    if (uniqueiter != temp_fields.end()) {
    210       usedFields_save.push_back(*iter);
     266      fields.push_back(*iter);
    211267      // add only once to ATOMDATA
    212268      temp_fields.erase(uniqueiter);
     
    441497    if (knownKeys[keyword.substr(0, keyword.find("="))] == TremoloKey::noKey) {
    442498      // TODO: throw exception about unknown key
    443       cout << "Unknown key: " << keyword << " is not part of the tremolo format specification." << endl;
     499      cout << "Unknown key: " << keyword.substr(0, keyword.find("=")) << " is not part of the tremolo format specification." << endl;
     500      throw IllegalParserKeyException();
    444501      break;
    445502    }
     
    449506}
    450507
     508/**
     509 * Tests whether the keys from the ATOMDATA line can be read correctly.
     510 *
     511 * \param line to parse the keys from
     512 */
     513bool FormatParser< tremolo >::testParseAtomDataKeysLine(
     514    const std::string &line) {
     515  std::string keyword;
     516  std::stringstream lineStream;
     517
     518  // check string after ATOMDATA
     519  const std::string AtomData("ATOMDATA");
     520  const size_t AtomDataOffset = line.find(AtomData, 0);
     521  if (AtomDataOffset == std::string::npos)
     522    lineStream << line;
     523  else
     524    lineStream << line.substr(AtomDataOffset + AtomData.length());
     525  while (lineStream.good()) {
     526    lineStream >> keyword;
     527    //LOG(2, "DEBUG: Checking key " << keyword.substr(0, keyword.find("=")) << ".");
     528    if (knownKeys[keyword.substr(0, keyword.find("="))] == TremoloKey::noKey)
     529      return false;
     530  }
     531  //LOG(1, "INFO: " << fields);
     532  return true;
     533}
     534
     535std::string FormatParser< tremolo >::getAtomData() const
     536{
     537  std::stringstream output;
     538  std::for_each(usedFields_save.begin(), usedFields_save.end(),
     539      output << boost::lambda::_1 << " ");
     540  const std::string returnstring(output.str());
     541  return returnstring.substr(0, returnstring.find_last_of(" "));
     542}
     543
     544/** Appends the properties per atom to print to .data file by parsing line from
     545 *  \a atomdata_string.
     546 *
     547 *  We just call \sa  FormatParser< tremolo >::parseAtomDataKeysLine().
     548 *
     549 * @param atomdata_string line to parse with space-separated values
     550 */
     551void FormatParser< tremolo >::setAtomData(const std::string &atomdata_string)
     552{
     553  parseAtomDataKeysLine(atomdata_string, 0, usedFields_save);
     554}
     555
    451556/** Sets the properties per atom to print to .data file by parsing line from
    452557 *  \a atomdata_string.
     
    457562 * @param atomdata_string line to parse with space-separated values
    458563 */
    459 void FormatParser< tremolo >::setAtomData(const std::string &atomdata_string)
     564void FormatParser< tremolo >::resetAtomData(const std::string &atomdata_string)
    460565{
    461566  usedFields_save.clear();
Note: See TracChangeset for help on using the changeset viewer.