source: src/Parser/TremoloParser.cpp@ 3f9eba

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 3f9eba 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
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 "CodePatterns/MemDebug.hpp"
21
22#include "CodePatterns/Assert.hpp"
23#include "CodePatterns/Log.hpp"
24#include "CodePatterns/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["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;
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);
70
71 // and noKey afterwards(!) such that it is not used in usedFields
72 knownKeys[" "] = TremoloKey::noKey; // with this we can detect invalid keys
73}
74
75/**
76 * Destructor.
77 */
78TremoloParser::~TremoloParser() {
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
94 // reset atomIdMap, for we now get new serials
95 atomIdMap.clear();
96 usedFields.clear();
97
98 molecule *newmol = World::getInstance().createMolecule();
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);
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) != '#') {
111 readAtomDataLine(line, newmol);
112 }
113 }
114
115 processNeighborInformation();
116 adaptImprData();
117 adaptTorsion();
118}
119
120/**
121 * Saves the \a atoms into as a tremolo file.
122 *
123 * \param file where to save the state
124 * \param atoms atoms to store
125 */
126void TremoloParser::save(ostream* file, const std::vector<atom *> &AtomList) {
127 DoLog(0) && (Log() << Verbose(0) << "Saving changes to tremolo." << std::endl);
128
129 vector<atom*>::const_iterator atomIt;
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
169 *file << currentAtom->at(0) << "\t";
170 *file << currentAtom->at(1) << "\t";
171 *file << currentAtom->at(2) << "\t";
172 break;
173 case TremoloKey::u :
174 // for the moment, assume there are always three dimensions
175 *file << currentAtom->AtomicVelocity[0] << "\t";
176 *file << currentAtom->AtomicVelocity[1] << "\t";
177 *file << currentAtom->AtomicVelocity[2] << "\t";
178 break;
179 case TremoloKey::Type :
180 *file << currentAtom->getType()->getSymbol() << "\t";
181 break;
182 case TremoloKey::Id :
183 *file << currentAtom->getId()+1 << "\t";
184 break;
185 case TremoloKey::neighbors :
186 writeNeighbors(file, atoi(it->substr(it->find("=") + 1, 1).c_str()), currentAtom);
187 break;
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;
198 default :
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 }
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()
225 ? (*currentBond)->GetOtherAtom(currentAtom)->getId()+1 : 0) << "\t";
226 if (currentBond != currentAtom->ListOfBonds.end())
227 ++currentBond;
228 }
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);
242 usedFields.clear();
243 while (lineStream.good()) {
244 lineStream >> keyword;
245 if (knownKeys[keyword.substr(0, keyword.find("="))] == TremoloKey::noKey) {
246 // TODO: throw exception about unknown key
247 cout << "Unknown key: " << keyword << " is not part of the tremolo format specification." << endl;
248 break;
249 }
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
259 * \param *newmol molecule to add atom to
260 */
261void TremoloParser::readAtomDataLine(string line, molecule *newmol = NULL) {
262 vector<string>::iterator it;
263 stringstream lineStream;
264 atom* newAtom = World::getInstance().createAtom();
265 TremoloAtomInfoContainer *atomInfo = NULL;
266 additionalAtomData[newAtom->getId()] = TremoloAtomInfoContainer(); // fill with default values
267 atomInfo = &additionalAtomData[newAtom->getId()];
268 TremoloKey::atomDataKey currentField;
269 string word;
270 int oldId;
271 double tmp;
272
273 lineStream << line;
274 for (it = usedFields.begin(); it < usedFields.end(); it++) {
275 currentField = knownKeys[it->substr(0, it->find("="))];
276 switch (currentField) {
277 case TremoloKey::x :
278 // for the moment, assume there are always three dimensions
279 for (int i=0;i<NDIM;i++) {
280 lineStream >> tmp;
281 newAtom->set(i, tmp);
282 }
283 break;
284 case TremoloKey::u :
285 // for the moment, assume there are always three dimensions
286 lineStream >> newAtom->AtomicVelocity[0];
287 lineStream >> newAtom->AtomicVelocity[1];
288 lineStream >> newAtom->AtomicVelocity[2];
289 break;
290 case TremoloKey::Type :
291 char type[3];
292 lineStream >> type;
293 newAtom->setType(World::getInstance().getPeriode()->FindElement(type));
294 ASSERT(newAtom->getType(), "Type was not set for this atom");
295 break;
296 case TremoloKey::Id :
297 lineStream >> oldId;
298 atomIdMap[oldId] = newAtom->getId();
299 break;
300 case TremoloKey::neighbors :
301 readNeighbors(&lineStream,
302 atoi(it->substr(it->find("=") + 1, 1).c_str()), newAtom->getId());
303 break;
304 default :
305 lineStream >> word;
306 atomInfo->set(currentField, word);
307 break;
308 }
309 }
310 if (newmol != NULL)
311 newmol->AddAtom(newAtom);
312}
313
314/**
315 * Reads neighbor information for one atom from the input.
316 *
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
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) {
327// std::cout << "Atom with global id " << atomId << " has neighbour with serial " << neighborId << std::endl;
328 additionalAtomData[atomId].neighbors.push_back(neighborId);
329 }
330 }
331}
332
333/**
334 * Checks whether the provided name is within the list of used fields.
335 *
336 * \param field name to check
337 *
338 * \return true if the field name is used
339 */
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 }
346
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 ) {
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;
376 }
377 }
378}
379
380/**
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 ",".
384 *
385 * \param string in which atom IDs should be adapted
386 *
387 * \return input string with modified atom IDs
388 */
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();
408}
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 }
424}
425
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.