1 #!/bin/env python 2 # 3 # File: VinaPerformDocking.py 4 # Author: Manish Sud <msud@san.rr.com> 5 # 6 # Acknowledgments: Diogo Santos-Martins and Stefano Forli 7 # 8 # Copyright (C) 2024 Manish Sud. All rights reserved. 9 # 10 # The functionality available in this script is implemented using AutoDockVina 11 # and Meeko, open source software packages for docking, and RDKit, an open 12 # source toolkit for cheminformatics developed by Greg Landrum. 13 # 14 # This file is part of MayaChemTools. 15 # 16 # MayaChemTools is free software; you can redistribute it and/or modify it under 17 # the terms of the GNU Lesser General Public License as published by the Free 18 # Software Foundation; either version 3 of the License, or (at your option) any 19 # later version. 20 # 21 # MayaChemTools is distributed in the hope that it will be useful, but without 22 # any warranty; without even the implied warranty of merchantability of fitness 23 # for a particular purpose. See the GNU Lesser General Public License for more 24 # details. 25 # 26 # You should have received a copy of the GNU Lesser General Public License 27 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or 28 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330, 29 # Boston, MA, 02111-1307, USA. 30 # 31 32 from __future__ import print_function 33 34 # Add local python path to the global path and import standard library modules... 35 import os 36 import sys; sys.path.insert(0, os.path.join(os.path.dirname(sys.argv[0]), "..", "lib", "Python")) 37 import time 38 import re 39 import shutil 40 import tempfile 41 import json 42 import glob 43 import multiprocessing as mp 44 45 # AutoDock Vina imports... 46 try: 47 from vina import Vina 48 from vina import __version__ as vinaVersion 49 except ImportError as ErrMsg: 50 sys.stderr.write("\nFailed to import AutoDock Vina module/package: %s\n" % ErrMsg) 51 sys.stderr.write("Check/update your Vina environment and try again.\n\n") 52 sys.exit(1) 53 54 # AutoDock Meeko imports... 55 try: 56 from meeko import __version__ as meekoVersion 57 from meeko import MoleculePreparation 58 from meeko import PDBQTMolecule 59 from meeko import RDKitMolCreate 60 from meeko import PDBQTWriterLegacy 61 except ImportError as ErrMsg: 62 sys.stderr.write("\nFailed to import AutoDock Meeko module/package: %s\n" % ErrMsg) 63 sys.stderr.write("Check/update your Meeko environment and try again.\n\n") 64 sys.exit(1) 65 66 # RDKit imports... 67 try: 68 from rdkit import rdBase 69 from rdkit import Chem 70 from rdkit.Chem import AllChem 71 from rdkit.Chem import rdMolTransforms 72 except ImportError as ErrMsg: 73 sys.stderr.write("\nFailed to import RDKit module/package: %s\n" % ErrMsg) 74 sys.stderr.write("Check/update your RDKit environment and try again.\n\n") 75 sys.exit(1) 76 77 # MayaChemTools imports... 78 try: 79 from docopt import docopt 80 import MiscUtil 81 import RDKitUtil 82 except ImportError as ErrMsg: 83 sys.stderr.write("\nFailed to import MayaChemTools module/package: %s\n" % ErrMsg) 84 sys.stderr.write("Check/update your MayaChemTools environment and try again.\n\n") 85 sys.exit(1) 86 87 ScriptName = os.path.basename(sys.argv[0]) 88 Options = {} 89 OptionsInfo = {} 90 91 def main(): 92 """Start execution of the script.""" 93 94 MiscUtil.PrintInfo("\n%s (Vina v%s; Meeko v%s; RDKit v%s; MayaChemTools v%s; %s): Starting...\n" % (ScriptName, vinaVersion, meekoVersion, rdBase.rdkitVersion, MiscUtil.GetMayaChemToolsVersion(), time.asctime())) 95 96 (WallClockTime, ProcessorTime) = MiscUtil.GetWallClockAndProcessorTime() 97 98 # Retrieve command line arguments and options... 99 RetrieveOptions() 100 101 # Process and validate command line arguments and options... 102 ProcessOptions() 103 104 # Perform actions required by the script... 105 PerformDocking() 106 107 MiscUtil.PrintInfo("\n%s: Done...\n" % ScriptName) 108 MiscUtil.PrintInfo("Total time: %s" % MiscUtil.GetFormattedElapsedTime(WallClockTime, ProcessorTime)) 109 110 def PerformDocking(): 111 """Perform docking.""" 112 113 # Setup a molecule reader... 114 MiscUtil.PrintInfo("\nProcessing file %s..." % OptionsInfo["Infile"]) 115 Mols = RDKitUtil.ReadMolecules(OptionsInfo["Infile"], **OptionsInfo["InfileParams"]) 116 117 # Set up molecule writers... 118 Writer, WriterFlexRes = SetupWriters() 119 if WriterFlexRes is None: 120 MiscUtil.PrintInfo("Generating file %s..." % OptionsInfo["Outfile"]) 121 else: 122 MiscUtil.PrintInfo("Generating files %s and %s..." % (OptionsInfo["Outfile"], OptionsInfo["OutfileFlexRes"])) 123 124 MolCount, ValidMolCount, DockingFailedCount = ProcessMolecules(Mols, Writer, WriterFlexRes) 125 126 CloseWriters(Writer, WriterFlexRes) 127 128 MiscUtil.PrintInfo("\nTotal number of molecules: %d" % MolCount) 129 MiscUtil.PrintInfo("Number of valid molecules: %d" % ValidMolCount) 130 MiscUtil.PrintInfo("Number of molecules failed during docking: %d" % DockingFailedCount) 131 MiscUtil.PrintInfo("Number of ignored molecules: %d" % (MolCount - ValidMolCount + DockingFailedCount)) 132 133 def ProcessMolecules(Mols, Writer, WriterFlexRes): 134 """Process and dock molecules.""" 135 136 if OptionsInfo["MPMode"]: 137 return ProcessMoleculesUsingMultipleProcesses(Mols, Writer, WriterFlexRes) 138 else: 139 return ProcessMoleculesUsingSingleProcess(Mols, Writer, WriterFlexRes) 140 141 def ProcessMoleculesUsingSingleProcess(Mols, Writer, WriterFlexRes): 142 """Process and dock molecules using a single process.""" 143 144 VinaHandle = InitializeVina(OptionsInfo["QuietMode"]) 145 MolPrepHandle = InitializeMeekoMolPrepration(OptionsInfo["QuietMode"]) 146 if not OptionsInfo["QuietMode"]: 147 MiscUtil.PrintInfo("\nVina configuration:\n%s" % VinaHandle) 148 149 MiscUtil.PrintInfo("\nDocking molecules (Mode: %s)..." % OptionsInfo["Mode"]) 150 151 (MolCount, ValidMolCount, DockingFailedCount) = [0] * 3 152 for Mol in Mols: 153 MolCount += 1 154 155 if Mol is None: 156 continue 157 158 if not CheckAndValidateMolecule(Mol, MolCount): 159 continue 160 161 ValidMolCount += 1 162 CalcStatus, PoseMol, PoseMolEnergies, PoseMolFlexRes = DockMolecule(VinaHandle, MolPrepHandle, Mol, MolCount) 163 164 if not CalcStatus: 165 if not OptionsInfo["QuietMode"]: 166 MiscUtil.PrintWarning("Failed to dock molecule %s" % RDKitUtil.GetMolName(Mol, MolCount)) 167 168 DockingFailedCount += 1 169 continue 170 171 WriteMolPoses(Writer, Mol, MolCount, PoseMol, PoseMolEnergies, WriterFlexRes, PoseMolFlexRes) 172 173 return (MolCount, ValidMolCount, DockingFailedCount) 174 175 def ProcessMoleculesUsingMultipleProcesses(Mols, Writer, WriterFlexRes): 176 """Process and calculate energy of molecules using multiprocessing.""" 177 178 MiscUtil.PrintInfo("\nDocking molecules using multiprocessing...") 179 MiscUtil.PrintInfo("\nDocking molecules (Mode: %s)..." % OptionsInfo["Mode"]) 180 181 MPParams = OptionsInfo["MPParams"] 182 183 # Setup data for initializing a worker process... 184 InitializeWorkerProcessArgs = (MiscUtil.ObjectToBase64EncodedString(Options), MiscUtil.ObjectToBase64EncodedString(OptionsInfo)) 185 186 # Setup a encoded mols data iterable for a worker process... 187 WorkerProcessDataIterable = RDKitUtil.GenerateBase64EncodedMolStrings(Mols) 188 189 # Setup process pool along with data initialization for each process... 190 if not OptionsInfo["QuietMode"]: 191 MiscUtil.PrintInfo("\nConfiguring multiprocessing using %s method..." % ("mp.Pool.imap()" if re.match("^Lazy$", MPParams["InputDataMode"], re.I) else "mp.Pool.map()")) 192 MiscUtil.PrintInfo("NumProcesses: %s; InputDataMode: %s; ChunkSize: %s\n" % (MPParams["NumProcesses"], MPParams["InputDataMode"], ("automatic" if MPParams["ChunkSize"] is None else MPParams["ChunkSize"]))) 193 194 ProcessPool = mp.Pool(MPParams["NumProcesses"], InitializeWorkerProcess, InitializeWorkerProcessArgs) 195 196 # Start processing... 197 if re.match("^Lazy$", MPParams["InputDataMode"], re.I): 198 Results = ProcessPool.imap(WorkerProcess, WorkerProcessDataIterable, MPParams["ChunkSize"]) 199 elif re.match("^InMemory$", MPParams["InputDataMode"], re.I): 200 Results = ProcessPool.map(WorkerProcess, WorkerProcessDataIterable, MPParams["ChunkSize"]) 201 else: 202 MiscUtil.PrintError("The value, %s, specified for \"--inputDataMode\" is not supported." % (MPParams["InputDataMode"])) 203 204 (MolCount, ValidMolCount, DockingFailedCount) = [0] * 3 205 for Result in Results: 206 MolCount += 1 207 208 MolIndex, EncodedMol, CalcStatus, EncodedPoseMol, PoseMolEnergies, EncodedPoseMolFlexRes = Result 209 210 if EncodedMol is None: 211 continue 212 213 ValidMolCount += 1 214 215 if not CalcStatus: 216 if not OptionsInfo["QuietMode"]: 217 MolName = RDKitUtil.GetMolName(Mol, MolCount) 218 MiscUtil.PrintWarning("Failed to dock molecule %s" % MolName) 219 220 DockingFailedCount += 1 221 continue 222 223 Mol = RDKitUtil.MolFromBase64EncodedMolString(EncodedMol) 224 PoseMol = None if EncodedPoseMol is None else RDKitUtil.MolFromBase64EncodedMolString(EncodedPoseMol) 225 PoseMolFlexRes = None if EncodedPoseMolFlexRes is None else RDKitUtil.MolFromBase64EncodedMolString(EncodedPoseMolFlexRes) 226 227 WriteMolPoses(Writer, Mol, MolCount, PoseMol, PoseMolEnergies, WriterFlexRes, PoseMolFlexRes) 228 229 return (MolCount, ValidMolCount, DockingFailedCount) 230 231 def InitializeWorkerProcess(*EncodedArgs): 232 """Initialize data for a worker process.""" 233 234 global Options, OptionsInfo 235 236 if not OptionsInfo["QuietMode"]: 237 MiscUtil.PrintInfo("Starting process (PID: %s)..." % os.getpid()) 238 239 # Decode Options and OptionInfo... 240 Options = MiscUtil.ObjectFromBase64EncodedString(EncodedArgs[0]) 241 OptionsInfo = MiscUtil.ObjectFromBase64EncodedString(EncodedArgs[1]) 242 243 # Initialize in a quiet mode... 244 OptionsInfo["VinaHandle"] = InitializeVina(True) 245 OptionsInfo["MolPrepHandle"] = InitializeMeekoMolPrepration(True) 246 247 def WorkerProcess(EncodedMolInfo): 248 """Process data for a worker process.""" 249 250 MolIndex, EncodedMol = EncodedMolInfo 251 252 CalcStatus, PoseMol, PoseMolEnergies, PoseMolFlexRes = [False, None, None, None] 253 254 if EncodedMol is None: 255 return [MolIndex, None, CalcStatus, PoseMol, Energies, PoseMolFlexRes] 256 257 Mol = RDKitUtil.MolFromBase64EncodedMolString(EncodedMol) 258 MolCount = MolIndex + 1 259 260 if not CheckAndValidateMolecule(Mol, MolCount): 261 return [MolIndex, None, CalcStatus, PoseMol, Energies, PoseMolFlexRes] 262 263 CalcStatus, PoseMol, PoseMolEnergies, PoseMolFlexRes = DockMolecule(OptionsInfo["VinaHandle"], OptionsInfo["MolPrepHandle"], Mol, MolCount) 264 265 EncodedPoseMol = None if PoseMol is None else RDKitUtil.MolToBase64EncodedMolString(PoseMol, PropertyPickleFlags = Chem.PropertyPickleOptions.MolProps | Chem.PropertyPickleOptions.PrivateProps) 266 267 EncodedPoseMolFlexRes = None if PoseMolFlexRes is None else RDKitUtil.MolToBase64EncodedMolString(PoseMolFlexRes, PropertyPickleFlags = Chem.PropertyPickleOptions.MolProps | Chem.PropertyPickleOptions.PrivateProps) 268 269 return [MolIndex, EncodedMol, CalcStatus, EncodedPoseMol, PoseMolEnergies, EncodedPoseMolFlexRes] 270 271 def DockMolecule(VinaHandle, MolPrepHandle, Mol, MolNum = None): 272 """Dock molecule.""" 273 274 Status, PoseMol, PoseMolEnergies, PoseMolFlexRes = [False, None, None, None] 275 276 if OptionsInfo["VinaVerbosity"] != 0: 277 MiscUtil.PrintInfo("\nProcessing molecule %s..." % RDKitUtil.GetMolName(Mol, MolNum)) 278 279 PDBQTMolStr = PrepareMolecule(MolPrepHandle, Mol) 280 if PDBQTMolStr is None: 281 return (Status, PoseMol, PoseMolEnergies, PoseMolFlexRes) 282 VinaHandle.set_ligand_from_string(PDBQTMolStr) 283 284 if OptionsInfo["ScoreOnlyMode"]: 285 return ProcessMoleculeForScoreOnlyMode(VinaHandle, Mol) 286 elif OptionsInfo["LocalOptimizationOnlyMode"]: 287 return ProcessMoleculeForLocalOptimizationOnlyMode(VinaHandle, Mol) 288 elif OptionsInfo["DockMode"]: 289 return ProcessMoleculeForDockMode(VinaHandle, Mol) 290 else: 291 MiscUtil.PrintError("The value specified, %s, for option \"-m, --mode\" is not valid. Supported values: Dock LocalOptimizationOnly ScoreOnly" % OptionsInfo["Mode"]) 292 293 return (Status, PoseMol, PoseMolEnergies, PoseMolFlexRes) 294 295 def ProcessMoleculeForScoreOnlyMode(VinaHandle, Mol): 296 """Score molecule without performing any docking.""" 297 298 Status, PoseMol, Energies, PoseMolFlexRes = [False, None, None, None] 299 300 # Score molecule... 301 try: 302 Energies = VinaHandle.score() 303 except Exception as ErrMsg: 304 if not OptionsInfo["QuietMode"]: 305 MiscUtil.PrintWarning("Failed to score molecule:\n%s\n" % ErrMsg) 306 return (False, None, None, None) 307 308 if len(Energies) == 0: 309 return (False, None, None, None) 310 311 Status = True 312 PoseMol = Mol 313 314 return (Status, PoseMol, Energies, PoseMolFlexRes) 315 316 def ProcessMoleculeForLocalOptimizationOnlyMode(VinaHandle, Mol): 317 """Score molecule after a local optimization wthout any docking.""" 318 319 Status, PoseMol, Energies, PoseMolFlexRes = [False, None, None, None] 320 321 # Optimize and score molecule... 322 try: 323 Energies = VinaHandle.optimize() 324 except Exception as ErrMsg: 325 if not OptionsInfo["QuietMode"]: 326 MiscUtil.PrintWarning("Failed to perform local optimization:\n%s\n" % ErrMsg) 327 return (False, None, None, None) 328 329 if len(Energies) == 0: 330 return (False, None, None, None) 331 332 # Write optimize pose to a temporray file and retrieve the PDBQT string for the pose... 333 (_, TmpFile) = tempfile.mkstemp(suffix = ".pdbqt", prefix = "VinaOptimize_", text = True) 334 VinaHandle.write_pose(TmpFile, overwrite = True) 335 336 TmpFH = open(TmpFile, "r") 337 PosePDBQTOutputStr = TmpFH.read() 338 TmpFH.close() 339 340 os.remove(TmpFile) 341 342 # Setup a mol containing optimized pose... 343 try: 344 PosePDBQTOutputMol = PDBQTMolecule(PosePDBQTOutputStr) 345 PoseMols = RDKitMolCreate.from_pdbqt_mol(PosePDBQTOutputMol) 346 except Exception as ErrMsg: 347 if not OptionsInfo["QuietMode"]: 348 MiscUtil.PrintWarning("Failed to retrieve optimize pose:\n%s\n" % ErrMsg) 349 return (False, None, None, None) 350 351 if len(PoseMols) == 0: 352 return (False, None, None, None) 353 354 Status = True 355 PoseMol = PoseMols[0] 356 357 return (Status, PoseMol, Energies, PoseMolFlexRes) 358 359 def ProcessMoleculeForDockMode(VinaHandle, Mol): 360 """Dock and score molecule.""" 361 362 Status, PoseMol, Energies, PoseMolFlexRes = [False, None, None, None] 363 364 # Dock molecule... 365 try: 366 VinaHandle.dock(exhaustiveness = OptionsInfo["Exhaustiveness"] , n_poses = OptionsInfo["NumPoses"], min_rmsd = OptionsInfo["MinRMSD"], max_evals = OptionsInfo["MaxEvaluations"]) 367 except Exception as ErrMsg: 368 if not OptionsInfo["QuietMode"]: 369 MiscUtil.PrintWarning("Failed to dock molecule:\n%s\n" % ErrMsg) 370 return (False, None, None, None) 371 372 # Retrieve poses... 373 try: 374 PosePDBQTOutputStr = VinaHandle.poses(n_poses = OptionsInfo["NumPoses"], energy_range = OptionsInfo["EnergyRange"], coordinates_only = False) 375 except Exception as ErrMsg: 376 if not OptionsInfo["QuietMode"]: 377 MiscUtil.PrintWarning("Failed to retrieve docked poses:\n%s\n" % ErrMsg) 378 return (False, None, None, None) 379 380 PoseMol, PoseMolFlexRes = SetupPoseMols(PosePDBQTOutputStr) 381 if PoseMol is None: 382 return (False, None, None, None) 383 384 # Retrieve energies... 385 try: 386 Energies = VinaHandle.energies(n_poses = OptionsInfo["NumPoses"], energy_range = OptionsInfo["EnergyRange"]) 387 except Exception as ErrMsg: 388 if not OptionsInfo["QuietMode"]: 389 MiscUtil.PrintWarning("Failed to retrieve energies for docked poses:\n%s\n" % ErrMsg) 390 return (False, None, None, None) 391 392 if len(Energies) == 0: 393 return (False, None, None, None) 394 395 Status = True 396 397 return (Status, PoseMol, Energies, PoseMolFlexRes) 398 399 def SetupPoseMols(PosePDBQTOutputStr): 400 """Process PDBQT Vina poses string to setup pose mols for the docked 401 molecule and any flexible residues.""" 402 403 PoseMol, PoseMolFlexRes = [None, None] 404 405 # Setup a mol containing poses as conformers... 406 try: 407 PosePDBQTOutputMol = PDBQTMolecule(PosePDBQTOutputStr) 408 PoseMols = RDKitMolCreate.from_pdbqt_mol(PosePDBQTOutputMol) 409 except Exception as ErrMsg: 410 if not OptionsInfo["QuietMode"]: 411 MiscUtil.PrintWarning("Failed to retrieve docked poses:\n%s\n" % ErrMsg) 412 return (None, None) 413 414 if len(PoseMols) == 0: 415 return (None, None) 416 417 # First mol is the pose for docked molecule... 418 PoseMol = PoseMols.pop(0) 419 420 # Collect pose mols foe flexible side chain residues... 421 PoseMolsFlexRes = [] 422 for Mol in PoseMols: 423 if not Mol.HasProp("meeko"): 424 continue 425 MeekoPropMap = json.loads(Mol.GetProp("meeko")) 426 if type(MeekoPropMap) is dict: 427 if "is_sidechain" in MeekoPropMap: 428 if MeekoPropMap["is_sidechain"]: 429 PoseMolsFlexRes.append(Mol) 430 431 # Combine pose mols for flexible side chain residues into a single pose mol... 432 if len(PoseMolsFlexRes): 433 for Mol in PoseMolsFlexRes: 434 if PoseMolFlexRes is None: 435 PoseMolFlexRes = Mol 436 else: 437 PoseMolFlexRes = Chem.CombineMols(PoseMolFlexRes, Mol) 438 439 if PoseMolFlexRes is not None: 440 PoseMolConfCount = PoseMol.GetNumConformers() 441 PoseMolFlexResConfCount = PoseMolFlexRes.GetNumConformers() 442 if PoseMolConfCount != PoseMolFlexResConfCount: 443 if not OptionsInfo["QuietMode"]: 444 MiscUtil.PrintWarning("The number of poses, %s, for flexible residues doesn't match number of poses, %s, for docked molecule...\n" % (PoseMolFlexResConfCount, PoseMolConfCount)) 445 446 return (PoseMol, PoseMolFlexRes) 447 448 def PrepareMolecule(MolPrepHandle, Mol): 449 """Prepare molecule for docking. """ 450 451 try: 452 PreppedMols = MolPrepHandle.prepare(Mol) 453 except Exception as ErrMsg: 454 if not OptionsInfo["QuietMode"]: 455 MiscUtil.PrintWarning("Failed to prepare molecule for docking:\n%s\n" % ErrMsg) 456 return None 457 458 if len(PreppedMols) == 0: 459 return None 460 461 PreppedMol = PreppedMols[0] 462 463 # Setup PDBQT mole string... 464 try: 465 PDBQTMolStr, Status, ErrMsg = PDBQTWriterLegacy.write_string(PreppedMol) 466 except Exception as ExceptionErrMsg: 467 if not OptionsInfo["QuietMode"]: 468 MiscUtil.PrintWarning("Failed to prepare molecule for docking:\n%s\n" % ExceptionErrMsg) 469 return None 470 471 if not Status: 472 if not OptionsInfo["QuietMode"]: 473 MiscUtil.PrintWarning("Failed to prepare molecule for docking:\n%s\n" % ErrMsg) 474 return None 475 476 if MiscUtil.IsEmpty(PDBQTMolStr): 477 return None 478 479 return PDBQTMolStr 480 481 def InitializeVina(Quiet = False): 482 """Initialize AutoDock Vina. """ 483 484 if not Quiet: 485 MiscUtil.PrintInfo("\nInitializing Vina...") 486 487 VinaHandle = Vina(sf_name = OptionsInfo["Forcefield"], cpu = OptionsInfo["NumThreads"], seed = OptionsInfo["RandomSeed"], no_refine = OptionsInfo["SkipRefinement"], verbosity = OptionsInfo["VinaVerbosity"]) 488 489 SetupReceptor(VinaHandle, Quiet) 490 SetupForcefieldWeights(VinaHandle, Quiet) 491 SetupReceptorMaps(VinaHandle, Quiet) 492 493 return VinaHandle 494 495 def SetupReceptor(VinaHandle, Quiet = False): 496 """Setup receptor """ 497 498 if OptionsInfo["UseReceptorFile"] and OptionsInfo["UseReceptorFlexFile"]: 499 VinaHandle.set_receptor(rigid_pdbqt_filename = OptionsInfo["ReceptorFile"], flex_pdbqt_filename = OptionsInfo["ReceptorFlexFile"]) 500 elif OptionsInfo["UseReceptorFile"]: 501 VinaHandle.set_receptor(rigid_pdbqt_filename = OptionsInfo["ReceptorFile"], flex_pdbqt_filename = None) 502 elif OptionsInfo["UseReceptorFlexFile"]: 503 VinaHandle.set_receptor(rigid_pdbqt_filename = None, flex_pdbqt_filename = OptionsInfo["ReceptorFlexFile"]) 504 505 def SetupForcefieldWeights(VinaHandle, Quiet = False): 506 """Setup forcefield weights. """ 507 508 Weights = OptionsInfo["ForcefieldWeightParams"] 509 Forcefield = OptionsInfo["Forcefield"] 510 if not OptionsInfo["ForcefieldWeightParamsSpecified"]: 511 if not Quiet: 512 MiscUtil.PrintInfo("\nUsing default forcefield weights for %s..." % Forcefield) 513 return 514 515 if not Quiet: 516 MiscUtil.PrintInfo("\nSetting specified forcefield weights for %s..." % Forcefield) 517 518 if OptionsInfo["UseAD4Forcefield"]: 519 VinaHandle.set_weights([Weights["AD4Vdw"], Weights["AD4HydrogenBond"], Weights["AD4Electrostatic"], Weights["AD4Desolvation"], Weights["AD4GlueLinearAttraction"], Weights["AD4Rot"]]) 520 elif OptionsInfo["UseVinaForcefield"]: 521 VinaHandle.set_weights([Weights["VinaGaussian1"], Weights["VinaGaussian2"], Weights["VinaRepulsion"], Weights["VinaHydrophobic"], Weights["VinaHydrogenBond"], Weights["VinaGlueLinearAttraction"], Weights["VinaRot"]]) 522 elif OptionsInfo["UseVinardoForcefield"]: 523 VinaHandle.set_weights([Weights["VinardoGaussian1"], Weights["VinardoRepulsion"], Weights["VinardoHydrophobic"], Weights["VinardoHydrogenBond"], Weights["VinardoGlueLinearAttraction"], Weights["VinardoRot"]]) 524 else: 525 MiscUtil.PrintError("The value specified, %s, for option \"-f, --forcefield\" is not valid. Supported values: AD4 Vina Vinardo" % Forcefield) 526 527 def SetupReceptorMaps(VinaHandle, Quiet = False): 528 """Setup receptor maps.""" 529 530 if not Quiet: 531 MiscUtil.PrintInfo("\nSetting up receptor and maps for %s forcefield..." % OptionsInfo["Forcefield"]) 532 533 if OptionsInfo["UseAD4Forcefield"]: 534 # Load maps for rigid portion of the receptor... 535 VinaHandle.load_maps(OptionsInfo["ReceptorMapsPrefix"]) 536 elif OptionsInfo["UseVinaForcefield"] or OptionsInfo["UseVinardoForcefield"]: 537 # Load or compute maps for rigid portion of the receptor... 538 if OptionsInfo["UseReceptorMapsPrefix"]: 539 VinaHandle.load_maps(OptionsInfo["ReceptorMapsPrefix"]) 540 else: 541 VinaHandle.compute_vina_maps(center = OptionsInfo["GridCenterList"], box_size = OptionsInfo["GridSizeList"], spacing = OptionsInfo["GridSpacing"], force_even_voxels = False) 542 else: 543 MiscUtil.PrintError("The value specified, %s, for option \"-f, --forcefield\" is not valid. Supported values: AD4 Vina Vinardo" % OptionsInfo["Forcefield"]) 544 545 def InitializeMeekoMolPrepration(Quiet = False): 546 """Initialize meeko molecule prepration.""" 547 548 if OptionsInfo["MergeHydrogens"]: 549 MolPrep = MoleculePreparation(merge_these_atom_types=("H",)) 550 else: 551 MolPrep = MoleculePreparation(merge_these_atom_types="") 552 553 return MolPrep 554 555 def CheckAndValidateMolecule(Mol, MolCount = None): 556 """Validate molecule for docking.""" 557 558 MolName = RDKitUtil.GetMolName(Mol, MolCount) 559 if RDKitUtil.IsMolEmpty(Mol): 560 if not OptionsInfo["QuietMode"]: 561 MiscUtil.PrintWarning("Ignoring empty molecule: %s\n" % MolName) 562 return False 563 564 if not OptionsInfo["ValidateMolecules"]: 565 return True 566 567 # Check for 3D flag... 568 if not Mol.GetConformer().Is3D(): 569 if not OptionsInfo["QuietMode"]: 570 MiscUtil.PrintWarning("3D tag is not set for molecule: %s\n" % MolName) 571 572 # Check for missing hydrogens... 573 if RDKitUtil.AreHydrogensMissingInMolecule(Mol): 574 if not OptionsInfo["QuietMode"]: 575 MiscUtil.PrintWarning("Missing hydrogens in molecule: %s\n" % MolName) 576 577 return True 578 579 def WriteMolPoses(Writer, Mol, MolNum, PoseMol, Energies, WriterFlexRes = None, PoseMolFlexRes = None): 580 """Write molecule.""" 581 582 if OptionsInfo["ScoreOnlyMode"]: 583 return WriteMolPoseForScoreOnlyMode(Writer, Mol, MolNum, PoseMol, Energies) 584 elif OptionsInfo["LocalOptimizationOnlyMode"]: 585 return WriteMolPoseForLocalOptimizationOnlyMode(Writer, Mol, MolNum, PoseMol, Energies) 586 elif OptionsInfo["DockMode"]: 587 return WriteMolPosesForDockMode(Writer, Mol, MolNum, PoseMol, Energies, WriterFlexRes, PoseMolFlexRes) 588 else: 589 MiscUtil.PrintError("The value specified, %s, for option \"-m, --mode\" is not valid. Supported values: Dock LocalOptimizationOnly ScoreOnly" % OptionsInfo["Mode"]) 590 591 def WriteMolPoseForScoreOnlyMode(Writer, Mol, MolNum, PoseMol, Energies): 592 """Write out molecule and associated information for score only mode.""" 593 594 ClearMeekoMolProperties(PoseMol) 595 596 MolName = RDKitUtil.GetMolName(Mol, MolNum) 597 PoseMol.SetProp("_Name", MolName) 598 599 SetupEnergyProperties(PoseMol, Energies) 600 Writer.write(PoseMol) 601 602 return 603 604 def WriteMolPoseForLocalOptimizationOnlyMode(Writer, Mol, MolNum, PoseMol, Energies): 605 """Write out molecule and associated information for score only mode.""" 606 607 ClearMeekoMolProperties(PoseMol) 608 609 MolName = RDKitUtil.GetMolName(Mol, MolNum) 610 PoseMol.SetProp("_Name", MolName) 611 612 SetupEnergyProperties(PoseMol, Energies) 613 Writer.write(PoseMol) 614 615 def WriteMolPosesForDockMode(Writer, Mol, MolNum, PoseMol, Energies, WriterFlexRes = None, PoseMolFlexRes = None): 616 """Write out molecule and associated information for dock mode.""" 617 618 MolName = RDKitUtil.GetMolName(Mol, MolNum) 619 620 # Write out poses for docked molecule... 621 ClearMeekoMolProperties(PoseMol) 622 for PoseMolConfIndex, PoseMolConf in enumerate(PoseMol.GetConformers()): 623 PoseMolName = "%s_Pose%s" % (MolName, (PoseMolConfIndex + 1)) 624 PoseMol.SetProp("_Name", PoseMolName) 625 626 SetupEnergyProperties(PoseMol, Energies[PoseMolConfIndex]) 627 628 Writer.write(PoseMol, confId = PoseMolConf.GetId()) 629 630 # Write out poses for flexible reside side chains... 631 if WriterFlexRes is None or PoseMolFlexRes is None: 632 return 633 634 ClearMeekoMolProperties(PoseMolFlexRes) 635 for PoseMolFlexResConfIndex, PoseMolFlexResConf in enumerate(PoseMolFlexRes.GetConformers()): 636 PoseMolFlexResName = "%s_Flex_Receptor_Pose%s" % (MolName, (PoseMolFlexResConfIndex + 1)) 637 PoseMolFlexRes.SetProp("_Name", PoseMolFlexResName) 638 639 WriterFlexRes.write(PoseMolFlexRes, confId = PoseMolFlexResConf.GetId()) 640 641 def ClearMeekoMolProperties(Mol): 642 """Clear Meeko molecule properties. """ 643 644 for PropName in ["meeko"]: 645 if Mol.HasProp(PropName): 646 Mol.ClearProp(PropName) 647 648 def SetupEnergyProperties(Mol, Energies): 649 """Setup energy properties. """ 650 651 Precision = OptionsInfo["Precision"] 652 653 for Index, EnergyLabel in enumerate(OptionsInfo["EnergyLabelsList"]): 654 EnergyValueIndex = OptionsInfo["EnergyValueIndicesList"][Index] 655 EnergyValue = "%.*f" % (Precision, Energies[EnergyValueIndex]) 656 Mol.SetProp(EnergyLabel, EnergyValue) 657 658 def SetupWriters(): 659 """Setup writers for output files. """ 660 661 Writer, WriterFlexRes = [None, None] 662 663 Writer = RDKitUtil.MoleculesWriter(OptionsInfo["Outfile"], **OptionsInfo["OutfileParams"]) 664 if Writer is None: 665 MiscUtil.PrintError("Failed to setup a writer for output fie %s " % OptionsInfo["Outfile"]) 666 667 if OptionsInfo["DockMode"] and OptionsInfo["UseReceptorFlexFile"]: 668 WriterFlexRes = RDKitUtil.MoleculesWriter(OptionsInfo["OutfileFlexRes"], **OptionsInfo["OutfileParams"]) 669 if WriterFlexRes is None: 670 MiscUtil.PrintError("Failed to setup a writer for output fie %s " % OptionsInfo["OutfileFlexRes"]) 671 672 return (Writer, WriterFlexRes) 673 674 def CloseWriters(Writer, WriterFlexRes): 675 """Close writers. """ 676 677 if Writer is not None: 678 Writer.close() 679 680 if WriterFlexRes is not None: 681 WriterFlexRes.close() 682 683 def ComputeGridCenter(LigandFile): 684 """Compute grid center from ligand file.""" 685 686 GridCenter = [] 687 688 MiscUtil.PrintInfo("\nComputing grid center from reference ligand file %s..." % LigandFile) 689 690 Mols = RDKitUtil.ReadMolecules(LigandFile) 691 Mol = Mols[0] 692 693 Centroid = rdMolTransforms.ComputeCentroid(Mol.GetConformer()) 694 695 GridCenter = [Centroid.x, Centroid.y, Centroid.z] 696 697 GridCenterFormatted = ["%.3f" % Value for Value in GridCenter] 698 MiscUtil.PrintInfo("GridCenter: %s" % (" ".join(GridCenterFormatted))) 699 700 return GridCenter 701 702 def ProcessReceptorOptions(): 703 """Process receptor options. """ 704 705 ReceptorFile, ReceptorMapsPrefix, UseReceptorFile, UseReceptorMapsPrefix = [None, None, False, False] 706 707 Receptor = Options["--receptor"] 708 if os.path.isfile(Receptor): 709 ReceptorFile = Receptor 710 UseReceptorFile = True 711 else: 712 ReceptorMapsPrefix = Receptor 713 UseReceptorMapsPrefix = True 714 715 OptionsInfo["Receptor"] = Receptor 716 717 OptionsInfo["ReceptorFile"] = ReceptorFile 718 OptionsInfo["UseReceptorFile"] = UseReceptorFile 719 720 OptionsInfo["ReceptorMapsPrefix"] = ReceptorMapsPrefix 721 OptionsInfo["UseReceptorMapsPrefix"] = UseReceptorMapsPrefix 722 723 UseReceptorFlexFile = False 724 ReceptorFlexFile = None 725 if not re.match("^None$", Options["--receptorFlexFile"],re.I): 726 UseReceptorFlexFile = True 727 ReceptorFlexFile = Options["--receptorFlexFile"] 728 OptionsInfo["ReceptorFlexFile"] = ReceptorFlexFile 729 OptionsInfo["UseReceptorFlexFile"] = UseReceptorFlexFile 730 731 if OptionsInfo["UseAD4Forcefield"]: 732 if OptionsInfo["UseReceptorFile"]: 733 MiscUtil.PrintError("The value specified, %s, for option \"-r, --receptor\" is not valid for %s forcefield. Supported value: Affinity maps prefix." % (OptionsInfo["Receptor"], Options["--forcefield"])) 734 735 def ProcessForcefieldWeightParamatersOption(ParamsOptionName, ParamsOptionValue, ParamsDefaultInfo = None): 736 """Process forcefield weight paramaters option.""" 737 738 ParamsInfo = {"AD4Vdw": 0.1662, "AD4HydrogenBond": 0.1209, "AD4Electrostatic": 0.1406, "AD4Desolvation": 0.1322, "AD4GlueLinearAttraction": 50.0, "AD4Rot": 0.2983, 739 "VinaGaussian1": -0.035579, "VinaGaussian2": -0.005156, "VinaRepulsion": 0.840245, "VinaHydrophobic": -0.035069, "VinaHydrogenBond": -0.587439, "VinaGlueLinearAttraction": 50.0, "VinaRot": 0.05846, 740 "VinardoGaussian1": -0.045, "VinardoRepulsion": 0.8, "VinardoHydrophobic": -0.035, "VinardoHydrogenBond": -0.600, "VinardoGlueLinearAttraction": 50.0, "VinardoRot": 0.05846} 741 742 # Setup a canonical paramater names... 743 ValidParamNames = [] 744 CanonicalParamNamesMap = {} 745 for ParamName in sorted(ParamsInfo): 746 ValidParamNames.append(ParamName) 747 CanonicalParamNamesMap[ParamName.lower()] = ParamName 748 749 # Update default values... 750 if ParamsDefaultInfo is not None: 751 for ParamName in ParamsDefaultInfo: 752 if ParamName not in ParamsInfo: 753 MiscUtil.PrintError("The default parameter name, %s, specified using \"%s\" to function ProcessForcefieldWeightParamatersOption is not a valid name. Supported parameter names: %s" % (ParamName, ParamsDefaultInfo, " ".join(ValidParamNames))) 754 ParamsInfo[ParamName] = ParamsDefaultInfo[ParamName] 755 756 if re.match("^auto$", ParamsOptionValue, re.I): 757 return ParamsInfo 758 759 ParamsOptionValueWords = ParamsOptionValue.split(",") 760 if len(ParamsOptionValueWords) % 2: 761 Miscutil.PrintError("The number of comma delimited paramater names and values, %d, specified using \"%s\" option must be an even number." % (len(ParamsOptionValueWords), ParamsOptionName)) 762 763 # Validate paramater name and value pairs... 764 for Index in range(0, len(ParamsOptionValueWords), 2): 765 Name = ParamsOptionValueWords[Index].strip() 766 Value = ParamsOptionValueWords[Index + 1].strip() 767 768 CanonicalName = Name.lower() 769 if CanonicalName not in CanonicalParamNamesMap: 770 MiscUtil.PrintError("The parameter name, %s, specified using \"%s\" is not a valid name. Supported parameter names: %s" % (Name, ParamsOptionName, " ".join(ValidParamNames))) 771 772 ParamName = CanonicalParamNamesMap[CanonicalName] 773 774 if not MiscUtil.IsFloat(Value): 775 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" must be a float." % (Value, Name, ParamsOptionName)) 776 ParamValue = float(Value) 777 778 ParamsInfo[ParamName] = ParamValue 779 780 return ParamsInfo 781 782 def ProcessModeOption(): 783 """Process mode option.""" 784 785 Mode = Options["--mode"] 786 DockMode, LocalOptimizationOnlyMode, ScoreOnlyMode = [False] * 3 787 if re.match("^Dock$", Mode, re.I): 788 Mode = "Dock" 789 DockMode = True 790 elif re.match("^LocalOptimizationOnly$", Mode, re.I): 791 Mode = "LocalOptimizationOnly" 792 LocalOptimizationOnlyMode = True 793 elif re.match("^ScoreOnly$", Mode, re.I): 794 Mode = "ScoreOnly" 795 ScoreOnlyMode = True 796 else: 797 MiscUtil.PrintError("The value specified, %s, for option \"-m, --mode\" is not valid. Supported values: Dock LocalOptimizationOnly ScoreOnly" % OptionsInfo["Mode"]) 798 799 OptionsInfo["Mode"] = Mode 800 OptionsInfo["DockMode"] = DockMode 801 OptionsInfo["LocalOptimizationOnlyMode"] = LocalOptimizationOnlyMode 802 OptionsInfo["ScoreOnlyMode"] = ScoreOnlyMode 803 804 def ProcessEnergyLabelOptions(): 805 """Process energy label options.""" 806 807 Forcefield = OptionsInfo["Forcefield"] 808 809 EnergyLabel = Options["--energyLabel"] 810 if re.match("^auto$", EnergyLabel, re.I): 811 EnergyLabel = "%s_Total_Energy (kcal/mol)" % Forcefield 812 OptionsInfo["EnergyLabel"] = EnergyLabel 813 814 EnergyLabelsList = [] 815 DefaultLabels = ["%s_Intermolecular_Energy (kcal/mol)" % (Forcefield), "%s_Internal_Energy (kcal/mol)" % (Forcefield), "%s_Torsions_Energy (kcal/mol)" % (Forcefield)] 816 817 EnergyLabels = Options["--energyComponentsLabels"] 818 if not re.match("^auto$", EnergyLabels, re.I): 819 EnergyLabelsWords = EnergyLabels.split(",") 820 if len(EnergyLabelsWords) != 3: 821 MiscUtil.PrintError("The specified value, %s, for option \"--energyComponentsLabels \" is not valid. It must contain 3 text values separated by comma." % EnergyLabels) 822 823 for LabelIndex, Label in enumerate(EnergyLabelsWords): 824 Label = Label.strip() 825 if re.match("^auto$", Label, re.I): 826 Label = DefaultLabels[LabelIndex] 827 828 EnergyLabelsList.append(Label) 829 else: 830 EnergyLabelsList = DefaultLabels 831 832 OptionsInfo["EnergyComponentsLabels"] = EnergyLabels 833 OptionsInfo["EnergyComponentsLabelsList"] = EnergyLabelsList 834 835 SetupEnergyLabelsAndIndices() 836 837 def SetupEnergyLabelsAndIndices(): 838 """Setup energy data labels and indices for writing out energy values. """ 839 840 EnergyLabelsList = [] 841 EnergyValueIndicesList = [] 842 843 # Total energy is always at index 0 in the list retured by vina.score (), 844 # vina.optimize(), and vina.energies() during ScoreOnly, LocalOptimizationOnly 845 # and Dock modes... 846 EnergyLabelsList.append(OptionsInfo["EnergyLabel"]) 847 EnergyValueIndicesList.append(0) 848 849 OptionsInfo["EnergyLabelsList"] = EnergyLabelsList 850 OptionsInfo["EnergyValueIndicesList"] = EnergyValueIndicesList 851 852 if not OptionsInfo["EnergyComponents"]: 853 return 854 855 # Setup energy labels and indices for energy components... 856 if OptionsInfo["ScoreOnlyMode"]: 857 # vina.score returns a list containing the following values: 858 # 859 # Vina/Vinardo FF: columns=[total, lig_inter, flex_inter, other_inter, flex_intra, lig_intra, torsions, lig_intra best pose] 860 # AutoDock FF: [total, lig_inter, flex_inter, other_inter, flex_intra, lig_intra, torsions, -lig_intra] 861 # 862 IntermolecularEnergyIndex, IntramolecularEnergyIndex, TorsionEnergyIndex = [1, 5, 6] 863 elif OptionsInfo["LocalOptimizationOnlyMode"]: 864 # vina.optimize returns a list containing the following values: 865 # 866 # Vina/Vinardo FF: [total, lig_inter, flex_inter, other_inter, flex_intra, lig_intra, torsions, lig_intra best pose] 867 # AutoDock FF: [total, lig_inter, flex_inter, other_inter, flex_intra, lig_intra, torsions, -lig_intra] 868 # 869 IntermolecularEnergyIndex, IntramolecularEnergyIndex, TorsionEnergyIndex = [1, 5, 6] 870 elif OptionsInfo["DockMode"]: 871 # vina.energies returns a list containing the following values: 872 # 873 # Vina/Vinardo FF: [total, inter, intra, torsions, intra best pose] 874 # AutoDock FF: [total, inter, intra, torsions, -intra] 875 # 876 IntermolecularEnergyIndex, IntramolecularEnergyIndex, TorsionEnergyIndex = [1, 2, 3] 877 else: 878 MiscUtil.PrintError("The value specified, %s, for option \"-m, --mode\" is not valid. Supported values: Dock LocalOptimizationOnly ScoreOnly" % OptionsInfo["Mode"]) 879 880 OptionsInfo["EnergyLabelsList"].extend(OptionsInfo["EnergyComponentsLabelsList"]) 881 OptionsInfo["EnergyValueIndicesList"].extend([IntermolecularEnergyIndex, IntramolecularEnergyIndex, TorsionEnergyIndex]) 882 883 def ProcessOptions(): 884 """Process and validate command line arguments and options.""" 885 886 MiscUtil.PrintInfo("Processing options...") 887 888 # Validate options... 889 ValidateOptions() 890 891 OptionsInfo["Infile"] = Options["--infile"] 892 ParamsDefaultInfoOverride = {"RemoveHydrogens": False} 893 OptionsInfo["InfileParams"] = MiscUtil.ProcessOptionInfileParameters("--infileParams", Options["--infileParams"], InfileName = Options["--infile"], ParamsDefaultInfo = ParamsDefaultInfoOverride) 894 895 OptionsInfo["Outfile"] = Options["--outfile"] 896 OptionsInfo["OutfileParams"] = MiscUtil.ProcessOptionOutfileParameters("--outfileParams", Options["--outfileParams"]) 897 898 FileDir, FileName, FileExt = MiscUtil.ParseFileName(Options["--outfile"]) 899 OptionsInfo["OutfileFlexRes"] = "%s_Flex_Receptor.%s" % (FileName, FileExt) 900 901 GridCenterLigandFile, GridCenterList, GridCenterByLigandFile= [None, None, False] 902 GridCenter = Options["--gridCenter"] 903 if re.search(",", GridCenter, re.I): 904 GridCenterList = [float(Value) for Value in GridCenter.split(",")] 905 else: 906 GridCenterByLigandFile = True 907 GridCenterLigandFile = GridCenter 908 GridCenterList = ComputeGridCenter(GridCenterLigandFile) 909 910 OptionsInfo["GridCenter"] = GridCenter 911 OptionsInfo["GridCenterList"] = GridCenterList 912 OptionsInfo["GridCenterLigandFile"] = GridCenterLigandFile 913 OptionsInfo["GridCenterByLigandFile"] = GridCenterByLigandFile 914 915 OptionsInfo["EnergyComponents"] = True if re.match("^yes$", Options["--energyComponents"], re.I) else False 916 917 OptionsInfo["EnergyRange"] = float(Options["--energyRange"]) 918 OptionsInfo["Exhaustiveness"] = int(Options["--exhaustiveness"]) 919 920 Forcefield = Options["--forcefield"] 921 UseAD4Forcefield, UseVinaForcefield, UseVinardoForcefield = [False, False, False] 922 if re.match("^AD4$", Forcefield, re.I): 923 Forcefield = "AD4" 924 UseAD4Forcefield = True 925 elif re.match("^Vina$", Forcefield, re.I): 926 Forcefield = "Vina" 927 UseVinaForcefield = True 928 elif re.match("^Vinardo$", Forcefield, re.I): 929 Forcefield = "Vinardo" 930 UseVinardoForcefield = True 931 else: 932 MiscUtil.PrintError("The value specified, %s, for option \"-f, --forcefield\" is not valid. Supported values: AD4 Vina Vinardo") 933 OptionsInfo["Forcefield"] = Forcefield 934 OptionsInfo["UseAD4Forcefield"] = UseAD4Forcefield 935 OptionsInfo["UseVinaForcefield"] = UseVinaForcefield 936 OptionsInfo["UseVinardoForcefield"] = UseVinardoForcefield 937 938 OptionsInfo["ForcefieldWeightParams"] = ProcessForcefieldWeightParamatersOption('--forcefieldWeightParams', Options["--forcefieldWeightParams"]) 939 OptionsInfo["ForcefieldWeightParamsSpecified"] = False if re.match("^auto$", Options["--forcefieldWeightParams"], re.I) else True 940 941 GridSize = Options["--gridSize"] 942 GridSizeList = [float(Value) for Value in GridSize.split(",")] 943 OptionsInfo["GridSize"] = GridSize 944 OptionsInfo["GridSizeList"] = GridSizeList 945 946 OptionsInfo["GridSpacing"] = float(Options["--gridSpacing"]) 947 948 OptionsInfo["MaxEvaluations"] = int(Options["--maxEvaluations"]) 949 OptionsInfo["MinRMSD"] = float(Options["--minRMSD"]) 950 951 MergeHydrogens = Options["--mergeHydrogens"] 952 if re.match("^auto$", MergeHydrogens, re.I): 953 MergeHydrogens = True if OptionsInfo["UseAD4Forcefield"] else False 954 else: 955 MergeHydrogens = True if re.match("^yes$", MergeHydrogens, re.I) else False 956 OptionsInfo["MergeHydrogens"] = MergeHydrogens 957 958 ProcessModeOption() 959 960 OptionsInfo["MPMode"] = True if re.match("^yes$", Options["--mp"], re.I) else False 961 OptionsInfo["MPParams"] = MiscUtil.ProcessOptionMultiprocessingParameters("--mpParams", Options["--mpParams"]) 962 963 OptionsInfo["NumPoses"] = int(Options["--numPoses"]) 964 965 if re.match("^auto$", Options["--numThreads"], re.I): 966 NumThreads = 1 if OptionsInfo["MPMode"] else 0 967 else: 968 NumThreads = int(Options["--numThreads"]) 969 OptionsInfo["NumThreads"] = NumThreads 970 971 OptionsInfo["Precision"] = int(Options["--precision"]) 972 OptionsInfo["RandomSeed"] = int(Options["--randomSeed"]) 973 974 OptionsInfo["SkipRefinement"] = True if re.match("^yes$", Options["--skipRefinement"], re.I) else False 975 976 OptionsInfo["ValidateMolecules"] = True if re.match("^yes$", Options["--validateMolecules"], re.I) else False 977 978 if re.match("^auto$", Options["--vinaVerbosity"], re.I): 979 VinaVerbosity = 0 if OptionsInfo["MPMode"] else 1 980 else: 981 VinaVerbosity = int(Options["--vinaVerbosity"]) 982 OptionsInfo["VinaVerbosity"] = VinaVerbosity 983 984 OptionsInfo["Overwrite"] = Options["--overwrite"] 985 OptionsInfo["QuietMode"] = True if re.match("^yes$", Options["--quiet"], re.I) else False 986 987 ProcessEnergyLabelOptions() 988 ProcessReceptorOptions() 989 990 def RetrieveOptions(): 991 """Retrieve command line arguments and options.""" 992 993 # Get options... 994 global Options 995 Options = docopt(_docoptUsage_) 996 997 # Set current working directory to the specified directory... 998 WorkingDir = Options["--workingdir"] 999 if WorkingDir: 1000 os.chdir(WorkingDir) 1001 1002 # Handle examples option... 1003 if "--examples" in Options and Options["--examples"]: 1004 MiscUtil.PrintInfo(MiscUtil.GetExamplesTextFromDocOptText(_docoptUsage_)) 1005 sys.exit(0) 1006 1007 def ValidateOptions(): 1008 """Validate option values.""" 1009 1010 MiscUtil.ValidateOptionFilePath("-i, --infile", Options["--infile"]) 1011 MiscUtil.ValidateOptionFileExt("-i, --infile", Options["--infile"], "sdf sd mol") 1012 1013 MiscUtil.ValidateOptionFileExt("-o, --outfile", Options["--outfile"], "sdf sd") 1014 MiscUtil.ValidateOptionsOutputFileOverwrite("-o, --outfile", Options["--outfile"], "--overwrite", Options["--overwrite"]) 1015 MiscUtil.ValidateOptionsDistinctFileNames("-i, --infile", Options["--infile"], "-o, --outfile", Options["--outfile"]) 1016 1017 FileDir, FileName, FileExt = MiscUtil.ParseFileName(Options["--receptor"]) 1018 if not MiscUtil.IsEmpty(FileExt): 1019 MiscUtil.ValidateOptionFilePath("-r, --receptor", Options["--receptor"]) 1020 MiscUtil.ValidateOptionFileExt("-r, --receptor", Options["--receptor"], "pdbqt") 1021 else: 1022 AffinityMapFiles = glob.glob("%s.*.map" % Options["--receptor"]) 1023 if len(AffinityMapFiles) == 0: 1024 MiscUtil.PrintError("The receptor affinity map files, %s.*.map, corresponding to maps prefix, %s, specified using option, \"-r, --receptor\" option don't exist." % (Options["--receptor"], Options["--receptor"])) 1025 1026 if not re.match("^None$", Options["--receptorFlexFile"],re.I): 1027 MiscUtil.ValidateOptionFilePath("--receptorFlexFile", Options["--receptorFlexFile"]) 1028 MiscUtil.ValidateOptionFileExt("--receptorFlexFile", Options["--receptorFlexFile"], "pdbqt") 1029 if os.path.isfile(Options["--receptor"]): 1030 MiscUtil.ValidateOptionsDistinctFileNames("-r, --receptor", Options["--receptor"], "--receptorFlexFile", Options["--receptorFlexFile"]) 1031 1032 if re.search(",", Options["--gridCenter"], re.I): 1033 MiscUtil.ValidateOptionNumberValues("-g, --gridCenter", Options["--gridCenter"], 3, ",", "float", {">=" : 0.0}) 1034 else: 1035 MiscUtil.ValidateOptionFilePath("-g, --gridCenter", Options["--gridCenter"]) 1036 MiscUtil.ValidateOptionFileExt("-g, --gridCenter", Options["--gridCenter"], "sdf sd mol pdb") 1037 1038 MiscUtil.ValidateOptionTextValue("--energyComponents", Options["--energyComponents"], "yes no") 1039 1040 MiscUtil.ValidateOptionFloatValue("--energyRange", Options["--energyRange"], {">": 0}) 1041 1042 MiscUtil.ValidateOptionIntegerValue("--exhaustiveness", Options["--exhaustiveness"], {">": 0}) 1043 1044 MiscUtil.ValidateOptionTextValue("-f, --forcefield", Options["--forcefield"], "AD4 Vina Vinardo") 1045 1046 MiscUtil.ValidateOptionNumberValues("--gridSize", Options["--gridSize"], 3, ",", "float", {">" : 0.0}) 1047 MiscUtil.ValidateOptionFloatValue("--gridSpacing", Options["--gridSpacing"], {">": 0}) 1048 1049 MiscUtil.ValidateOptionIntegerValue("--maxEvaluations", Options["--maxEvaluations"], {">=": 0}) 1050 MiscUtil.ValidateOptionFloatValue("--minRMSD", Options["--minRMSD"], {">": 0}) 1051 1052 MiscUtil.ValidateOptionTextValue("--mergeHydrogens", Options["--mergeHydrogens"], "yes no auto") 1053 1054 MiscUtil.ValidateOptionTextValue("-m, --mode", Options["--mode"], "Dock LocalOptimizationOnly ScoreOnly") 1055 1056 MiscUtil.ValidateOptionTextValue("--mp", Options["--mp"], "yes no") 1057 1058 MiscUtil.ValidateOptionIntegerValue("--numPoses", Options["--numPoses"], {">": 0}) 1059 1060 if not re.match("^auto$", Options["--numThreads"], re.I): 1061 MiscUtil.ValidateOptionIntegerValue("--numThreads", Options["--numThreads"], {">": 0}) 1062 1063 MiscUtil.ValidateOptionIntegerValue("-p, --precision", Options["--precision"], {">": 0}) 1064 MiscUtil.ValidateOptionIntegerValue("--randomSeed", Options["--randomSeed"], {}) 1065 1066 MiscUtil.ValidateOptionTextValue("--skipRefinement", Options["--skipRefinement"], "yes no") 1067 1068 MiscUtil.ValidateOptionTextValue("-v, --validateMolecules", Options["--validateMolecules"], "yes no") 1069 1070 if not re.match("^auto$", Options["--vinaVerbosity"], re.I): 1071 MiscUtil.ValidateOptionIntegerValue("--vinaVerbosity", Options["--vinaVerbosity"], {">=": 0}) 1072 MiscUtil.ValidateOptionTextValue("--vinaVerbosity", Options["--vinaVerbosity"], "0 1 2") 1073 1074 MiscUtil.ValidateOptionTextValue("-q, --quiet", Options["--quiet"], "yes no") 1075 1076 # Setup a usage string for docopt... 1077 _docoptUsage_ = """ 1078 VinaPerformDocking.py - Perform docking 1079 1080 Usage: 1081 VinaPerformDocking.py [--energyComponents <yes or no>] [--energyComponentsLabels <Label1, label2, Label3>] 1082 [--energyLabel <text>] [--energyRange <number>] [--exhaustiveness <number>] 1083 [--forcefield <AD4, Vina, or Vinardo>] [--forcefieldWeightParams <Name,Value,...>] [--gridSpacing <number>] 1084 [--gridSize <xsize,ysize,zsize>] [--infileParams <Name,Value,...>] [--maxEvaluations <number>] 1085 [--mergeHydrogens <yes or no>] [--minRMSD <number>] [--mode <Dock, LocalOptimizationOnly, ScoreOnly>] [--mp <yes or no>] 1086 [--mpParams <Name, Value,...>] [--numPoses <number>] [--numThreads <number>] [--outfileParams <Name,Value,...> ] 1087 [--overwrite] [--precision <number>] [--quiet <yes or no>] [--randomSeed <number>] [--receptorFlexFile <receptor flex file>] 1088 [--skipRefinement <yes or no>] [--validateMolecules <yes or no>] [--vinaVerbosity <number>] 1089 [-w <dir>] -g <RefLigandFile or x,y,z> -r <receptorfile or maps prerfix> -i <infile> -o <outfile> 1090 VinaPerformDocking.py -h | --help | -e | --examples 1091 1092 Description: 1093 Dock molecules against a protein receptor using AutoDock Vina [Ref 168, 169]. 1094 The molecules must have 3D coordinates in input file. In addition, the hydrogens 1095 must be present for all molecules in input file. 1096 1097 No protein receptor preparation is performed during docking. It must be prepared 1098 employing standalone scripts available as part of AutoDock Vina. You may 1099 optionally specify flexible residues in the binding pocket to prepare a flexible 1100 receptor file and employ it for docking molecules along with the fixed receptor 1101 file. 1102 1103 The following three forecefileds are available to score molecules: AD4 1104 (AutoDock4), Vina, and Vinardo (Vina RaDii Optimized) [Ref 170]. 1105 1106 The supported input file formats are shown below: 1107 1108 Rigid/Flexible protein receptor files - PDBQT(.pdbqt) 1109 Reference ligand file: PDB(.pdb), Mol (.mol), SD (.sdf, .sd) 1110 1111 Input molecules file - Mol (.mol), SD (.sdf, .sd) 1112 1113 The supported output file format is: SD (.sdf, .sd). 1114 1115 The following output files are generated: 1116 1117 <OutfileRoot>.<OutfileExt> - Docked/scored molecules 1118 <OutfileRoot>_Flex_Receptor.<OutfileExt> - Docked poses for flexible 1119 residues 1120 1121 The flexible receptor output file contains docked poses corresponding to 1122 flexible residues. It is only generated during 'Dock' value of '-m, --mode' 1123 option. The number of poses in this file matches those written to the 1124 output file containing docked molecules. 1125 1126 Options: 1127 --energyComponents <yes or no> [default: no] 1128 Write out binding energy components of the total binding energy docking 1129 score to outfile. The following three energy components are written to 1130 outfile: intermolecula energy, internal energy, and torsions energy. 1131 --energyComponentsLabels <Label1, label2, Label3> [default: auto] 1132 A triplet of comma delimited values corresponding to energy data field 1133 labels for writing out the binding energy components to outfile. You must 1134 specify all three values. A value of 'None' implies the use of the default 1135 labels as shown below: 1136 1137 Label1: <ForcefieldName>_Intermolecular_Energy (kcal/mol) 1138 Label2: <ForcefieldName>_Internal_Energy (kcal/mol) 1139 Label3: <ForcefieldName>_Torsions_Energy (kcal/mol) 1140 1141 --energyLabel <text> [default: auto] 1142 Energy data field label for writing out binding energy docking score to 1143 output file. Default: <ForcefieldName>_Total_Energy (kcal/mol). 1144 --energyRange <number> [default: 3.0] 1145 Maximum energy difference from the best pose during the generation of 1146 poses. Units: kcal/mol. 1147 -e, --examples 1148 Print examples. 1149 --exhaustiveness <number> [default: 8] 1150 Exhaustiveness of global MC search. The higher values make the search 1151 more exhaustive and it takes longer to complete. You may want to use 1152 '16' or '32' as the value of '--exhaustiveness ' to increase the accuracy of 1153 your pose prediction. 1154 -f, --forcefield <AD4, Vina, or Vinardo> [default: Vina] 1155 Forcefield to use for scoring. Possible values: AD4 (AutoDock 4), Vina 1156 [Ref 169, 169], or Vinardo (Vina RaDii Optimized) [Ref 170]. 1157 1158 You must specify affinity maps using '-r, --receptor' option during the use 1159 of 'AD4' forcefield. 1160 --forcefieldWeightParams <Name,Value,...> [default: auto] 1161 A comma delimited list of parameter name and value pairs for forcefield 1162 scoring. 1163 1164 The supported parameter names along with their default values are 1165 are shown below for different forcefields: 1166 1167 AD4 (6 weights): 1168 1169 ad4Vdw, 0.1662, ad4HydrogenBond, 0.1209, ad4Electrostatic, 0.1406, 1170 ad4Desolvation, 0.1322, ad4GlueLinearAttraction, 50.0, 1171 ad4Rot, 0.2983 1172 1173 Vina (7 weights): 1174 1175 vinaGaussian1, -0.035579, vinaGaussian2, -0.005156, 1176 vinaRepulsion, 0.840245, vinaHydrophobic, -0.035069, 1177 vinaHydrogenBond, -0.587439, vinaGlueLinearAttraction, 50.0, 1178 vinaRot, 0.05846 1179 1180 Vinardo (6 weights): 1181 1182 vinardoGaussian1, -0.045, vinardoRepulsion, 0.8, 1183 vinardoHydrophobic, -0.035, vinardoHydrogenBond, -0.600 1184 vinardoGlueLinearAttraction, 50.0, vinardoRot, 0.05846 1185 1186 The glue weight parameter corresponds to linear attraction for macrocycle 1187 closure and has the same value for AD4, Vina, and Vinardo. The rot weight 1188 has the same value for Vina and Vinardo. 1189 -g, --gridCenter <RefLigandFile or x,y,z> 1190 Reference ligand file for calculating the docking grid center or a triplet 1191 of comma delimited values in Angstrom corresponding to grid center. 1192 1193 This is required option. However, it is ignored during the specification 1194 of maps prefix for '-r, --receptor' option. 1195 --gridSize <xsize,ysize,zsize> [default: 25.0, 25.0, 25.0] 1196 Docking grid size in Angstrom. 1197 --gridSpacing <number> [default: 0.375] 1198 Docking grid spacing in Angstrom. 1199 -h, --help 1200 Print this help message. 1201 -i, --infile <infile> 1202 Input file name containing molecules for docking against a receptor. The 1203 molecules must have 3D coordinates in input file. In addition, the hydrogens 1204 must be present for all molecules in input file. The input file may contain 3D 1205 conformers. 1206 --infileParams <Name,Value,...> [default: auto] 1207 A comma delimited list of parameter name and value pairs for reading 1208 molecules from files. The supported parameter names for different file 1209 formats, along with their default values, are shown below: 1210 1211 SD, MOL: removeHydrogens,no,sanitize,yes,strictParsing,yes 1212 1213 --maxEvaluations <number> [default: 0] 1214 Maximum number of evaluations to perform for each MC run during docking. 1215 By default, its value is set 0 and the number of MC evaluations is determined 1216 using heuristic rules. 1217 --mergeHydrogens <yes or no> [default: auto] 1218 Merge hydrogens during preparation of molecules for docking. The hydrogens 1219 are automatically merged during 'AD4' value of '-f, --forcefield' option and its 1220 value is set to 'yes'. Otherwise, it's set to 'no'. 1221 --minRMSD <number> [default: 1.0] 1222 Minimum RMSD between output poses in Angstrom. 1223 -m, --mode <Dock, LocalOptimizationOnly, ScoreOnly> [default: Dock] 1224 Dock molecules or simply score molecules without performing any docking. 1225 The supported values along with a brief explanation of the expected 1226 behavior are shown below: 1227 1228 Dock: Global search along with local optimization and scoring after 1229 docking 1230 LocalOptimizationOnly: Local optimization and scoring without any docking 1231 ScoreOnly: Scoring without any local optimizatiom and docking 1232 1233 The 'ScoreOnly" allows you to score 3D moleculed from input file which 1234 are already positioned in a binding pocket of a receptor. 1235 --mp <yes or no> [default: no] 1236 Use multiprocessing. 1237 1238 By default, input data is retrieved in a lazy manner via mp.Pool.imap() 1239 function employing lazy RDKit data iterable. This allows processing of 1240 arbitrary large data sets without any additional requirements memory. 1241 1242 All input data may be optionally loaded into memory by mp.Pool.map() 1243 before starting worker processes in a process pool by setting the value 1244 of 'inputDataMode' to 'InMemory' in '--mpParams' option. 1245 1246 A word to the wise: The default 'chunkSize' value of 1 during 'Lazy' input 1247 data mode may adversely impact the performance. The '--mpParams' section 1248 provides additional information to tune the value of 'chunkSize'. 1249 --mpParams <Name,Value,...> [default: auto] 1250 A comma delimited list of parameter name and value pairs to configure 1251 multiprocessing. 1252 1253 The supported parameter names along with their default and possible 1254 values are shown below: 1255 1256 chunkSize, auto 1257 inputDataMode, Lazy [ Possible values: InMemory or Lazy ] 1258 numProcesses, auto [ Default: mp.cpu_count() ] 1259 1260 These parameters are used by the following functions to configure and 1261 control the behavior of multiprocessing: mp.Pool(), mp.Pool.map(), and 1262 mp.Pool.imap(). 1263 1264 The chunkSize determines chunks of input data passed to each worker 1265 process in a process pool by mp.Pool.map() and mp.Pool.imap() functions. 1266 The default value of chunkSize is dependent on the value of 'inputDataMode'. 1267 1268 The mp.Pool.map() function, invoked during 'InMemory' input data mode, 1269 automatically converts RDKit data iterable into a list, loads all data into 1270 memory, and calculates the default chunkSize using the following method 1271 as shown in its code: 1272 1273 chunkSize, extra = divmod(len(dataIterable), len(numProcesses) * 4) 1274 if extra: chunkSize += 1 1275 1276 For example, the default chunkSize will be 7 for a pool of 4 worker processes 1277 and 100 data items. 1278 1279 The mp.Pool.imap() function, invoked during 'Lazy' input data mode, employs 1280 'lazy' RDKit data iterable to retrieve data as needed, without loading all the 1281 data into memory. Consequently, the size of input data is not known a priori. 1282 It's not possible to estimate an optimal value for the chunkSize. The default 1283 chunkSize is set to 1. 1284 1285 The default value for the chunkSize during 'Lazy' data mode may adversely 1286 impact the performance due to the overhead associated with exchanging 1287 small chunks of data. It is generally a good idea to explicitly set chunkSize to 1288 a larger value during 'Lazy' input data mode, based on the size of your input 1289 data and number of processes in the process pool. 1290 1291 The mp.Pool.map() function waits for all worker processes to process all 1292 the data and return the results. The mp.Pool.imap() function, however, 1293 returns the the results obtained from worker processes as soon as the 1294 results become available for specified chunks of data. 1295 1296 The order of data in the results returned by both mp.Pool.map() and 1297 mp.Pool.imap() functions always corresponds to the input data. 1298 -n, --numPoses <number> [default: 1] 1299 Number of docked poses to generate for each molecule and write out 1300 to output file. This option is only valid for 'Dock' value of '-m, --mode' 1301 option. 1302 --numThreads <number> [default: auto] 1303 Number of threads/CPUs to use for MC search calculation in Vina. The 1304 default value is set to 1 during multiprocessing for 'Yes' value of '--mp' 1305 option. Otherwise, it's set to 0 and rely on Vina detect and use all 1306 available CPUs for multi-threading. 1307 -o, --outfile <outfile> 1308 Output file name for writing out molecules. The flexible receptor residues 1309 are written to <OutfileRoot>_Flex_Receptor.<OutfileExt>. 1310 --outfileParams <Name,Value,...> [default: auto] 1311 A comma delimited list of parameter name and value pairs for writing 1312 molecules to files. The supported parameter names for different file 1313 formats, along with their default values, are shown below: 1314 1315 SD: kekulize,yes,forceV3000,no 1316 1317 --overwrite 1318 Overwrite existing files. 1319 --precision <number> [default: 2] 1320 Floating point precision for writing energy values. 1321 -q, --quiet <yes or no> [default: no] 1322 Use quiet mode. The warning and information messages will not be printed. 1323 --randomSeed <number> [default: 0] 1324 Random seed for MC search calculations. A value of zero implies it's randomly 1325 chosen by Vina during the calculation. 1326 -r, --receptor <receptor file or maps prerfix> 1327 Protein receptor file name or prefix for affinity map files corresponding 1328 to the fixed portion of the receptor. 1329 1330 You must specify affinity map files for 'AD4' forcefield. The affinity map 1331 files correspond to <MapsPrefix>.*.map and must be present 1332 1333 The supported receptor file format is PDBQT (.pdbqt). It must contain a 1334 prepared protein receptor ready for docking. You may prepare a PDBQT 1335 receptor file from a PDB file employing the command line scripts available 1336 with AutoDock Vina and Meeko. For example: prepare_receptor, 1337 prepare_flexreceptor.py, or or mk_make_recepror.py. 1338 1339 You may want to perform the following steps to clean up your PDB file 1340 before generating a PDBQT receptor file: Remove extraneous molecules 1341 such as solvents, ions, and ligand etc.; Extract data for a chain containing 1342 the binding pocket of interest. 1343 --receptorFlexFile <receptor flex file> [default: none] 1344 Protein receptor file name corresponding to the flexible portion of the 1345 receptor. The supported receptor file format is PDBQT (.pdbqt). It must 1346 contain a prepared protein receptor ready for docking. You may prepare 1347 a flexible PDBQT receptor file from a PDB file employing the command line 1348 script prepare_flexreceptor or mk_make_recepror.py available with Autodock 1349 Vina and Meeko. 1350 --skipRefinement <yes or no> [default: no] 1351 Skip refinement. Vina is initialized to skip the use of explicit receptor atoms, 1352 instead of precalculated grids, during the following three docking modes: 1353 Dock, LocalOptimizationOnly, and ScoreOnly. 1354 -v, --validateMolecules <yes or no> [default: yes] 1355 Validate molecules for docking. The input molecules must have 3D coordinates 1356 and the hydrogens must be present. You may skip validation of molecules in 1357 input file containing all valid molecules. 1358 --vinaVerbosity <number> [default: auto] 1359 Verbosity level for running Vina. Possible values: 0 - No output; 1 - Normal 1360 output; 2 - Verbose. Default: 0 during multiprocessing for 'Yes' value of '--mp' 1361 option; otherwise, its set to 1. A non-zero value is not recommended during 1362 multiprocessing. It doesn't work due to the mingling of the Vina output 1363 from multiple processes. 1364 -w, --workingdir <dir> 1365 Location of working directory which defaults to the current directory. 1366 1367 Examples: 1368 To dock molecules using Vina forcefield against a prepared receptor 1369 corresponding to chain A extracted from PDB file 1R4L.pdb, multi-threading 1370 across all available CPUs during Vina MC search, calculating grid center form 1371 a reference ligand file, using grid box size of 25 Angstrom, generating one 1372 pose for each molecule, and write out a SD file containing docked molecules, 1373 type: 1374 1375 % VinaPerformDocking.py -g SampleACE2RefLigand.pdb 1376 -r SampleACE2Receptor.pdbqt -i SampleACE2Ligands.sdf 1377 -o SampleACE2LigandsOut.sdf 1378 1379 To run the first example for generating multiple docked poses for each 1380 molecule and write out all energy terms to a SD file, type: 1381 1382 % VinaPerformDocking.py -g SampleACE2RefLigand.pdb 1383 -r SampleACE2Receptor.pdbqt --numPoses 5 --energyComponents yes 1384 -i SampleACE2Ligands.sdf -o SampleACE2LigandsOut.sdf 1385 1386 To run the first example for docking molecules using Vinardo forcefield and write 1387 out a SD file, type: 1388 1389 % VinaPerformDocking.py -f Vinardo -g SampleACE2RefLigand.pdb 1390 -r SampleACE2Receptor.pdbqt -i SampleACE2Ligands.sdf 1391 -o SampleACE2LigandsOut.sdf 1392 1393 To run the first example for docking molecules using AD4 forcefield relying on 1394 the presence of affinity maps in the working directory and write out a SD file, 1395 type: 1396 1397 % VinaPerformDocking.py -f AD4 -g SampleACE2RefLigand.pdb 1398 -r SampleACE2Receptor -i SampleACE2Ligands.sdf 1399 -o SampleACE2LigandsOut.sdf 1400 1401 To run the first example for docking molecules using a set of explicit values 1402 for grid dimensions and write out a SD file, type: 1403 1404 % VinaPerformDocking.py -g "41.399, 5.851, 28.082" 1405 --gridSize "25.0, 25.0, 25.0" --gridSpacing 0.375 1406 -r SampleACE2Receptor.pdbqt -i SampleACE2Ligands.sdf 1407 -o SampleACE2LigandsOut.sdf 1408 1409 To run the first example for only scoring molecules already positioned in the 1410 binding pocket and write out a SD file, type: 1411 1412 % VinaPerformDocking.py -m ScoreOnly -g SampleACE2RefLigand.sdf 1413 -r SampleACE2Receptor.pdbqt -i SampleACE2RefLigandWithHs.sdf 1414 -o SampleACE2LigandsOut.sdf 1415 1416 To run the first example for docking molecules to increase the accuracy of 1417 pose predictions and write out a SD file, type: 1418 1419 % VinaPerformDocking.py -g SampleACE2RefLigand.pdb 1420 -r SampleACE2Receptor.pdbqt --exhaustiveness 24 1421 -i SampleACE2Ligands.sdf -o SampleACE2LigandsOut.sdf 1422 1423 To run the first example in multiprocessing mode on all available CPUs 1424 without loading all data into memory, a single thread for Vina docking, and 1425 write out a SD file, type: 1426 1427 % VinaPerformDocking.py -g SampleACE2RefLigand.pdb 1428 -r SampleACE2Receptor.pdbqt --mp yes 1429 -i SampleACE2Ligands.sdf -o SampleACE2LigandsOut.sdf 1430 1431 To run the first example in multiprocessing mode on all available CPUs 1432 by loading all data into memory, a single thread for Vina, and write out 1433 a SD file, type: 1434 1435 % VinaPerformDocking.py -g SampleACE2RefLigand.pdb 1436 -r SampleACE2Receptor.pdbqt --mp yes --mpParams "inputDataMode, 1437 InMemory" -i SampleACE2Ligands.sdf -o SampleACE2LigandsOut.sdf 1438 1439 To run the first example in multiprocessing mode on specific number of CPUs 1440 and chunk size without loading all data into memory along with a specific number 1441 of threads for Vina docking and write out a SD file, type: 1442 1443 % VinaPerformDocking.py -g SampleACE2RefLigand.pdb 1444 -r SampleACE2Receptor.pdbqt --mp yes --mpParams "inputDataMode,lazy, 1445 numProcesses,4,chunkSize,2" --numThreads 2 1446 -i SampleACE2Ligands.sdf -o SampleACE2LigandsOut.sdf 1447 1448 To run the first example for docking molecules employing a flexible portion 1449 of the receptor corresponding to ARG273 and write out a SD file, type: 1450 1451 % VinaPerformDocking.py -g SampleACE2RefLigand.pdb 1452 -r SampleACE2RigidReceptor.pdbqt 1453 --receptorFlexFile SampleACE2FlexReceptor.pdbqt 1454 -i SampleACE2Ligands.sdf -o SampleACE2LigandsOut.sdf 1455 1456 To run the first example for docking molecules using specified parameters and 1457 write out a SD file, type: 1458 1459 % VinaPerformDocking.py -g "41.399, 5.851, 28.082" 1460 --gridSize "25.0, 25.0, 25.0" --gridSpacing 0.375 --energyComponents 1461 yes --exhaustiveness 32 --forcefield Vina --mode dock --numPoses 2 1462 --numThreads 4 --randomSeed 42 --validateMolecules no 1463 --vinaVerbosity 0 -r SampleACE2Receptor.pdbqt 1464 -i SampleACE2Ligands.sdf -o SampleACE2LigandsOut.sdf 1465 1466 Author: 1467 Manish Sud(msud@san.rr.com) 1468 1469 Acknowledgments: 1470 Diogo Santos-Martins and Stefano Forli 1471 1472 See also: 1473 PyMOLConvertLigandFileFormat.py, PyMOLExtractSelection.py, 1474 PyMOLInfoMacromolecules.py, PyMOLVisualizeMacromolecules.py, 1475 RDKitConvertFileFormat.py, RDKitEnumerateTautomers.py, 1476 RDKitGenerateConformers.py, RDKitPerformMinimization.py, 1477 RDKitPerformConstrainedMinimization.py 1478 1479 Copyright: 1480 Copyright (C) 2024 Manish Sud. All rights reserved. 1481 1482 The functionality available in this script is implemented using AutoDockVina 1483 and Meeko, open source software packages for docking, and RDKit, an open 1484 source toolkit for cheminformatics developed by Greg Landrum. 1485 1486 This file is part of MayaChemTools. 1487 1488 MayaChemTools is free software; you can redistribute it and/or modify it under 1489 the terms of the GNU Lesser General Public License as published by the Free 1490 Software Foundation; either version 3 of the License, or (at your option) any 1491 later version. 1492 1493 """ 1494 1495 if __name__ == "__main__": 1496 main()