source: src/Parser/TremoloParser.cpp@ 6f5dfe

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

TremoloParser can now deal with copied molecules/atoms.

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