source: src/Parser/TremoloParser.cpp@ bcf653

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 bcf653 was bcf653, checked in by Frederik Heber <heber@…>, 15 years ago

Added copyright note to each .cpp file and an extensive one to builder.cpp.

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