source: src/Parser/TremoloParser.cpp@ 8d6d31

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

Added verbose message on save to all derived FormatParser and ChangeTracker.

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