source: src/Parser/TremoloParser.cpp@ cd7a87

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since cd7a87 was ad011c, checked in by Frederik Heber <heber@…>, 14 years ago

CodePatterns places all includes now in subfolder CodePatterns/.

  • change all includes accordingly.
  • this was necessary as Helpers and Patterns are not very distinctive names for include folders. Already now, we had a conflict between Helpers from CodePatterns and Helpers from this project.
  • changed compilation test in ax_codepatterns.m4 when changing CodePatterns includes.
  • Property mode set to 100644
File size: 13.5 KB
RevLine 
[bcf653]1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010 University of Bonn. All rights reserved.
5 * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
6 */
7
[6bc51d]8/*
9 * TremoloParser.cpp
10 *
11 * Created on: Mar 2, 2010
12 * Author: metzler
13 */
14
[bf3817]15// include config.h
16#ifdef HAVE_CONFIG_H
17#include <config.h>
18#endif
19
[ad011c]20#include "CodePatterns/MemDebug.hpp"
[112b09]21
[ad011c]22#include "CodePatterns/Assert.hpp"
23#include "CodePatterns/Log.hpp"
24#include "CodePatterns/Verbose.hpp"
[9131f3]25#include "TremoloParser.hpp"
26#include "World.hpp"
27#include "atom.hpp"
[b8d4a3]28#include "bond.hpp"
[dc1d9e]29#include "element.hpp"
30#include "molecule.hpp"
[9131f3]31#include "periodentafel.hpp"
[b8d4a3]32#include "Descriptors/AtomIdDescriptor.hpp"
[9131f3]33#include <map>
34#include <vector>
35
[74a444]36#include <iostream>
37#include <iomanip>
[b8d4a3]38
[9131f3]39using namespace std;
40
41/**
42 * Constructor.
43 */
44TremoloParser::TremoloParser() {
[b8d4a3]45 knownKeys["x"] = TremoloKey::x;
46 knownKeys["u"] = TremoloKey::u;
47 knownKeys["F"] = TremoloKey::F;
48 knownKeys["stress"] = TremoloKey::stress;
49 knownKeys["Id"] = TremoloKey::Id;
50 knownKeys["neighbors"] = TremoloKey::neighbors;
51 knownKeys["imprData"] = TremoloKey::imprData;
52 knownKeys["GroupMeasureTypeNo"] = TremoloKey::GroupMeasureTypeNo;
53 knownKeys["Type"] = TremoloKey::Type;
54 knownKeys["extType"] = TremoloKey::extType;
55 knownKeys["name"] = TremoloKey::name;
56 knownKeys["resName"] = TremoloKey::resName;
57 knownKeys["chainID"] = TremoloKey::chainID;
58 knownKeys["resSeq"] = TremoloKey::resSeq;
59 knownKeys["occupancy"] = TremoloKey::occupancy;
60 knownKeys["tempFactor"] = TremoloKey::tempFactor;
61 knownKeys["segID"] = TremoloKey::segID;
62 knownKeys["Charge"] = TremoloKey::Charge;
63 knownKeys["charge"] = TremoloKey::charge;
64 knownKeys["GrpTypeNo"] = TremoloKey::GrpTypeNo;
65 knownKeys["torsion"] = TremoloKey::torsion;
[52baf9]66
67 // default behavior: use all possible keys on output
68 for (std::map<std::string, TremoloKey::atomDataKey>::iterator iter = knownKeys.begin(); iter != knownKeys.end(); ++iter)
69 usedFields.push_back(iter->first);
[ff3c40]70
71 // and noKey afterwards(!) such that it is not used in usedFields
72 knownKeys[" "] = TremoloKey::noKey; // with this we can detect invalid keys
[9131f3]73}
74
75/**
76 * Destructor.
77 */
78TremoloParser::~TremoloParser() {
[b8d4a3]79 usedFields.clear();
80 additionalAtomData.clear();
81 atomIdMap.clear();
82 knownKeys.clear();
83}
84
85/**
86 * Loads atoms from a tremolo-formatted file.
87 *
88 * \param tremolo file
89 */
90void TremoloParser::load(istream* file) {
91 string line;
92 string::size_type location;
93
[0bbfa1]94 // reset atomIdMap, for we now get new serials
95 atomIdMap.clear();
[b8d4a3]96 usedFields.clear();
[0bbfa1]97
[dc1d9e]98 molecule *newmol = World::getInstance().createMolecule();
[bd2390]99 newmol->ActiveFlag = true;
100 // TODO: Remove the insertion into molecule when saving does not depend on them anymore. Also, remove molecule.hpp include
101 World::getInstance().getMolecules()->insert(newmol);
[b8d4a3]102 while (file->good()) {
103 std::getline(*file, line, '\n');
104 if (usedFields.empty()) {
105 location = line.find("ATOMDATA", 0);
106 if (location != string::npos) {
107 parseAtomDataKeysLine(line, location + 8);
108 }
109 }
110 if (line.length() > 0 && line.at(0) != '#') {
[dc1d9e]111 readAtomDataLine(line, newmol);
[b8d4a3]112 }
113 }
114
115 processNeighborInformation();
116 adaptImprData();
117 adaptTorsion();
118}
119
120/**
[73916f]121 * Saves the \a atoms into as a tremolo file.
[b8d4a3]122 *
123 * \param file where to save the state
[73916f]124 * \param atoms atoms to store
[b8d4a3]125 */
[73916f]126void TremoloParser::save(ostream* file, const std::vector<atom *> &AtomList) {
[e97a44]127 DoLog(0) && (Log() << Verbose(0) << "Saving changes to tremolo." << std::endl);
128
[73916f]129 vector<atom*>::const_iterator atomIt;
[b8d4a3]130 vector<string>::iterator it;
131
132 *file << "# ATOMDATA";
133 for (it=usedFields.begin(); it < usedFields.end(); it++) {
134 *file << "\t" << *it;
135 }
136 *file << endl;
137 for (atomIt = AtomList.begin(); atomIt != AtomList.end(); atomIt++) {
138 saveLine(file, *atomIt);
139 }
140}
141
142/**
143 * Sets the keys for which data should be written to the stream when save is
144 * called.
145 *
146 * \param string of field names with the same syntax as for an ATOMDATA line
147 * but without the prexix "ATOMDATA"
148 */
149void TremoloParser::setFieldsForSave(std::string atomDataLine) {
150 parseAtomDataKeysLine(atomDataLine, 0);
151}
152
153
154/**
155 * Writes one line of tremolo-formatted data to the provided stream.
156 *
157 * \param stream where to write the line to
158 * \param reference to the atom of which information should be written
159 */
160void TremoloParser::saveLine(ostream* file, atom* currentAtom) {
161 vector<string>::iterator it;
162 TremoloKey::atomDataKey currentField;
163
164 for (it = usedFields.begin(); it != usedFields.end(); it++) {
165 currentField = knownKeys[it->substr(0, it->find("="))];
166 switch (currentField) {
167 case TremoloKey::x :
168 // for the moment, assume there are always three dimensions
[d74077]169 *file << currentAtom->at(0) << "\t";
170 *file << currentAtom->at(1) << "\t";
171 *file << currentAtom->at(2) << "\t";
[b8d4a3]172 break;
173 case TremoloKey::u :
174 // for the moment, assume there are always three dimensions
[d74077]175 *file << currentAtom->AtomicVelocity[0] << "\t";
176 *file << currentAtom->AtomicVelocity[1] << "\t";
177 *file << currentAtom->AtomicVelocity[2] << "\t";
[b8d4a3]178 break;
179 case TremoloKey::Type :
180 *file << currentAtom->getType()->getSymbol() << "\t";
181 break;
182 case TremoloKey::Id :
[dc1d9e]183 *file << currentAtom->getId()+1 << "\t";
[b8d4a3]184 break;
185 case TremoloKey::neighbors :
186 writeNeighbors(file, atoi(it->substr(it->find("=") + 1, 1).c_str()), currentAtom);
187 break;
[74a444]188 case TremoloKey::resSeq :
189 if (additionalAtomData.find(currentAtom->getId()) != additionalAtomData.end()) {
190 *file << additionalAtomData[currentAtom->getId()].get(currentField);
191 } else if (currentAtom->getMolecule() != NULL) {
192 *file << setw(4) << currentAtom->getMolecule()->getId()+1;
193 } else {
194 *file << defaultAdditionalData.get(currentField);
195 }
196 *file << "\t";
197 break;
[b8d4a3]198 default :
[74a444]199 if (additionalAtomData.find(currentAtom->getId()) != additionalAtomData.end()) {
200 *file << additionalAtomData[currentAtom->getId()].get(currentField);
201 } else if (additionalAtomData.find(currentAtom->GetTrueFather()->getId()) != additionalAtomData.end()) {
202 *file << additionalAtomData[currentAtom->GetTrueFather()->getId()].get(currentField);
203 } else {
204 *file << defaultAdditionalData.get(currentField);
205 }
[b8d4a3]206 *file << "\t";
207 break;
208 }
209 }
210
211 *file << endl;
212}
213
214/**
215 * Writes the neighbor information of one atom to the provided stream.
216 *
217 * \param stream where to write neighbor information to
218 * \param number of neighbors
219 * \param reference to the atom of which to take the neighbor information
220 */
221void TremoloParser::writeNeighbors(ostream* file, int numberOfNeighbors, atom* currentAtom) {
222 BondList::iterator currentBond = currentAtom->ListOfBonds.begin();
223 for (int i = 0; i < numberOfNeighbors; i++) {
224 *file << (currentBond != currentAtom->ListOfBonds.end()
[dc1d9e]225 ? (*currentBond)->GetOtherAtom(currentAtom)->getId()+1 : 0) << "\t";
226 if (currentBond != currentAtom->ListOfBonds.end())
[0bbfa1]227 ++currentBond;
[b8d4a3]228 }
[9131f3]229}
230
231/**
232 * Stores keys from the ATOMDATA line.
233 *
234 * \param line to parse the keys from
235 * \param with which offset the keys begin within the line
236 */
237void TremoloParser::parseAtomDataKeysLine(string line, int offset) {
238 string keyword;
239 stringstream lineStream;
240
241 lineStream << line.substr(offset);
[52baf9]242 usedFields.clear();
[9131f3]243 while (lineStream.good()) {
244 lineStream >> keyword;
[b8d4a3]245 if (knownKeys[keyword.substr(0, keyword.find("="))] == TremoloKey::noKey) {
[ecb799]246 // TODO: throw exception about unknown key
[4415da]247 cout << "Unknown key: " << keyword << " is not part of the tremolo format specification." << endl;
248 break;
249 }
[9131f3]250 usedFields.push_back(keyword);
251 }
252}
253
254/**
255 * Reads one data line of a tremolo file and interprets it according to the keys
256 * obtained from the ATOMDATA line.
257 *
258 * \param line to parse as an atom
[dc1d9e]259 * \param *newmol molecule to add atom to
[9131f3]260 */
[dc1d9e]261void TremoloParser::readAtomDataLine(string line, molecule *newmol = NULL) {
[9131f3]262 vector<string>::iterator it;
263 stringstream lineStream;
[4415da]264 atom* newAtom = World::getInstance().createAtom();
[b8d4a3]265 TremoloAtomInfoContainer *atomInfo = NULL;
[24f128]266 additionalAtomData[newAtom->getId()] = TremoloAtomInfoContainer(); // fill with default values
[b8d4a3]267 atomInfo = &additionalAtomData[newAtom->getId()];
268 TremoloKey::atomDataKey currentField;
[9131f3]269 string word;
[b8d4a3]270 int oldId;
[d74077]271 double tmp;
[9131f3]272
273 lineStream << line;
[b8d4a3]274 for (it = usedFields.begin(); it < usedFields.end(); it++) {
[4415da]275 currentField = knownKeys[it->substr(0, it->find("="))];
276 switch (currentField) {
[b8d4a3]277 case TremoloKey::x :
[4415da]278 // for the moment, assume there are always three dimensions
[d74077]279 for (int i=0;i<NDIM;i++) {
280 lineStream >> tmp;
281 newAtom->set(i, tmp);
282 }
[4415da]283 break;
[b8d4a3]284 case TremoloKey::u :
[4415da]285 // for the moment, assume there are always three dimensions
[d74077]286 lineStream >> newAtom->AtomicVelocity[0];
287 lineStream >> newAtom->AtomicVelocity[1];
288 lineStream >> newAtom->AtomicVelocity[2];
[4415da]289 break;
[b8d4a3]290 case TremoloKey::Type :
[4415da]291 char type[3];
292 lineStream >> type;
293 newAtom->setType(World::getInstance().getPeriode()->FindElement(type));
[b8d4a3]294 ASSERT(newAtom->getType(), "Type was not set for this atom");
[4415da]295 break;
[b8d4a3]296 case TremoloKey::Id :
297 lineStream >> oldId;
298 atomIdMap[oldId] = newAtom->getId();
[4415da]299 break;
[b8d4a3]300 case TremoloKey::neighbors :
301 readNeighbors(&lineStream,
302 atoi(it->substr(it->find("=") + 1, 1).c_str()), newAtom->getId());
[9131f3]303 break;
304 default :
305 lineStream >> word;
[b8d4a3]306 atomInfo->set(currentField, word);
[9131f3]307 break;
308 }
309 }
[dc1d9e]310 if (newmol != NULL)
311 newmol->AddAtom(newAtom);
[6bc51d]312}
[9131f3]313
[b8d4a3]314/**
315 * Reads neighbor information for one atom from the input.
316 *
[0bbfa1]317 * \param line stream where to read the information from
318 * \param numberOfNeighbors number of neighbors to read
319 * \param atomid world id of the atom the information belongs to
[b8d4a3]320 */
321void TremoloParser::readNeighbors(stringstream* line, int numberOfNeighbors, int atomId) {
322 int neighborId = 0;
323 for (int i = 0; i < numberOfNeighbors; i++) {
324 *line >> neighborId;
325 // 0 is used to fill empty neighbor positions in the tremolo file.
326 if (neighborId > 0) {
[0bbfa1]327// std::cout << "Atom with global id " << atomId << " has neighbour with serial " << neighborId << std::endl;
[b8d4a3]328 additionalAtomData[atomId].neighbors.push_back(neighborId);
329 }
330 }
331}
[9131f3]332
333/**
[b8d4a3]334 * Checks whether the provided name is within the list of used fields.
[9131f3]335 *
[b8d4a3]336 * \param field name to check
337 *
338 * \return true if the field name is used
[9131f3]339 */
[b8d4a3]340bool TremoloParser::isUsedField(string fieldName) {
341 bool fieldNameExists = false;
342 for (vector<string>::iterator usedField = usedFields.begin(); usedField != usedFields.end(); usedField++) {
343 if (usedField->substr(0, usedField->find("=")) == fieldName)
344 fieldNameExists = true;
345 }
[9131f3]346
[b8d4a3]347 return fieldNameExists;
348}
349
350
351/**
352 * Adds the collected neighbor information to the atoms in the world. The atoms
353 * are found by their current ID and mapped to the corresponding atoms with the
354 * Id found in the parsed file.
355 */
356void TremoloParser::processNeighborInformation() {
357 if (!isUsedField("neighbors")) {
358 return;
359 }
360
361 for(map<int, TremoloAtomInfoContainer>::iterator currentInfo = additionalAtomData.begin();
362 currentInfo != additionalAtomData.end(); currentInfo++
363 ) {
[0bbfa1]364 if (!currentInfo->second.neighbors_processed) {
365 for(vector<int>::iterator neighbor = currentInfo->second.neighbors.begin();
366 neighbor != currentInfo->second.neighbors.end(); neighbor++
367 ) {
368// std::cout << "Creating bond between ("
369// << currentInfo->first
370// << ") and ("
371// << atomIdMap[*neighbor] << "|" << *neighbor << ")" << std::endl;
372 World::getInstance().getAtom(AtomById(currentInfo->first))
373 ->addBond(World::getInstance().getAtom(AtomById(atomIdMap[*neighbor])));
374 }
375 currentInfo->second.neighbors_processed = true;
[9131f3]376 }
377 }
[6bc51d]378}
379
[9131f3]380/**
[b8d4a3]381 * Replaces atom IDs read from the file by the corresponding world IDs. All IDs
382 * IDs of the input string will be replaced; expected separating characters are
383 * "-" and ",".
[9131f3]384 *
[b8d4a3]385 * \param string in which atom IDs should be adapted
386 *
387 * \return input string with modified atom IDs
[9131f3]388 */
[b8d4a3]389string TremoloParser::adaptIdDependentDataString(string data) {
390 // there might be no IDs
391 if (data == "-") {
392 return "-";
393 }
394
395 char separator;
396 int id;
397 stringstream line, result;
398 line << data;
399
400 line >> id;
401 result << atomIdMap[id];
402 while (line.good()) {
403 line >> separator >> id;
404 result << separator << atomIdMap[id];
405 }
406
407 return result.str();
[6bc51d]408}
[b8d4a3]409
410/**
411 * Corrects the atom IDs in each imprData entry to the corresponding world IDs
412 * as they might differ from the originally read IDs.
413 */
414void TremoloParser::adaptImprData() {
415 if (!isUsedField("imprData")) {
416 return;
417 }
418
419 for(map<int, TremoloAtomInfoContainer>::iterator currentInfo = additionalAtomData.begin();
420 currentInfo != additionalAtomData.end(); currentInfo++
421 ) {
422 currentInfo->second.imprData = adaptIdDependentDataString(currentInfo->second.imprData);
423 }
[6bc51d]424}
[4415da]425
[b8d4a3]426/**
427 * Corrects the atom IDs in each torsion entry to the corresponding world IDs
428 * as they might differ from the originally read IDs.
429 */
430void TremoloParser::adaptTorsion() {
431 if (!isUsedField("torsion")) {
432 return;
433 }
434
435 for(map<int, TremoloAtomInfoContainer>::iterator currentInfo = additionalAtomData.begin();
436 currentInfo != additionalAtomData.end(); currentInfo++
437 ) {
438 currentInfo->second.torsion = adaptIdDependentDataString(currentInfo->second.torsion);
439 }
440}
441
Note: See TracBrowser for help on using the repository browser.