source: src/Parser/TremoloParser.cpp@ 9784cf

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 9784cf was bd2390, checked in by Frederik Heber <heber@…>, 14 years ago

BUGFIX: new boost::filesystem led to non-parsing of files.

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