72 cout <<
"The VOTCA pdb reader attempts to follow the official format: "
74 cout <<
"http://www.wwpdb.org/documentation/file-format" << endl;
76 cout <<
"NOTE the element symbol is important for associating a mass with "
78 cout <<
"each atom, if no element symbol is specified the atom name will be"
80 cout <<
"used and assumed to be an element symbol." << endl;
81 cout <<
"The pdb file format does not support pseudo atoms such as a CH3 "
83 cout <<
"and thus VOTCA cannot read such atoms in when using a .pdb file."
85 cout <<
"If you need to use pseudo atoms consider using a different file "
87 cout <<
"format such as the lammps data format." << endl;
94 vector<vector<Index>> bond_pairs;
100 vector<Bead *> bead_vec;
104 Index bead_count = 0;
107 string a, b, c, alpha, beta, gamma;
110 a = string(line, (7 - 1), 9);
112 b = string(line, (16 - 1), 9);
114 c = string(line, (25 - 1), 9);
116 alpha = string(line, (34 - 1), 7);
118 beta = string(line, (41 - 1), 7);
120 gamma = string(line, (48 - 1), 7);
124 }
catch (std::out_of_range &) {
125 throw std::runtime_error(
"Misformated pdb file in CRYST1 line");
127 boost::algorithm::trim(a);
128 boost::algorithm::trim(b);
129 boost::algorithm::trim(c);
130 boost::algorithm::trim(alpha);
131 boost::algorithm::trim(beta);
132 boost::algorithm::trim(gamma);
135 throw std::runtime_error(
136 "Non cubical box in pdb file not implemented, yet!");
138 double aa = stod(a) / 10.0;
139 double bb = stod(b) / 10.0;
140 double cc = stod(c) / 10.0;
141 Eigen::Matrix3d box = Eigen::Matrix3d::Zero();
142 box.diagonal() = Eigen::Vector3d(aa, bb, cc);
147 vector<string> bonded_atms;
154 ss << string(line.substr(6));
160 bonded_atms.push_back(temp_atm);
166 bonded_atms.push_back(temp_atm);
169 }
catch (std::out_of_range &) {
170 throw std::runtime_error(
"Misformated pdb file in CONECT line\n" +
174 vector<Index> row(2);
175 boost::algorithm::trim(atm1);
176 Index at1 = boost::lexical_cast<Index>(atm1);
179 for (
auto &bonded_atm : bonded_atms) {
180 Index at2 = boost::lexical_cast<Index>(bonded_atm);
186 bond_pairs.push_back(row);
194 string x, y, z, resNum, resName, atName;
195 string charge, elem_sym;
206 atName = string(line, (13 - 1), 4);
210 resName = string(line, (18 - 1), 3);
214 resNum = string(line, (23 - 1), 4);
218 x = string(line, (31 - 1), 8);
220 y = string(line, (39 - 1), 8);
222 z = string(line, (47 - 1), 8);
230 elem_sym = string(line, (77 - 1), 2);
232 charge = string(line, (79 - 1), 2);
233 }
catch (std::out_of_range &) {
234 string err_msg =
"Misformated pdb file in atom line # " +
235 boost::lexical_cast<string>(bead_count) +
236 "\n the correct pdb file format requires 80 "
237 "characters in width (spaces matter). Furthermore, " +
238 "\n to read the topology in from a .pdb file the "
239 "following attributes must be " +
242 "\n Atom Name, Residue Name, Residue Number, x, y, z, "
244 "charge (optional) \n";
245 throw std::runtime_error(err_msg);
247 boost::algorithm::trim(atName);
248 boost::algorithm::trim(resName);
249 boost::algorithm::trim(resNum);
250 boost::algorithm::trim(x);
251 boost::algorithm::trim(y);
252 boost::algorithm::trim(z);
253 boost::algorithm::trim(elem_sym);
254 boost::algorithm::trim(charge);
263 resnr = boost::lexical_cast<Index>(resNum);
264 }
catch (bad_lexical_cast &) {
265 throw std::runtime_error(
266 "Cannot convert resNum='" + resNum +
267 "' to int, that usallly means: misformated pdb file");
271 cout <<
"WARNING no resname specified, assigning name to: UNK"
277 throw std::runtime_error(
"Misformated pdb file, resnr has to be > 0");
288 cout <<
"Warning: residue numbers not continuous, create dummy "
289 "residue with residue number "
305 cout <<
"WARNING no charge was specified for " << endl;
306 cout << line << endl;
307 cout <<
"Assuming a charge of 0" << endl;
310 if (elem_sym ==
"") {
311 cout <<
"WARNING no element was specified, assuming atom name is "
313 cout <<
"an element symbol: " << atName << endl;
317 throw std::runtime_error(
318 "Atom name is not an element symbol, so substitution fails, "
319 "the element is needed in order to resolve the mass.");
333 elements.
getMass(elem_sym), ch);
335 b = top.
getBead(bead_count - 1);
339 Eigen::Vector3d(stod(x) / 10.0, stod(y) / 10.0, stod(z) / 10.0));
341 bead_vec.push_back(b);
344 if ((line ==
"ENDMDL") || (line ==
"END") || (
fl_.eof())) {
350 throw std::runtime_error(
351 "number of beads in topology and trajectory differ");
366 map<Index, Index> atm_molecule;
370 unordered_map<Index, list<Index>> molecule_atms;
376 for (
auto &bond_pair : bond_pairs) {
378 Index atm_id1 = bond_pair.at(0);
379 Index atm_id2 = bond_pair.at(1);
382 auto mol_iter1 = atm_molecule.find(atm_id1);
383 auto mol_iter2 = atm_molecule.find(atm_id2);
386 if (mol_iter1 == atm_molecule.end() && mol_iter2 == atm_molecule.end()) {
388 list<Index> atms_in_mol;
389 atms_in_mol.push_back(atm_id1);
390 atms_in_mol.push_back(atm_id2);
391 molecule_atms[mol_index] = atms_in_mol;
393 atm_molecule[atm_id1] = mol_index;
394 atm_molecule[atm_id2] = mol_index;
399 }
else if (mol_iter1 == atm_molecule.end()) {
401 molecule_atms[mol_iter2->second].push_back(atm_id1);
403 atm_molecule[atm_id1] = mol_iter2->second;
406 }
else if (mol_iter2 == atm_molecule.end()) {
408 molecule_atms[mol_iter1->second].push_back(atm_id2);
410 atm_molecule[atm_id2] = mol_iter1->second;
412 }
else if (mol_iter1 != mol_iter2) {
419 if (mol_iter1->second < mol_iter2->second) {
420 chosen_mol = mol_iter1->second;
421 obsolete_mol = mol_iter2->second;
423 chosen_mol = mol_iter2->second;
424 obsolete_mol = mol_iter1->second;
429 for (
Index &atm_temp : molecule_atms[obsolete_mol]) {
431 atm_molecule[atm_temp] = chosen_mol;
436 molecule_atms[chosen_mol].splice(molecule_atms[chosen_mol].end(),
437 molecule_atms[obsolete_mol]);
440 molecule_atms.erase(obsolete_mol);
444 cerr <<
"Consistency check for pdbreader" << endl;
446 for (
auto lis = molecule_atms.begin(); lis != molecule_atms.end(); lis++) {
447 cerr <<
"Molecule " << i << endl;
449 for (
auto atm_ind = lis->second.begin(); atm_ind != lis->second.end();
451 cerr << *atm_ind <<
" ";
465 map<Index, Molecule *> mol_map;
471 map<Index, Index> mol_reInd_map;
474 for (
auto mol = molecule_atms.begin(); mol != molecule_atms.end(); mol++) {
476 string mol_name =
"PDB Molecule " + boost::lexical_cast<string>(ind);
479 mol_map[mol->first] = mi;
480 mol_reInd_map[mol->first] = ind;
483 list<Index> atm_list = molecule_atms[mol->first];
484 for (
Index &atm_temp : atm_list) {
486 string residuename =
"DUM";
487 mi->
AddBead(bead_vec.at(atm_temp - 1), residuename);
494 for (
auto &bond_pair : bond_pairs) {
496 Index atm_id1 = bond_pair.at(0);
497 Index atm_id2 = bond_pair.at(1);
500 Index mol_ind = atm_molecule[atm_id1];
504 Index bead_id1 = bead_vec.at(atm_id1 - 1)->getId();
505 Index bead_id2 = bead_vec.at(atm_id2 - 1)->getId();