void checkStructures() { // fragment DB if (frag_db == 0) { frag_db = new FragmentDB; } Log.info() << "system contains " << S.countAtoms() << " atoms." << endl; // building bonds S.apply(frag_db->build_bonds); // checking residues Log.info() << "checking system" << endl; ResidueChecker check(*frag_db); S.apply(check); // Check residue energies double energy_limit = 500.0; S.deselect(); amber.setup(S); ResidueIterator it = S.beginResidue(); for (; +it; ++it) { it->select(); amber.updateEnergy(); double residue_energy = amber.getStretchEnergy() + amber.getBendEnergy() + amber.getVdWEnergy(); if (residue_energy > energy_limit) { Log.info() << "suspicious energies in residue " << it->getFullName() << ":" << it->getID() << " " << residue_energy << " kJ/mol (bend: " << amber.getBendEnergy() << " kJ/mol, stretch: " << amber.getStretchEnergy() << " kJ/mol, vdW: " << amber.getVdWEnergy() << " kJ/mol)" << endl; } it->deselect(); double quality = std::max(0.0, std::min(1.0, (energy_limit - residue_energy) / energy_limit)); for (PDBAtomIterator ai = it->beginPDBAtom(); +ai; ++ai) { ai->setOccupancy(quality); } } }
void setup() { // fragment DB if (frag_db == 0) { frag_db = new FragmentDB; } // create force field Log.info() << "setting up force field" << endl; if (verbose) { Log.info() << "force field parameters are read from " << FF_filename << endl; } S.deselect(); amber.options[AmberFF::Option::FILENAME] = FF_filename; if (!amber.setup(S)) { Log.error() << "Setup failed! Abort." << endl; exit(10); } }
int main(int argc, char** argv) { Log.setPrefix(cout, "[%T] "); Log.setPrefix(cerr, "[%T] ERROR: "); // issue a usage hint if called without parameters if (argc != 3) { Log << argv[0] << " <PDB infile> <PDB outfile>" << endl; return 1; } // open a PDB file with the name of the first argument PDBFile file(argv[1]); if (!file) { // if file does not exist: complain and abort Log.error() << "error opening " << argv[1] << " for input." << endl; return 2; } // create a system and read the contents of the PDB file System S; file >> S; file.close(); // print the number of atoms read from the file Log << "read " << S.countAtoms() << " atoms." << endl; // now we open a fragment database Log << "reading fragment DB..." << endl; FragmentDB fragment_db(""); // and normalize the atom names, i.e. we convert different // naming standards to the PDB naming scheme - just in case! Log << "normalizing names..." << endl; S.apply(fragment_db.normalize_names); // now we add any missing hydrogens to the residues // the data on the hydrogen positions stems from the // fragment database. However the hydrogen positions // created in this way are only good estimates Log << "creating missing atoms..." << endl; S.apply(fragment_db.add_hydrogens); Log << "added " << fragment_db.add_hydrogens.getNumberOfInsertedAtoms() << " atoms" << endl; // now we create the bonds between the atoms (PDB files hardly // ever contain a complete set of CONECT records) Log << "building bonds..." << endl; S.apply(fragment_db.build_bonds); // now we check whether the model we built is consistent // The ResidueChecker checks for charges, bond lengths, // and missing atoms Log << "checking the built model..." << endl; ResidueChecker checker(fragment_db); S.apply(checker); // now we create an AMBER force field Log << "setting up force field..." << endl; AmberFF FF; // we then select all hydrogens (element(H)) // using a specialized processor (Selector) S.deselect(); FF.setup(S); Selector selector("element(H)"); S.apply(selector); // just for curiosity: check how many atoms we are going // to optimize Log << "optimizing " << FF.getNumberOfMovableAtoms() << " out of " << S.countAtoms() << " atoms" << endl; // now we create a minimizer object that uses a conjugate // gradient algorithm to optimize the atom positions ConjugateGradientMinimizer minimizer; // calculate the total energy of the system float initial_energy = FF.updateEnergy(); Log << "initial energy: " << initial_energy << " kJ/mol" << endl; // initialize the minimizer and perform (up to) // 1000 optimization steps minimizer.setup(FF); minimizer.setEnergyOutputFrequency(1); minimizer.minimize(50); // calculate the terminal energy and print it float terminal_energy = FF.getEnergy(); Log << "energy before/after minimization: " << initial_energy << "/" << terminal_energy << " kJ/mol" << endl; // write the optimized structure to a file whose // name is given as the second command line argument Log << "writing PBD file " << argv[2] << endl; file.open(argv[2], ios::out); file << S; file.close(); // done. return 0; }
int main(int argc, char** argv) { if (argc != 3) { Log.error() << argv[0] << " <pdb file A> <pdb file B>" << endl; return 1; } // open the first PDB file PDBFile pdb(argv[1]); if (pdb.bad()) { // if the file could not be opened, print error message and exit Log.error() << "cannot open PBD file " << argv[1] << endl; return 2; } // read the contents of the file A into a system System A; pdb >> A; pdb.close(); // open the second PDB file pdb.open(argv[2]); if (pdb.bad()) { // if the file could not be opened, print error message and exit Log.error() << "cannot open PBD file " << argv[2] << endl; return 2; } // read the contents of the file B into a system System B; pdb >> B; pdb.close(); // normalize the names and build all bonds Log.info() << "normalizing names and building bonds..." << endl; FragmentDB db(""); A.apply(db.normalize_names); A.apply(db.build_bonds); B.apply(db.normalize_names); B.apply(db.build_bonds); // calculate the atomic contact energies of A and B float ACE_A = calculateACE(A); float ACE_B = calculateACE(B); // calculate the electrostatic energies of A and B AmberFF amber; amber.options[AmberFF::Option::ASSIGN_CHARGES] = "true"; amber.options[AmberFF::Option::OVERWRITE_CHARGES] = "true"; amber.setup(A); amber.updateEnergy(); float ES_A = amber.getESEnergy(); float C_A = calculateCoulomb(A); amber.setup(B); amber.updateEnergy(); float ES_B = amber.getESEnergy(); float C_B = calculateCoulomb(B); // finally, join the to systems into a single system cout << "atoms in A: " << A.countAtoms() << endl; cout << "atoms in B: " << B.countAtoms() << endl; A.splice(B); cout << "final atoms: " << A.countAtoms() << endl; float ACE_AB = calculateACE(A); amber.setup(A); amber.updateEnergy(); float ES_AB = amber.getESEnergy(); float C_AB = calculateCoulomb(A); // print the resulting energies cout << "ES energy of A: " << ES_A << endl; cout << "ES energy of B: " << ES_B << endl; cout << "ES energy of AB:" << ES_AB << endl; cout << "C energy of A: " << C_A << endl; cout << "C energy of B: " << C_B << endl; cout << "C energy of AB:" << C_AB << endl; cout << "change in atomic contact energy on binding: " << (ACE_AB - ACE_A - ACE_B) << " kJ/mol" << endl; cout << "change in electrostatic energy on binding: " << (ES_AB - ES_A - ES_B) << " kJ/mol" << endl; cout << "total binding free energy: " << (ACE_AB - ACE_A - ACE_B) + (ES_AB - ES_A - ES_B) << " kJ/mol" << endl; // done return 0; }