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

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

new class FormatParserStorage takes care of allocation, uniqueness and de-allocation.

This is necessary as otherwise ofstream have to be given to each Parser on instantiation. I.e. files are written over at the start of the program. Critical exits will thus results in empty files.

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