├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── src ├── mcdock.cpp └── utils.hpp └── xyz ├── benzene.xyz ├── glucosepane.xyz ├── small_conformer.xyz └── water.xyz /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | *.smod 19 | 20 | # Compiled Static libraries 21 | *.lai 22 | *.la 23 | *.a 24 | *.lib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | 31 | mcdock 32 | out.xyz 33 | min.xyz 34 | conformers.xyz 35 | temp.mop 36 | temp.out 37 | temp.arc 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Anders Steen Christensen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CXX = g++ 2 | 3 | OBDIR = /home/andersx/opt/openbabel2.4 4 | 5 | INCLUDE = -I$(OBDIR)/include/openbabel-2.0/ 6 | LIBS = -L$(OBDIR)/lib 7 | 8 | CXX_FLAGS = -std=c++11 -O3 -march=native -Wall 9 | LINKER_FLAGS = -lopenbabel 10 | 11 | all: mcdock 12 | 13 | mcdock: src/mcdock.cpp src/utils.hpp 14 | $(CXX) $(INCLUDE) $(LIBS) $(CXX_FLAGS) src/mcdock.cpp -o mcdock $(LINKER_FLAGS) 15 | 16 | clean: 17 | rm -f mcdock 18 | rm -f temp.mop 19 | rm -f temp.out 20 | rm -f temp.arc 21 | rm -f min.xyz 22 | rm -f out.xyz 23 | rm -f conformers.xyz 24 | 25 | 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # McDock 2 | McDock: Simple Monte Carlo docking algorithm in C++ 3 | 4 | ## How to install: 5 | Note: you need Open Babel installed (and working) to do the following. 6 | 7 | git clone https://github.com/andersx/mcdock.git 8 | 9 | If you have Open Babel installed in a non-standard path, add this to the `OBDIR` variable in the `Makefile`. 10 | 11 | Now compile McDock: 12 | 13 | cd mcdock 14 | make 15 | 16 | ## How it works: 17 | 18 | 1. The host molecule is minimized 19 | 2. A rotamer search is performed for the ligand 20 | * Each rotamer is energy minimized 21 | * A number of Monte Carlo Metropolis-Hastings (i.e. constant temperature) docking simulations is performed for each rotamer - the number of trajectories and steps for each trajectory is given in the input line, as well as the MC temperature. 22 | * The final docking conformation in minimized 23 | * The binding energy is calculated 24 | 25 | 26 | The binding energy is calculated as: 27 | 28 | > Ebind = E - [Ehost + Eligand\_min] 29 | 30 | Where `E` is the energy of a specific binding conformation, `Ehost` is the energy of the minimized host molecule, and `Eligand_min` is the energy of the ligand in the lowest-energy conformation from the minimzed rotamer search. 31 | 32 | The MC move is combination of random translations and rotations. 33 | 34 | * The conformers found from the rotamer search is saved in the file `conformers.xyz`. 35 | * The last motif from each trajectory is saved in the file `out.xyz`. 36 | * The strongest binding motif is saved in the file `min.xyz`. 37 | 38 | 39 | ## Program options: 40 | 41 | The possible program options are: 42 | 43 | Running McDock 0.2 alpha 44 | Usage: ./mcdock --target file1.xyz --ligand file2.xyz [--args] 45 | 46 | Optional arguments: 47 | --energy [string] Potential energy function "MMFF94" (default), 48 | "UFF", "PM6-D3H4" (requires MOPAC). 49 | --temperature [float] Temperature in units of [R T] (default = 1.0). 50 | --trajectories [int] Number of independent trajectories (default = 10). 51 | --mc-steps [int] Number of Monte Carlo steps in each trajectories (default = 1000). 52 | --no-rotor-search Disable rotor search. (default = perform rotor search). 53 | 54 | The possible potential energy functions are the `MMFF` and `UFF` force fields as implemented in Open Babel. 55 | If MOPAC is installed in `/opt/mopac/` it is possible to use the semi-empirical method `PM6-D3H4` as well. 56 | 57 | ## Running McDock: 58 | 59 | Running McDock for 2000 steps, with 5 trajectories at temperature T = 0.3 (in units of R T), using the MMFF94 force field: 60 | 61 | ./mcdock --target xyz/glucosepane.xyz --ligand xyz/small_conformer.xyz \ 62 | --trajectories 5 --temperature 0.3 --mc-steps 2000 --energy MMFF94 63 | 64 | The energy is printed in units of **kcal/mol**. The MC temperature unit is **R T** where **R** is the ideal gas constant. 65 | 66 | This will generate something like the following output: 67 | 68 | Running McDock 0.2 alpha 69 | Target (minimized) E = -33.4960 kcal/mol file: xyz/glucosepane.xyz 70 | Performing rotor search for ligand molecule file: xyz/small_conformer.xyz 71 | ..tot conformations = 3 72 | ..tot confs tested = 3 73 | ..below energy threshold = 3 74 | Found 1 rotatable bonds 75 | Rotamer 0 E = 20.2736 kcal/mol 76 | Rotamer 1 E = 19.9836 kcal/mol 77 | Rotamer 2 E = 20.2721 kcal/mol 78 | Rotamer 3 E = 24.2927 kcal/mol 79 | Lowest energy conformation E = 19.9836 kcal/mol 80 | Running 5 trajectories for 2000 steps. 81 | MC temperature (tau) = 0.3000 82 | 83 | Conformation: Trajectory: Acceptance rate: Final Ebind: 84 | --------------------------------------------------------------------------- 85 | 1 / 4 1 / 5 7.40 % -9.0204 kcal/mol <---- New lowest 86 | 1 / 4 2 / 5 9.50 % -11.8772 kcal/mol <---- New lowest 87 | 1 / 4 3 / 5 19.74 % -2.4114 kcal/mol 88 | 1 / 4 4 / 5 9.15 % -10.1515 kcal/mol 89 | 1 / 4 5 / 5 6.25 % -10.1287 kcal/mol 90 | 2 / 4 1 / 5 8.80 % -8.3443 kcal/mol 91 | 2 / 4 2 / 5 12.99 % -10.4063 kcal/mol 92 | 2 / 4 3 / 5 9.40 % -10.6525 kcal/mol 93 | 2 / 4 4 / 5 15.54 % -8.1072 kcal/mol 94 | 2 / 4 5 / 5 7.95 % -8.9660 kcal/mol 95 | 3 / 4 1 / 5 5.85 % -11.0246 kcal/mol 96 | 3 / 4 2 / 5 12.14 % -11.3170 kcal/mol 97 | 3 / 4 3 / 5 6.95 % -10.3502 kcal/mol 98 | 3 / 4 4 / 5 11.84 % -8.1763 kcal/mol 99 | 3 / 4 5 / 5 8.10 % -6.1784 kcal/mol 100 | 4 / 4 1 / 5 8.40 % -4.8038 kcal/mol 101 | 4 / 4 2 / 5 7.55 % -3.6463 kcal/mol 102 | 4 / 4 3 / 5 7.20 % -3.3909 kcal/mol 103 | 4 / 4 4 / 5 24.74 % -1.4923 kcal/mol 104 | 4 / 4 5 / 5 9.90 % -1.9934 kcal/mol 105 | 106 | Optimized E_bind = -11.8772 kcal/mol Elapsed time = 8.47 seconds 107 | 108 | A "good" temperature will usually yield an acceptance rate around 20 %. 109 | 110 | 111 | ## License: 112 | 113 | McDock is licensed under the MIT open source license. Cite the use of McDock by citing this github repository. 114 | -------------------------------------------------------------------------------- /src/mcdock.cpp: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // 3 | // Copyright (c) 2017 Anders Steen Christensen 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | // Conformer search requires HAVE_EIGEN defined 24 | // due to bug/quirk in Open Babel 25 | #define HAVE_EIGEN 26 | 27 | 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #include "utils.hpp" 47 | 48 | 49 | 50 | int main(int argc, char *argv[]) { 51 | 52 | // Start timer 53 | OpenBabel::OBStopwatch timer; 54 | timer.Start(); 55 | 56 | printf("Running McDock 0.2 alpha\n"); 57 | McDock::Option opts = McDock::get_options(argc, argv); 58 | 59 | // Get OBMols 60 | OpenBabel::OBMol mol = McDock::readfile(opts.target); 61 | OpenBabel::OBMol ligand = McDock::readfile(opts.ligand); 62 | OpenBabel::vector3 com; 63 | 64 | // Center ligand molecule 65 | com = McDock::get_com(ligand); 66 | McDock::move_molecule(ligand, -com); 67 | 68 | // Gent energies of target molecule 69 | double ea; 70 | if (opts.use_mopac == false) { 71 | ea = McDock::minimize_molecule(mol, opts.ff); 72 | } else { 73 | ea = McDock::mopac_optimize(mol); 74 | } 75 | 76 | printf("Target (minimized) E = %10.4f kcal/mol file: %s \n", ea, opts.target.c_str()); 77 | 78 | // Center target molecule 79 | com = McDock::get_com(mol); 80 | McDock::move_molecule(mol, -com); 81 | 82 | // Do rotor search for ligand molecule 83 | if (opts.rotor_flag == 0) { 84 | printf("Performing rotor search for ligand molecule file: %s\n", opts.ligand.c_str()); 85 | McDock::set_conformations(ligand, opts.ff); 86 | printf("Found %3i rotatable bonds\n", ligand.NumRotors()); 87 | } else { 88 | printf("No rotors search performed for ligand molecule file: %s\n", opts.ligand.c_str()); 89 | } 90 | 91 | // Initialize random number generators 92 | std::default_random_engine generator; 93 | std::uniform_real_distribution random_length(0.0, 0.25); 94 | std::uniform_real_distribution random_angle(0.0, 90.0/180.0*M_PI); 95 | std::uniform_real_distribution uniform1(0.0, 1.0); 96 | 97 | // Initialize variables 98 | double e_low = std::numeric_limits::infinity(); 99 | double eb_min = std::numeric_limits::infinity(); 100 | 101 | // Initialize force field 102 | OpenBabel::OBForceField* pFF = OpenBabel::OBForceField::FindForceField(opts.ff); 103 | 104 | // Initialize variables 105 | double theta; 106 | OpenBabel::vector3 temp; 107 | OpenBabel::vector3 dir; 108 | OpenBabel::vector3 rot; 109 | OpenBabel::vector3 move; 110 | 111 | double eb; 112 | 113 | // Initialize file output 114 | OpenBabel::OBConversion conv; 115 | conv.SetInAndOutFormats("xyz", "xyz"); 116 | std::remove("conformers.xyz"); 117 | std::ofstream ofs_conf("conformers.xyz"); 118 | 119 | // Minimize all conformers from rotamer search and dump to file 120 | for (int c = 0; c < ligand.NumConformers(); ++c) { 121 | 122 | ligand.SetConformer(c); 123 | 124 | if (opts.use_mopac == false) { 125 | eb = McDock::minimize_molecule(ligand, opts.ff); 126 | } else { 127 | eb = McDock::mopac_optimize(ligand); 128 | } 129 | 130 | if (eb < eb_min) eb_min = eb; 131 | 132 | printf("Rotamer %4i E = %10.4f kcal/mol\n", c, eb); 133 | conv.Write(&ligand, &ofs_conf); 134 | } 135 | 136 | ofs_conf.close(); 137 | printf("Lowest energy conformation E = %10.4f kcal/mol\n", eb_min); 138 | printf("Running %3i trajectories for %10i steps.\n", opts.trajectories, opts.steps); 139 | printf("MC temperature (tau) = %10.4f\n", opts.temperature); 140 | 141 | // Initialize output for trajectory 142 | std::remove("out.xyz"); 143 | std::ofstream ofs("out.xyz"); 144 | 145 | // Print header 146 | printf("\nConformation: Trajectory: Acceptance rate: Final Ebind:\n"); 147 | printf("---------------------------------------------------------------------------\n"); 148 | 149 | for (int c = 0; c < ligand.NumConformers(); ++c) { 150 | 151 | ligand.SetConformer(c); 152 | 153 | // Minimize conformer 154 | if (opts.use_mopac == false) { 155 | eb = McDock::minimize_molecule(ligand, opts.ff); 156 | } else { 157 | eb = McDock::mopac_optimize(ligand); 158 | } 159 | 160 | for (unsigned int n = 0; n < opts.trajectories; n++) { 161 | 162 | // Translate molecule randomly 163 | dir.randomUnitVector(); 164 | com = McDock::get_com(ligand); 165 | temp = dir * 4.0 - com; 166 | McDock::move_molecule(ligand, temp); 167 | 168 | // Rotate molecule randomly 169 | rot.randomUnitVector(); 170 | theta = random_angle(generator); 171 | McDock::rotate_molecule(ligand, rot, theta); 172 | 173 | // Make object to roll-back rejected MC moves 174 | OpenBabel::OBMol mol_ligand = mol; 175 | mol_ligand += ligand; 176 | OpenBabel::OBMol mol_old = mol_ligand; 177 | mol_old.SetCoordinates(mol_ligand.GetCoordinates()); 178 | 179 | // Initialize MC energy 180 | pFF->Setup(mol_ligand); 181 | double e; 182 | 183 | // Calculate energy of complex 184 | if (opts.use_mopac == false) { 185 | e = pFF->Energy(); 186 | 187 | } else { 188 | e = McDock::mopac_energy(mol_ligand); 189 | } 190 | 191 | // Initialize variables 192 | double energy_old = e; 193 | double delta_e = 0.0; 194 | int accept = 0; 195 | double acceptance_ratio; 196 | 197 | // Start and end ID of ligand in complex 198 | int startid = mol_ligand.NumAtoms() - ligand.NumAtoms() + 1; 199 | int endid = mol_ligand.NumAtoms() + 1; 200 | 201 | // Begin MC simulation 202 | for (int step = 0; step < opts.steps; step++) { 203 | 204 | // Translation move 205 | move.randomUnitVector(); 206 | move *= random_length(generator); 207 | McDock::move_molecule(mol_ligand, move, startid=startid, endid=endid); 208 | 209 | // Rotation move 210 | rot.randomUnitVector(); 211 | theta = random_angle(generator); 212 | McDock::rotate_molecule(mol_ligand, rot, theta, startid=startid, endid=endid); 213 | 214 | // Evaluate total energy 215 | pFF->SetCoordinates(mol_ligand); 216 | if (opts.use_mopac == false) { 217 | e = pFF->Energy(); 218 | } else { 219 | e = McDock::mopac_energy(mol_ligand); 220 | } 221 | 222 | delta_e = e - energy_old; 223 | 224 | // Metropolis-Hastings MC criterion, accept ... 225 | if (std::exp( - delta_e / opts.temperature) >= uniform1(generator)) { 226 | mol_old.SetCoordinates(mol_ligand.GetCoordinates()); 227 | energy_old = e; 228 | // printf(" Etot = %10.4f Ea = %10.4f Eb = %10.4f E_bind = %10.4f\n", e, ea, eb_min, e - (ea + eb_min)); 229 | // printf("Step: %6i Etotal = %10.4f kcal/mol\n", step, e); 230 | accept += 1; 231 | // ... or reject. 232 | } else { 233 | mol_ligand.SetCoordinates(mol_old.GetCoordinates()); 234 | e = energy_old; 235 | } 236 | 237 | // acceptance_ratio = accept * 100.0 / (step + 1); 238 | // printf("Step: %6i acceptance = %6.2f %% Etotal = %10.4f kcal/mol\n", step + 1, acceptance_ratio, e); 239 | } 240 | 241 | double ec; 242 | if (opts.use_mopac == false) { 243 | ec = McDock::minimize_molecule(mol_ligand, opts.ff); 244 | } else { 245 | ec = McDock::mopac_optimize(mol_ligand); 246 | } 247 | 248 | // double ec = mopac_optimize(mol_ligand); 249 | double e_bind = ec - (ea + eb_min); 250 | acceptance_ratio = accept * 100.0 / (opts.steps + 1); 251 | 252 | // printf("Rotamer: %3i / %3i Trajectory: %3i / %3i acceptance = %6.2f %% E_bind = %10.4f kcal/mol", c + 1, ligand.NumConformers(), n + 1, opts.trajectories, acceptance_ratio, e_bind); 253 | printf(" %3i / %3i %3i / %3i %6.2f %% %10.4f kcal/mol", c + 1, ligand.NumConformers(), n + 1, opts.trajectories, acceptance_ratio, e_bind); 254 | 255 | std::string title = "Binding Energy: " + std::to_string(e_bind); 256 | mol_ligand.SetTitle(title); 257 | mol_ligand.SetEnergy(ec); 258 | conv.Write(&mol_ligand, &ofs); 259 | 260 | // Check if we found the lowest energy 261 | if (e_bind < e_low) { 262 | 263 | printf(" <---- New lowest\n"); 264 | OpenBabel::OBConversion conv2; 265 | conv2.SetInAndOutFormats("xyz", "xyz"); 266 | e_low = e_bind; 267 | std::remove("min.xyz"); 268 | std::ofstream ofs_min("min.xyz"); 269 | std::string title = "Binding Energy: " + std::to_string(e_bind); 270 | mol_ligand.SetTitle(title); 271 | conv2.Write(&mol_ligand, &ofs_min); 272 | ofs_min.close(); 273 | 274 | } else { 275 | printf("\n"); 276 | } 277 | } 278 | } 279 | 280 | ofs.close(); 281 | 282 | double time_elapsed = timer.Elapsed(); 283 | printf("\nOptimized E_bind = %10.4f kcal/mol Elapsed time = %6.2f seconds\n", 284 | e_low, time_elapsed); 285 | 286 | 287 | return 0; 288 | 289 | } 290 | -------------------------------------------------------------------------------- /src/utils.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SRC_UTILS_HPP 2 | #define SRC_UTILS_HPP 3 | #define HAVE_EIGEN 4 | 5 | namespace McDock { 6 | 7 | // Returns a rotated vector, rotated by T 8 | OpenBabel::vector3 rotate(const OpenBabel::vector3 &V, 9 | const OpenBabel::vector3 &J, const double T) { 10 | 11 | double x = V.x(); 12 | double y = V.y(); 13 | double z = V.z(); 14 | 15 | double u = J.x(); 16 | double v = J.y(); 17 | double w = J.z(); 18 | 19 | double norm = std::sqrt(u*u + v*v + w*w); 20 | double inv_norm_sqrt = 1.0 / (norm * norm); 21 | double sint = std::sin(T); 22 | double cost = std::cos(T); 23 | 24 | double a = (u * (u*x + v*y + w*z) + (x * (v*v + w*w) - u * (v*y + w*z)) 25 | * cost + norm * (-w*y + v*z) * sint) * inv_norm_sqrt; 26 | double b = (v * (u*x + v*y + w*z) + (y * (u*u + w*w) - v * (u*x + w*z)) 27 | * cost + norm * ( w*x - u*z) * sint) * inv_norm_sqrt; 28 | double c = (w * (u*x + v*y + w*z) + (z * (u*u + v*v) - w * (u*x + v*y)) 29 | * cost + norm * (-v*x + u*y) * sint) * inv_norm_sqrt; 30 | 31 | OpenBabel::vector3 rotated; 32 | rotated.Set(a, b, c); 33 | 34 | return rotated; 35 | } 36 | 37 | void move_molecule(OpenBabel::OBMol &mol, OpenBabel::vector3 move, 38 | int startid = 1, int endid = -1) { 39 | 40 | if (endid == -1) endid = mol.NumAtoms() + 1; 41 | 42 | OpenBabel::vector3 temp; 43 | OpenBabel::OBAtom *atom; 44 | 45 | for (int i = startid; i < endid; i++) { 46 | atom = mol.GetAtom(i); 47 | temp = atom->GetVector(); 48 | temp += move; 49 | atom->SetVector(temp); 50 | } 51 | 52 | } 53 | 54 | void rotate_molecule(OpenBabel::OBMol &mol, OpenBabel::vector3 direction, 55 | double theta, int startid = 1, int endid = -1) { 56 | 57 | if (endid == -1) endid = mol.NumAtoms() + 1; 58 | 59 | OpenBabel::vector3 com; 60 | com.Set(0.0, 0.0, 0.0); 61 | OpenBabel::OBAtom *atom; 62 | 63 | for (int i = startid; i < endid; i++) { 64 | 65 | atom = mol.GetAtom(i); 66 | com += atom->GetVector(); 67 | } 68 | 69 | com /= (double)(endid - startid); 70 | 71 | 72 | OpenBabel::vector3 temp; 73 | // Center ligand, and give random rotation 74 | for (int i = startid; i < endid; i++) { 75 | 76 | atom = mol.GetAtom(i); 77 | temp = atom->GetVector(); 78 | temp -= com; 79 | temp = rotate(temp, direction, theta); 80 | temp += com; 81 | atom->SetVector(temp); 82 | 83 | } 84 | 85 | 86 | } 87 | 88 | 89 | OpenBabel::OBMol readfile(std::string filename) { 90 | 91 | OpenBabel::OBMol mol; 92 | 93 | OpenBabel::OBConversion conv; 94 | conv.SetInAndOutFormats("xyz", "xyz"); 95 | std::ifstream ifs; 96 | 97 | ifs.open(filename.c_str()); 98 | conv.Read(&mol, &ifs); 99 | ifs.close(); 100 | 101 | return mol; 102 | 103 | } 104 | 105 | double mopac_energy(OpenBabel::OBMol &mol) { 106 | 107 | std::remove("temp.mop"); 108 | std::remove("temp.out"); 109 | std::remove("temp.arc"); 110 | 111 | OpenBabel::OBConversion conv; 112 | conv.SetInAndOutFormats("moo", "mop"); 113 | 114 | std::ofstream ofs("temp.mop"); 115 | conv.Write(&mol, &ofs); 116 | ofs.close(); 117 | 118 | // int success = system("./run_mopac_1scf"); 119 | int success = 0; 120 | success += system("sed -i \"s/PUT KEYWORDS HERE/PM6-D3H4 1SCF/\" temp.mop"); 121 | success += system("LD_LIBRARY_PATH=/opt/mopac:$LD_LIBRARY_PATH OMP_NUM_THREADS=1 MKL_NUM_THREADS=1 /opt/mopac/MOPAC2016.exe temp.mop 2> /dev/null "); 122 | if (success > 1) printf("Error running MOPAC!"); 123 | 124 | OpenBabel::OBMol molout; 125 | 126 | std::ifstream ifs; 127 | ifs.open("temp.out"); 128 | conv.Read(&molout, &ifs); 129 | ifs.close(); 130 | 131 | std::remove("temp.mop"); 132 | std::remove("temp.out"); 133 | std::remove("temp.arc"); 134 | 135 | return molout.GetEnergy(); 136 | 137 | } 138 | 139 | double mopac_optimize(OpenBabel::OBMol &mol) { 140 | 141 | std::remove("temp.mop"); 142 | std::remove("temp.out"); 143 | std::remove("temp.arc"); 144 | 145 | OpenBabel::OBConversion conv; 146 | conv.SetInAndOutFormats("moo", "mop"); 147 | 148 | std::ofstream ofs("temp.mop"); 149 | conv.Write(&mol, &ofs); 150 | ofs.close(); 151 | 152 | int success = 0; 153 | success += system("sed -i \"s/PUT KEYWORDS HERE/PM6-D3H4 EF/\" temp.mop"); 154 | success += system("LD_LIBRARY_PATH=/opt/mopac:$LD_LIBRARY_PATH OMP_NUM_THREADS=1 MKL_NUM_THREADS=1 /opt/mopac/MOPAC2016.exe temp.mop 2> /dev/null "); 155 | if (success > 1) printf("Error running MOPAC!"); 156 | 157 | OpenBabel::OBMol molout; 158 | 159 | std::ifstream ifs; 160 | ifs.open("temp.out"); 161 | conv.Read(&molout, &ifs); 162 | ifs.close(); 163 | 164 | // Segfaults for unknown random reasons?? 165 | // mol.SetCoordinates(molout.GetCoordinates()); 166 | 167 | // Workaround for above problem 168 | for (unsigned int i = 1; i < mol.NumAtoms() + 1; i++) { 169 | OpenBabel::OBAtom *atom = mol.GetAtom(i); 170 | atom->SetVector((molout.GetAtom(i))->GetVector()); 171 | } 172 | 173 | mol.SetEnergy(molout.GetEnergy()); 174 | 175 | std::remove("temp.mop"); 176 | std::remove("temp.out"); 177 | std::remove("temp.arc"); 178 | 179 | return molout.GetEnergy(); 180 | 181 | } 182 | 183 | double minimize_molecule(OpenBabel::OBMol &mol, const std::string &ff) { 184 | 185 | OpenBabel::OBForceField* pFF = OpenBabel::OBForceField::FindForceField(ff); 186 | pFF->Setup(mol); 187 | 188 | double e = pFF->Energy(); 189 | // printf("E_before = %10.4f kJ/mol %i\n", e, mol.NumAtoms()); 190 | 191 | const int steps = 200; 192 | const double crit = 5.0e-4; 193 | 194 | // pFF->SteepestDescentInitialize(steps, crit); 195 | pFF->ConjugateGradientsInitialize(steps, crit); 196 | 197 | bool done = true; 198 | 199 | while (done) { 200 | 201 | // done = pFF->SteepestDescentTakeNSteps(1); 202 | done = pFF->ConjugateGradientsTakeNSteps(1); 203 | 204 | if (pFF->DetectExplosion()) { 205 | 206 | std::cerr << "explosion has occured!" << std::endl; 207 | exit(1); 208 | 209 | } else { 210 | 211 | pFF->GetCoordinates(mol); 212 | } 213 | 214 | } 215 | e = pFF->Energy(); 216 | mol.SetEnergy(e); 217 | 218 | // printf("E_after = %10.4f kJ/mol %i\n", e, mol.NumAtoms()); 219 | return e; 220 | 221 | } 222 | 223 | void set_conformations(OpenBabel::OBMol &mol, std::string ff){ 224 | 225 | // if (ff.compare("PM6-D3H4") == 0) ff = "MMFF94"; 226 | OpenBabel::OBForceField* pFF = OpenBabel::OBForceField::FindForceField(ff); 227 | pFF->Setup(mol); 228 | 229 | double rmsd_cutoff = 0.5; 230 | double energy_cutoff = 50.0; 231 | unsigned int conf_cutoff = 1000000; // 1 Million 232 | bool verbose = false; 233 | 234 | pFF->DiverseConfGen(rmsd_cutoff, conf_cutoff, energy_cutoff, verbose); 235 | pFF->GetConformers(mol); 236 | 237 | 238 | } 239 | 240 | 241 | OpenBabel::vector3 get_com(OpenBabel::OBMol mol) { 242 | 243 | OpenBabel::vector3 com; 244 | com.Set(0.0, 0.0, 0.0); 245 | OpenBabel::OBAtom *atom; 246 | 247 | OpenBabel::vector3 temp; 248 | for (unsigned int i = 1; i < mol.NumAtoms() + 1; i++) { 249 | 250 | atom = mol.GetAtom(i); 251 | temp = atom->GetVector(); 252 | com += temp; 253 | } 254 | 255 | com /= mol.NumAtoms(); 256 | 257 | return com; 258 | 259 | } 260 | 261 | 262 | void save_xyz(OpenBabel::OBMol mol, std::string filename) { 263 | 264 | OpenBabel::OBConversion conv; 265 | conv.SetInAndOutFormats("xyz", "xyz"); 266 | 267 | std::ofstream ofs(filename); 268 | 269 | //std::string title = std::to_string(e_bind); 270 | //mol_ligand.SetTitle(title); 271 | 272 | conv.Write(&mol, &ofs); 273 | ofs.close(); 274 | 275 | 276 | } 277 | 278 | // Prints help 279 | void print_help() { 280 | 281 | printf("Usage: ./mcdock --target file1.xyz --ligand file2.xyz [--args]\n\n"); 282 | 283 | printf("Optional arguments:\n"); 284 | 285 | printf("--energy [string] Potential energy function \"MMFF94\" (default),\n"); 286 | printf(" \"UFF\", \"PM6-D3H4\" (requires MOPAC). \n"); 287 | printf("--temperature [float] Temperature in units of [R T] (default = 1.0).\n"); 288 | printf("--trajectories [int] Number of independent trajectories (default = 10).\n"); 289 | printf("--mc-steps [int] Number of Monte Carlo steps in each trajectories (default = 1000).\n"); 290 | printf("--no-rotor-search Disable rotor search. (default = perform rotor search).\n"); 291 | 292 | printf("\n"); 293 | } 294 | 295 | 296 | // Container for command-line options 297 | struct Option { 298 | 299 | std::string ff = "MMFF94"; 300 | std::string target; 301 | std::string ligand; 302 | bool use_mopac = false; 303 | unsigned int trajectories = 1; 304 | int steps = 1000; 305 | double temperature = 1.0; 306 | double verbose_flag = false; 307 | double rotor_flag = false; 308 | double help_flag= false; 309 | 310 | }; 311 | 312 | // Option parser 313 | Option get_options (int argc, char **argv) { 314 | 315 | if (argc < 2) { 316 | print_help(); 317 | exit(0); 318 | } 319 | 320 | int c; 321 | 322 | Option opts; 323 | 324 | int verbose_flag = 0; 325 | int rotor_flag = 0; 326 | int help_flag = 0; 327 | 328 | while (1) { 329 | static struct option long_options[] = { 330 | {"verbose", no_argument, &verbose_flag, 1}, 331 | {"help", no_argument, &help_flag, 1}, 332 | {"no-rotor-search", no_argument, &rotor_flag, 1}, 333 | {"target", required_argument, 0, 'a'}, 334 | {"ligand", required_argument, 0, 'b'}, 335 | {"trajectories", required_argument, 0, 'c'}, 336 | {"energy", required_argument, 0, 'd'}, 337 | {"temperature", required_argument, 0, 'e'}, 338 | {"mc-steps", required_argument, 0, 'f'}, 339 | {0, 0, 0, 0} 340 | }; 341 | 342 | int option_index = 0; 343 | 344 | c = getopt_long (argc, argv, "a:b:c:d:f:", long_options, &option_index); 345 | 346 | if (c == -1) 347 | break; 348 | 349 | switch (c) { 350 | 351 | case 0: 352 | if (long_options[option_index].flag != 0) break; 353 | break; 354 | 355 | case 'a': 356 | opts.target = optarg; 357 | break; 358 | 359 | case 'b': 360 | opts.ligand = optarg; 361 | break; 362 | 363 | case 'e': 364 | opts.temperature = std::stod(optarg); 365 | break; 366 | 367 | case 'c': 368 | opts.trajectories = atoi(optarg); 369 | break; 370 | 371 | case 'f': 372 | opts.steps = atoi(optarg); 373 | break; 374 | 375 | case 'd': { 376 | std::string ff = optarg; 377 | 378 | if (ff.compare("MMFF94") == 0) { 379 | opts.ff = optarg; 380 | opts.use_mopac = false; 381 | } else if (ff.compare("MMFF94s") == 0) { 382 | opts.ff = optarg; 383 | opts.use_mopac = false; 384 | } else if (ff.compare("GAFF") == 0) { 385 | opts.ff = optarg; 386 | opts.use_mopac = false; 387 | } else if (ff.compare("UFF") == 0) { 388 | opts.ff = optarg; 389 | opts.use_mopac = false; 390 | } else if (ff.compare("PM6-D3H4") == 0) { 391 | opts.ff = "MMFF94"; 392 | opts.use_mopac = true; 393 | 394 | } else { 395 | printf ("ERROR: Unsupported force field `%s'\n", optarg); 396 | exit(0); 397 | } 398 | break; 399 | } 400 | case '?': 401 | /* getopt_long already printed an error message. */ 402 | break; 403 | 404 | default: 405 | abort (); 406 | } 407 | } 408 | 409 | if (verbose_flag) opts.verbose_flag = true; 410 | if (rotor_flag) opts.rotor_flag = true; 411 | if (help_flag) { 412 | print_help(); 413 | exit(0); 414 | } 415 | 416 | /* Print any remaining command line arguments (not options). */ 417 | if (optind < argc) 418 | { 419 | printf ("non-option ARGV-elements: "); 420 | while (optind < argc) 421 | printf ("%s ", argv[optind++]); 422 | putchar ('\n'); 423 | } 424 | 425 | if (opts.temperature < 0) { 426 | std::cout << "ERROR: Positive temperature required" << std::endl; 427 | exit(0); 428 | } 429 | 430 | if (opts.ligand.compare("") == 0) { 431 | printf("ERROR: No ligand xyz-file specified.\n"); 432 | 433 | print_help(); 434 | exit(0); 435 | } 436 | 437 | if (opts.target.compare("") == 0) { 438 | printf("ERROR: No target xyz-file specified.\n"); 439 | 440 | print_help(); 441 | exit(0); 442 | } 443 | 444 | return opts; 445 | 446 | } 447 | 448 | 449 | 450 | } // Namespace McDock 451 | 452 | #endif 453 | -------------------------------------------------------------------------------- /xyz/benzene.xyz: -------------------------------------------------------------------------------- 1 | 12 2 | Energy: 16.2269671 3 | C -8.04283 0.32421 1.51679 4 | C -8.33049 1.58696 0.99888 5 | C -7.05172 0.17765 2.48723 6 | C -6.34826 1.29386 2.93976 7 | C -6.63597 2.55663 2.42189 8 | C -7.62709 2.70318 1.45145 9 | H -7.85125 3.68702 1.04798 10 | H -9.10265 1.70113 0.24276 11 | H -8.59090 -0.54545 1.16422 12 | H -6.82759 -0.80618 2.89075 13 | H -5.57604 1.17967 3.69581 14 | H -6.08794 3.42629 2.77450 15 | -------------------------------------------------------------------------------- /xyz/glucosepane.xyz: -------------------------------------------------------------------------------- 1 | 31 2 | 3 | C 1.08711411 -0.24360695 -1.10659575 4 | N 0.75203106 -1.47356443 -0.39919971 5 | C -0.60304786 -1.49596037 0.14764527 6 | C -1.14066508 -2.76440688 0.83824246 7 | O -2.48286789 -2.47074446 1.20187851 8 | C -1.11695461 -4.03570896 -0.02782550 9 | O -1.74161150 -3.75538576 -1.28680021 10 | C 0.25924549 -4.71005127 -0.17737968 11 | C 1.48844381 -3.86473441 0.20394386 12 | N 2.71296278 -4.54800011 -0.18938266 13 | C 3.30733636 -3.70398886 -0.97568973 14 | N 4.49213858 -3.92932030 -1.59574375 15 | C 5.12624544 -5.23061010 -1.56282906 16 | N 2.69727362 -2.45784593 -1.22129246 17 | C 1.60273354 -2.51578746 -0.51128119 18 | H 0.65128846 0.60781723 -0.57706598 19 | H 0.69834317 -0.25220789 -2.13368736 20 | H 2.17055260 -0.14156103 -1.15336954 21 | H -0.70696052 -0.67487125 0.86709395 22 | H -1.30590976 -1.27358718 -0.66890635 23 | H -0.61328176 -2.94669193 1.77949978 24 | H -2.99885673 -2.53561861 0.38727530 25 | H -1.81044286 -4.72780053 0.46022066 26 | H -1.07507362 -3.38011454 -1.87288684 27 | H 0.37373660 -5.03783149 -1.21649154 28 | H 0.29500515 -5.61934542 0.42939219 29 | H 1.48330820 -3.69037002 1.28954779 30 | H 4.71262860 -3.29082563 -2.33910749 31 | H 4.40071710 -6.02964701 -1.75513382 32 | H 5.91333573 -5.26231086 -2.32014788 33 | H 5.57983206 -5.42591758 -0.58422318 34 | -------------------------------------------------------------------------------- /xyz/small_conformer.xyz: -------------------------------------------------------------------------------- 1 | 13 2 | 3 | C -7.75695 -1.16705 -0.12619 4 | C -6.23754 -1.13432 -0.11376 5 | H -8.16934 -0.23565 -0.52569 6 | H -8.15478 -1.32368 0.88239 7 | H -8.11632 -2.00010 -0.73970 8 | C -5.70597 0.01445 0.75582 9 | H -5.86229 -1.02506 -1.13702 10 | O -5.75246 -2.39147 0.35874 11 | H -6.08233 0.97816 0.39956 12 | O -4.28152 0.06437 0.74607 13 | H -6.01075 -0.11481 1.79947 14 | H -3.97716 -0.22052 -0.13398 15 | H -5.87116 -2.41555 1.32537 16 | -------------------------------------------------------------------------------- /xyz/water.xyz: -------------------------------------------------------------------------------- 1 | 3 2 | 3 | O -0.00000 -0.35107 -0.00000 4 | H -0.81100 0.17553 0.00000 5 | H 0.81100 0.17553 0.00000 6 | --------------------------------------------------------------------------------