source: src/Parser/TremoloParser.cpp@ 512f85

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 512f85 was 0bbfa1, checked in by Frederik Heber <heber@…>, 14 years ago

BUGFIX: Parsing a second .data file failed.

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