source: src/Parser/PdbParser.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: 12.4 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 * PdbParser.cpp
10 *
11 * Created on: Aug 17, 2010
12 * Author: heber
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 "PdbParser.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
34#include <map>
35#include <vector>
36
37#include <iostream>
38#include <iomanip>
39
40using namespace std;
41
42/**
43 * Constructor.
44 */
45PdbParser::PdbParser() {
46 knownKeys[" "] = PdbKey::noKey; // with this we can detect invalid keys
47 knownKeys["x"] = PdbKey::x;
48 knownKeys["Id"] = PdbKey::Id;
49 knownKeys["Type"] = PdbKey::Type;
50 knownKeys["extType"] = PdbKey::extType;
51 knownKeys["name"] = PdbKey::name;
52 knownKeys["resName"] = PdbKey::resName;
53 knownKeys["chainID"] = PdbKey::chainID;
54 knownKeys["resSeq"] = PdbKey::resSeq;
55 knownKeys["occupancy"] = PdbKey::occupancy;
56 knownKeys["tempFactor"] = PdbKey::tempFactor;
57 knownKeys["segID"] = PdbKey::segID;
58 knownKeys["charge"] = PdbKey::charge;
59}
60
61/**
62 * Destructor.
63 */
64PdbParser::~PdbParser() {
65 additionalAtomData.clear();
66 atomIdMap.clear();
67 knownKeys.clear();
68}
69
70/**
71 * Loads atoms from a tremolo-formatted file.
72 *
73 * \param tremolo file
74 */
75void PdbParser::load(istream* file) {
76 // TODO: PdbParser::load implementation
77 ASSERT(false, "Not implemented yet");
78// string line;
79// string::size_type location;
80//
81// usedFields.clear();
82// while (file->good()) {
83// std::getline(*file, line, '\n');
84// if (usedFields.empty()) {
85// location = line.find("ATOMDATA", 0);
86// if (location != string::npos) {
87// parseAtomDataKeysLine(line, location + 8);
88// }
89// }
90// if (line.length() > 0 && line.at(0) != '#') {
91// readAtomDataLine(line);
92// }
93// }
94//
95// processNeighborInformation();
96// adaptImprData();
97// adaptTorsion();
98}
99
100/**
101 * Saves the World's current state into as a tremolo file.
102 *
103 * \param file where to save the state
104 */
105void PdbParser::save(ostream* file) {
106 DoLog(0) && (Log() << Verbose(0) << "Saving changes to pdb." << std::endl);
107
108 {
109 // add initial remark
110 *file << "REMARK created by molecuilder on ";
111 time_t now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time'
112 // ctime ends in \n\0, we have to cut away the newline
113 std::string time(ctime(&now));
114 size_t pos = time.find('\n');
115 if (pos != 0)
116 *file << time.substr(0,pos);
117 else
118 *file << time;
119 *file << endl;
120 }
121
122 {
123 vector<atom *> AtomList = World::getInstance().getAllAtoms();
124
125 std::vector<int> elementNo(MAX_ELEMENTS,1);
126 char name[MAXSTRINGSIZE];
127
128 // write ATOMs
129 int AtomNo = 1; // serial number starts at 1 in pdb
130 int MolNo = 1; // residue number starts at 1 in pdb
131 for (vector<atom *>::iterator atomIt = AtomList.begin(); atomIt != AtomList.end(); atomIt++) {
132 const size_t Z = (*atomIt)->getType()->getAtomicNumber();
133 sprintf(name, "%2s%02d",(*atomIt)->getType()->getSymbol().c_str(), elementNo[Z]);
134 elementNo[Z] = (elementNo[Z]+1) % 100; // confine to two digits
135 const molecule *mol = (*atomIt)->getMolecule();
136 if (mol == NULL) { // for homeless atoms, MolNo = -1 is reserved
137 MolNo = -1;
138 } else {
139 MolNo = mol->getId();
140 }
141 saveLine(file, *atomIt, name, AtomNo, MolNo);
142 setAtomId((*atomIt)->getId(), AtomNo);
143 AtomNo++;
144 }
145
146 // write CONECTs
147 for (vector<atom *>::iterator atomIt = AtomList.begin(); atomIt != AtomList.end(); atomIt++) {
148 writeNeighbors(file, 4, *atomIt);
149 }
150 }
151
152 // END
153 *file << "END" << endl;
154}
155
156/**
157 * Writes one line of tremolo-formatted data to the provided stream.
158 *
159 * \param stream where to write the line to
160 * \param *currentAtom the atom of which information should be written
161 * \param *name name of atom, i.e. H01
162 * \param AtomNo serial number of atom
163 * \param ResidueNo number of residue
164 */
165void PdbParser::saveLine(ostream* file, const atom* currentAtom, const char *name, const int AtomNo, const int ResidueNo) {
166 *file << "ATOM ";
167 *file << setw(6) << AtomNo; /* atom serial number */
168 *file << setw(1) << " ";
169 *file << setfill(' ') << left << setw(4) << name << right; /* atom name */
170 *file << setw(1) << " ";
171 *file << setfill(' ') << setw(3) << ((currentAtom->getMolecule() != NULL) ? currentAtom->getMolecule()->getName().substr(0,3) : "-"); /* residue name */
172 *file << setw(1) << " ";
173 *file << setfill(' ') << setw(1) << (char)('a'+(unsigned char)(AtomNo % 26)); /* letter for chain */
174 *file << setw(4) << ResidueNo; /* residue sequence number */
175 *file << setw(4) << " ";
176 for (int i=0;i<NDIM;i++) {
177 *file << setw(8) << setprecision(3) << showpoint << currentAtom->at(i); /* positional coordinate in Angstroem */
178 }
179 *file << setw(6) << setprecision(2) << showpoint << (double)currentAtom->getType()->getValence(); /* occupancy */
180 *file << setw(6) << setprecision(2) << showpoint << (double)currentAtom->getType()->getNoValenceOrbitals(); /* temperature factor */
181 *file << noshowpoint;
182 *file << setw(6) << " ";
183 *file << setw(4) << "0";
184 *file << setfill(' ') << setw(2) << currentAtom->getType()->getSymbol();
185 *file << setw(2) << "0";
186
187 *file << endl;
188}
189
190/**
191 * Writes the neighbor information of one atom to the provided stream.
192 *
193 * \param *file where to write neighbor information to
194 * \param MaxnumberOfNeighbors of neighbors
195 * \param *currentAtom to the atom of which to take the neighbor information
196 */
197void PdbParser::writeNeighbors(ostream* file, int MaxnumberOfNeighbors, atom* currentAtom) {
198 if (!currentAtom->ListOfBonds.empty()) {
199 *file << "CONECT";
200 *file << setw(5) << getAtomId(currentAtom->getId());
201 int MaxNo = 0;
202 for(BondList::iterator currentBond = currentAtom->ListOfBonds.begin(); currentBond != currentAtom->ListOfBonds.end(); ++currentBond) {
203 if (MaxNo < MaxnumberOfNeighbors) {
204 *file << setw(5) << getAtomId((*currentBond)->GetOtherAtom(currentAtom)->getId());
205 }
206 MaxNo++;
207 }
208 *file << endl;
209 }
210}
211
212
213/** Retrieves a value from PdbParser::atomIdMap.
214 * \param atomid key
215 * \return value
216 */
217int PdbParser::getAtomId(int atomid) const
218{
219 ASSERT(atomIdMap.find(atomid) != atomIdMap.end(), "PdbParser::getAtomId: atomid not present in Map.");
220 return (atomIdMap.find(atomid)->second);
221}
222
223/** Sets an entry in PdbParser::atomIdMap.
224 * \param localatomid key
225 * \param atomid value
226 * \return true - key not present, false - value present
227 */
228void PdbParser::setAtomId(int localatomid, int atomid)
229{
230 pair<std::map<int,int>::iterator, bool > inserter;
231 inserter = atomIdMap.insert( pair<int, int>(localatomid, atomid) );
232 ASSERT(inserter.second, "PdbParser::setAtomId: atomId already present in Map.");
233}
234
235/**
236 * Reads one data line of a tremolo file and interprets it according to the keys
237 * obtained from the ATOMDATA line.
238 *
239 * \param line to parse as an atom
240 */
241void PdbParser::readAtomDataLine(string line) {
242// vector<string>::iterator it;
243// stringstream lineStream;
244// atom* newAtom = World::getInstance().createAtom();
245// PdbAtomInfoContainer *atomInfo = NULL;
246// additionalAtomData[newAtom->getId()] = *(new PdbAtomInfoContainer);
247// atomInfo = &additionalAtomData[newAtom->getId()];
248// PdbKey::atomDataKey currentField;
249// string word;
250// int oldId;
251// double tmp;
252//
253// lineStream << line;
254// for (it = usedFields.begin(); it < usedFields.end(); it++) {
255// currentField = knownKeys[it->substr(0, it->find("="))];
256// switch (currentField) {
257// case PdbKey::x :
258// // for the moment, assume there are always three dimensions
259// for (int i=0;i<NDIM;i++) {
260// lineStream >> tmp;
261// newAtom->set(i, tmp);
262// }
263// break;
264// case PdbKey::u :
265// // for the moment, assume there are always three dimensions
266// lineStream >> newAtom->AtomicVelocity[0];
267// lineStream >> newAtom->AtomicVelocity[1];
268// lineStream >> newAtom->AtomicVelocity[2];
269// break;
270// case PdbKey::Type :
271// char type[3];
272// lineStream >> type;
273// newAtom->setType(World::getInstance().getPeriode()->FindElement(type));
274// ASSERT(newAtom->getType(), "Type was not set for this atom");
275// break;
276// case PdbKey::Id :
277// lineStream >> oldId;
278// atomIdMap[oldId] = newAtom->getId();
279// break;
280// case PdbKey::neighbors :
281// readNeighbors(&lineStream,
282// atoi(it->substr(it->find("=") + 1, 1).c_str()), newAtom->getId());
283// break;
284// default :
285// lineStream >> word;
286// atomInfo->set(currentField, word);
287// break;
288// }
289// }
290}
291
292/**
293 * Reads neighbor information for one atom from the input.
294 *
295 * \param stream where to read the information from
296 * \param number of neighbors to read
297 * \param world id of the atom the information belongs to
298 */
299void PdbParser::readNeighbors(stringstream* line, int numberOfNeighbors, int atomId) {
300// int neighborId = 0;
301// for (int i = 0; i < numberOfNeighbors; i++) {
302// *line >> neighborId;
303// // 0 is used to fill empty neighbor positions in the tremolo file.
304// if (neighborId > 0) {
305// additionalAtomData[atomId].neighbors.push_back(neighborId);
306// }
307// }
308}
309
310/**
311 * Adds the collected neighbor information to the atoms in the world. The atoms
312 * are found by their current ID and mapped to the corresponding atoms with the
313 * Id found in the parsed file.
314 */
315void PdbParser::processNeighborInformation() {
316// if (!isUsedField("neighbors")) {
317// return;
318// }
319//
320// for(map<int, PdbAtomInfoContainer>::iterator currentInfo = additionalAtomData.begin();
321// currentInfo != additionalAtomData.end(); currentInfo++
322// ) {
323// for(vector<int>::iterator neighbor = currentInfo->second.neighbors.begin();
324// neighbor != currentInfo->second.neighbors.end(); neighbor++
325// ) {
326// World::getInstance().getAtom(AtomById(currentInfo->first))
327// ->addBond(World::getInstance().getAtom(AtomById(atomIdMap[*neighbor])));
328// }
329// }
330}
331
332/**
333 * Replaces atom IDs read from the file by the corresponding world IDs. All IDs
334 * IDs of the input string will be replaced; expected separating characters are
335 * "-" and ",".
336 *
337 * \param string in which atom IDs should be adapted
338 *
339 * \return input string with modified atom IDs
340 */
341string PdbParser::adaptIdDependentDataString(string data) {
342// // there might be no IDs
343// if (data == "-") {
344// return "-";
345// }
346//
347// char separator;
348// int id;
349// stringstream line, result;
350// line << data;
351//
352// line >> id;
353// result << atomIdMap[id];
354// while (line.good()) {
355// line >> separator >> id;
356// result << separator << atomIdMap[id];
357// }
358//
359// return result.str();
360 return "";
361}
362
363
364PdbAtomInfoContainer::PdbAtomInfoContainer() :
365 name("-"),
366 resName("-"),
367 chainID("0"),
368 resSeq("0"),
369 occupancy("0"),
370 tempFactor("0"),
371 segID("0"),
372 charge("0")
373{}
374
375void PdbAtomInfoContainer::set(PdbKey::PdbDataKey key, string value) {
376 switch (key) {
377 case PdbKey::extType :
378 extType = value;
379 break;
380 case PdbKey::name :
381 name = value;
382 break;
383 case PdbKey::resName :
384 resName = value;
385 break;
386 case PdbKey::chainID :
387 chainID = value;
388 break;
389 case PdbKey::resSeq :
390 resSeq = value;
391 break;
392 case PdbKey::occupancy :
393 occupancy = value;
394 break;
395 case PdbKey::tempFactor :
396 tempFactor = value;
397 break;
398 case PdbKey::segID :
399 segID = value;
400 break;
401 case PdbKey::charge :
402 charge = value;
403 break;
404 default :
405 cout << "Unknown key: " << key << ", value: " << value << endl;
406 break;
407 }
408}
409
410string PdbAtomInfoContainer::get(PdbKey::PdbDataKey key) {
411 switch (key) {
412 case PdbKey::extType :
413 return extType;
414 case PdbKey::name :
415 return name;
416 case PdbKey::resName :
417 return resName;
418 case PdbKey::chainID :
419 return chainID;
420 case PdbKey::resSeq :
421 return resSeq;
422 case PdbKey::occupancy :
423 return occupancy;
424 case PdbKey::tempFactor :
425 return tempFactor;
426 case PdbKey::segID :
427 return segID;
428 case PdbKey::charge :
429 return charge;
430 default :
431 cout << "Unknown key: " << key << endl;
432 return "";
433 }
434}
435
Note: See TracBrowser for help on using the repository browser.