Molecular simulation / Docking

AutoDock Vina Docking Tutorial: From a PDB File to Publishable Results

This tutorial follows the current usage of Vina 1.2.7 and Meeko 0.8.0. It gives complete commands for receptor and ligand preparation, box setup, parameter choice, redocking validation, and analysis with PyMOL and interaction diagrams, and lists what breaks when you copy old tutorials and how to fix common errors.

Short answer

The current way to dock with AutoDock Vina is to generate receptor and ligand PDBQT files with Meeko (MGLTools is based on Python 2, and the official tutorial now uses Meeko), with ligands first protonated at pH 7.4 and embedded in 3D by molscrub. Center the box on the co-crystal ligand or a predicted pocket; sizes are in Å and usually no larger than 30×30×30 Å. Start exhaustiveness at 32 and repeat with at least 3 random seeds. Before docking new molecules, redock the co-crystal ligand into its own structure; the best pose should have a heavy-atom RMSD below 2 Å. The Vina score has a standard error of about 2.85 kcal/mol, and −7 kcal/mol corresponds to only about 7 µM by ΔG = RT ln Kd, so compare against a positive control under the same settings rather than treating the score alone as evidence of activity.

Version changes

Most tutorials still rely on the AutoDockTools GUI (MGLTools 1.5.7) and Vina 1.1.2. The table lists what goes wrong when you copy them on Vina 1.2.x.

StepOld tutorialCurrent practiceConsequence of the old approach
Receptor/ligand PDBQTADT GUI: add hydrogens, compute Gasteiger charges, export PDBQTMeeko: mk_prepare_receptor.py, mk_prepare_ligand.pyMGLTools was last patched in 2022 and is based on Python 2, which is hard to install on current systems; Meeko 0.8.0 requires Python ≥ 3.10
Ligand hydrogens and 3D"Add Hydrogens" in ADT, or direct Open Babel conversionmolscrub scrub.py: enumerates protonation states and tautomers at pH 7.4 by default, ETKDGv3 3D embeddingWrong protonation changes which atoms count as H-bond donors/acceptors; 2D input cannot be fixed during docking
Loggingvina --config conf.txt --log log.txtvina ... | tee dock.logVina 1.2.x removed --log: Command line parse error: unrecognised option '--log'
Box sizeRead 60×60×60 (grid points) from the ADT Grid BoxWrite Å directly: size_x = 22, etc.ADT shows grid points (0.375 Å spacing); copied into Vina this becomes a 60 Å cube and triggers the 27000 ų warning
ChargesEmphasis on Gasteiger charges for receptor and ligandThe Vina scoring function ignores partial charges; they matter only for AD4 scoringTime spent on charges does not change Vina results; protonation states do
Installationpip install vina, then type vinavina=1.2.7 from conda-forge, which ships the vina command and the Python bindingsThe pip package has only the Python bindings, so vina gives command not found; PyPI has prebuilt 1.2.7 wheels only for Linux x86_64, and on macOS pip fails with Boost library location was not found!
Viewing resultsOpen the output PDBQT directly in PyMOLConvert to SDF with mk_export.py firstRecent PyMOL versions get bond orders wrong from PDBQT; Open Babel cannot infer them correctly for some molecules
Vina versionVina 1.1.2Vina 1.2.7 (2025-02)1.1.2 cannot read the G0/CG0 pseudo-atoms Meeko writes for macrocycles: ATOM syntax incorrect

Installation

The Vina pip package contains only the Python bindings, not the vina command. PyPI has prebuilt vina 1.2.7 wheels only for Linux x86_64 (Python 3.8–3.12); on macOS pip falls back to a source build and fails with Boost library location was not found! when Boost is missing. The conda-forge vina 1.2.7 package provides the vina and vina_split commands and the Python bindings on Linux and macOS, and the environment below uses it. Windows users run it in WSL or download the win.exe build from GitHub Releases. Tested on this page: part 1 of the commands below installs from scratch with micromamba on macOS arm64 (Apple M2).

Open Babel and RDKit play supporting roles in the current workflow. RDKit reads and writes SDF, assigns bond orders to PDB ligands and computes RMSD. Open Babel handles format conversion and is a PLIP dependency; it is no longer used to write PDBQT files for docking.

Environment setupbash
# 1) Environment: take vina from conda-forge; the package ships the vina and vina_split commands and the Python bindings
#    (linux-64, linux-aarch64, osx-64, osx-arm64; Python 3.10-3.14)
micromamba create -n dock -c conda-forge python=3.11 rdkit gemmi prody pdbfixer openmm vina=1.2.7 -y
micromamba activate dock
# Meeko 0.8.0 and molscrub 0.3.0 are only on PyPI; molscrub 0.3.0 imports joblib without declaring it, so install it by hand
pip install meeko==0.8.0 molscrub==0.3.0 propka joblib
vina --version        # AutoDock Vina v1.2.7

# 2) Without conda: download the binary for your platform from GitHub Releases
#    File suffixes: linux_x86_64, linux_aarch64, mac_aarch64, mac_x86_64, win.exe
curl -fL -o vina https://github.com/ccsb-scripps/AutoDock-Vina/releases/download/v1.2.7/vina_1.2.7_linux_x86_64
chmod +x vina && ./vina --version
#    pip install vina installs only the Python bindings; PyPI has prebuilt 1.2.7 wheels only for Linux x86_64,
#    so on macOS pip builds from source and fails with Boost library location was not found!

# 3) Optional: pocket prediction and interaction analysis
#    P2Rank 2.5.1: download from https://github.com/rdk/p2rank/releases and unpack (needs Java); the command is prank
#    fpocket: micromamba install -c conda-forge -c bioconda fpocket
#    PLIP: install openbabel from conda-forge, then pip install plip

Receptor preparation

Meeko matches each residue against templates. Heavy atoms must match the template exactly; hydrogens are optional. Receptor preparation therefore centers on completing heavy atoms and fixing the states of titratable residues.

Chain selection and waters

When a PDB entry contains several identical chains, keep one (chain A for 1IEP). Crystal waters are usually all removed. If the literature shows a water mediating ligand binding across several structures, keep it, or use the hydrated docking protocol in the Vina docs (AD4 scoring).

Missing atoms and residues

Residues with missing side-chain atoms make Meeko fail with Template matching failed for: [...]. Fill them with PDBFixer --add-atoms=all. Problem residues far from the pocket can be removed with --delete_bad_res_from_box_radius, which deletes only those outside the box; in Meeko 0.8.0, -a/--allow_bad_res was renamed -x/--delete_bad_res. If a whole loop near the pocket is missing, complete it from a homologous structure or an AlphaFold model first and inspect its conformation.

Protonation at the target pH

PDBFixer --ph 7.4 adds hydrogens for the most common variant at that pH. Only neutral histidine is assigned HID or HIE based on hydrogen bonding; environmental pKa shifts are not computed. Check pocket His, Asp, Glu, Lys and Cys with propka3. For residues whose pKa is within 1 unit of the target pH (the minor state then exceeds about 9%), decide from the literature and set them with Meeko -n, e.g. -n A:5,7=CYX,B:17=HID (ASH is protonated Asp; names follow Amber).

Metal ions

Keep active-site metals (Zn, Mg, Fe, Ca, etc.); Meeko ships templates for them. Removing all ions at once with PyMOL remove inorganic is a common mistake that deletes catalytic zinc. For zinc proteins, use the AutoDock4Zn protocol in the Vina docs (AD4 scoring with zinc pseudo-atoms).

Cofactors

Keep NAD+, FAD, heme and similar cofactors when they occupy part of the pocket under physiological conditions. If Meeko has no template, prepare an SDF with the correct protonation state and pass it with --add_templates NAD:nad.sdf.

AlphaFold models

Trim flexible segments with pLDDT < 70 outside the pocket, then follow the steps above. AF2 models are ligand-free, and pocket side chains may block the pocket. A systematic study on GPCRs found that pose accuracy when docking to AF2 models is similar to traditional homology models and clearly lower than docking to experimental structures.

Ligand preparation

mk_prepare_ligand.py requires a 3D structure with all hydrogens; SDF is recommended. PDB format has no bond-order information, and the official docs advise against using it for small molecules.

Docking straight from SMILES or a 2D structure fails for two reasons. Vina only rotates rotatable bonds during docking, so rings keep their input conformation and a wrong chair/boat cannot be corrected. A flat 2D input is also one of the failure causes listed in the official FAQ. molscrub embeds 3D conformers with ETKDGv3, minimizes them with a force field and converts six-membered boats to chairs.

Vina uses a united-atom scoring function, so output hydrogen positions are meaningless. Input hydrogens still decide which atoms are H-bond donors or acceptors, so the protonation state directly changes the score. For imatinib, molscrub gives two states over pH 5–9, with a neutral or a protonated pyridine, and the piperazine amines protonated in both.

  • Structures downloaded from PubChem often include salts and counterions; scrub.py keeps only the largest fragment by default.
  • When the protonation state is uncertain, enumerate states with --ph_low and --ph_high, dock each, and report the best one with its state.
  • Resolve undefined stereocenters in the SMILES first. molscrub 0.3.0 has no stereoisomer enumeration option, and ETKDG assigns undefined stereocenters arbitrarily; when enumeration is needed, expand the SMILES with RDKit EnumerateStereoisomers first and pass the results to scrub.py.
  • Macrocycles: Meeko makes macrocycles flexible by default, and Vina computes the conformational entropy penalty from the number of BRANCH records, which can shift scores by about 2 kcal/mol. Use the same setting for all molecules you compare, and add --rigid_macrocycles when needed.
  • Ligands containing elements without Vina parameters or metals fail with Atom type ... is not a valid AutoDock type and need custom atom type parameters.

Grid box

A smaller box lets the search converge more easily; positions outside the box are never sampled. The Vina FAQ recommends a box "as small as possible, but not smaller" and suggests raising exhaustiveness when the box exceeds 30×30×30 Å.

Box too small: part of the ligand is pushed out, and Vina returns truncated poses or clearly worse scores. Box too large: at the same exhaustiveness the search is insufficient, and results vary strongly between seeds. Feinstein and Brylinski found on 3659 complexes that Vina poses were most accurate when the cube edge was 2.857 times the ligand radius of gyration; a generic box of "at least 22.5 Å per dimension" gave a mean RMSD of 4.9 Å versus 4.0 Å for the optimized box.

Blind docking (a box enclosing the whole protein) is common in network pharmacology papers. Che and Zhang reviewed 35 such papers from 2024 and found 17 using or likely using blind docking. In the CASF-2016 data they cite, Vina blind docking placed 34–47% of ligands within 2 Å RMSD, versus 90.2% when docking to the specified site.

Tested on this page (P2Rank 2.5.1, fpocket 4.2.3, input: chain A of 1IEP after PDBFixer as in the workflow below): the center of the top P2Rank pocket (probability 0.937) lies 3.0 Å from the crystal ligand center, the center of the top fpocket pocket lies 3.4 Å from it, and the pocket residues include Thr315 and Met318. --box_enveloping xtal_lig.sdf --padding 5 produced an 18.7×26.7×23.5 Å box; 2.857 × radius of gyration gives 19.1 Å for the crystal pose and 18.7 Å for the scrub.py conformer. P2Rank takes about 1 minute per structure on an 8-core machine; the column names in its CSV have leading spaces, so read it in pandas with skipinitialspace=True.

No co-crystal ligand: pocket prediction and boxbash
# Crystal structure
prank predict -f protA_H.pdb -o p2rank_out
# AlphaFold, NMR and cryo-EM models: the default model uses B-factors, which hold pLDDT in AlphaFold files
prank predict -c alphafold -f AF-model.pdb -o p2rank_out
# The first row is the top-ranked pocket; columns center_x/y/z give the box center
head -3 p2rank_out/protA_H.pdb_predictions.csv

# Cross-check: fpocket writes to protA_H_out/
fpocket -f protA_H.pdb

# Box from pocket center and ligand size (Feinstein & Brylinski 2015: edge = 2.857 x radius of gyration)
python - <<'EOF'
from rdkit import Chem
from rdkit.Chem import Descriptors3D
m = Chem.MolFromMolFile("lig_scrub.sdf")  # Hs removed by default: heavy atoms only
print("cube edge (A):", round(2.857 * Descriptors3D.RadiusOfGyration(m), 1))
EOF
mk_prepare_receptor.py --read_pdb protA_H.pdb -o rec -p -v \
    --box_center 12.3 45.6 7.8 --box_size 22 22 22
SituationCenterSizeNotes
Co-crystal ligand availableGeometric center of the co-crystal ligand heavy atomsLigand bounding box padded by 4–5 Å per side, or a cube with edge = 2.857 × ligand radius of gyrationMeeko --box_enveloping xtal_lig.sdf --padding 5 does this in one step
Homolog has a co-crystal ligandSuperimpose the homologous complex onto the target and use its ligand centerSame as aboveCheck that pocket residues correspond after superposition
No co-crystal; literature gives key residuesCenter of the key residues' Cα atoms20–25 Å cube (PoseBusters uses 25 Å)Confirm with P2Rank that these residues actually form a pocket
No co-crystal, no literatureCenter of the top P2Rank pocket, cross-checked with fpocketFrom the radius of gyration of the ligand to dockAgreement between both tools raises confidence; dock and report the top 2–3 pockets separately
AlphaFold / cryo-EM structuresP2Rank with -c alphafoldSame as aboveThe default model uses B-factors as a feature; in AlphaFold files the B-factor column holds pLDDT

Parameters

The same seed does not guarantee the same result as someone else: the random number generator comes from Boost, and builds against different Boost versions follow different trajectories. The maintainers suggest running about 10 times each and comparing the score distributions. In the data cited by Che and Zhang, raising exhaustiveness from 8 to 64 lowered the median RMSD from 3.37 Å to 2.21 Å at about 8 times the runtime.

Tested on this page (1IEP redocking, an 18.7×26.7×23.5 Å box from --box_enveloping with 5 Å padding; other conditions in the next section): exhaustiveness 8, 16, 32 and 64 with 3 seeds each (10 seeds for 8 and 32) all gave best-pose RMSDs of 0.77–0.85 Å and scores between −12.74 and −12.82 kcal/mol. The median CPU time (user) per run was 109, 281, 362 and 821 s, and the median wall time 70, 175, 94 and 280 s (heavily affected by machine load; use only as an order of magnitude). This box fits the crystal ligand tightly, and the default of 8 already reached 2 Å in 10 of 10 runs. The official docs note that the default 8 occasionally misses the correct pose, so large boxes or more flexible ligands should still start at 32. Repeated runs on the same machine with the same vina binary and the same seed give identical scores and poses.

ParameterMeaningDefaultRecommendation
exhaustivenessNumber of independent Monte Carlo runs; also caps the number of threads used. Runtime is roughly proportional to it8Start at 32 for single molecules (the official 1IEP example uses 32, and the docs note that the default 8 occasionally misses the correct pose); for virtual screening, pre-screen at the default 8 and re-dock top hits at 32
num_modesMaximum number of poses written9Usually keep 9. The terminal table lists up to 9 poses, but the output file only contains poses within energy_range of the best score, so it often holds fewer than 9
energy_rangeMaximum score difference from the best pose (kcal/mol)3Raise to 5 to see more alternative poses
min_rmsdMinimum RMSD between output poses1.0 ÅUsually unchanged
seedRandom seed0 (random each run)At least 3 seeds per molecule; report the seed values
cpuNumber of threads0 (detect all cores)When exhaustiveness is below the core count, extra cores sit idle
spacingGrid map spacing0.375 ÅLeave unchanged; it is not the unit of the box size
scoringScoring function: vina, vinardo, ad4vinaScores from different scoring functions are not comparable

Complete commands

Using the official Vina example system 1IEP (c-Abl kinase + imatinib), these commands go from the PDB file to a table of scores and RMSDs. The ligand starts from SMILES, so the test checks whether the whole preparation workflow reproduces the crystal pose. In the official example the best pose scores about −13 kcal/mol with the Vina scoring function.

Tested on this page (AutoDock Vina 1.2.7 (conda-forge), Meeko 0.8.0, molscrub 0.3.0, PDBFixer 1.12, RDKit 2025.09 and 2026.03; macOS arm64, Apple M2 with 8 cores and 16 GB; other jobs were running on the machine during the tests, with a system load of about 25–70): the four code blocks above run end to end. All chain A residues from the PDBFixer output matched Meeko templates; scrub.py gives a single state at pH 7.4 (both piperazine N protonated, net charge +2). mk_export.py writes one SDF record per pose, not one molecule with several conformers.

Redocking results: starting from SMILES with exhaustiveness 32 and seeds 1–10, the best pose scored −12.74 to −12.82 kcal/mol with an in-place RMSD of 0.80–0.85 Å to the crystal pose, below 2 Å in all 10 runs. The second-ranked pose is the end-to-end flipped binding mode (RMSD about 13 Å, about 1.4 kcal/mol worse). PLIP shows that the top pose reproduces the hydrogen bonds to the Met318 backbone and the Thr315 side chain. Scoring the crystal pose directly (--score_only) gives −12.51 kcal/mol, and local optimization in place (--local_only) gives −13.24 kcal/mol at an RMSD of 0.21 Å.

The starting conformer changes the score: rerunning the same script in an RDKit 2026.03 environment, scrub.py produced a different starting conformer and the best score of all 3 seeds was −12.41 to −12.42 kcal/mol, with RMSD 0.84–0.85 Å. Cross-docking confirmed that the difference comes from the ligand starting conformer, not from receptor hydrogens. Vina keeps bond lengths, angles and ring conformations fixed during docking, so fix the ligand preparation environment or keep the starting conformer files when comparing scores.

The Vina terminal table lists up to num_modes poses, but the output PDBQT only contains poses within energy_range of the best score: here the terminal listed 9 poses and the file held only 2–7 in each run. rmsd_table.py reads scores from the REMARK VINA RESULT lines in the PDBQT, which correspond one to one with the SDF records.

run_redock.shbash
set -euo pipefail
SMI='Cc1ccc(NC(=O)c2ccc(CN3CCN(C)CC3)cc2)cc1Nc1nccc(-c2cccnc2)n1'   # imatinib

# 1. Download 1IEP; keep chain A protein (no altloc or altloc A) and the chain A ligand STI
curl -fsSLO https://files.rcsb.org/download/1IEP.pdb
awk 'substr($0,1,4)=="ATOM" && substr($0,22,1)=="A" && (substr($0,17,1)==" " || substr($0,17,1)=="A")' 1IEP.pdb > protA.pdb
echo END >> protA.pdb
awk 'substr($0,1,6)=="HETATM" && substr($0,18,3)=="STI" && substr($0,22,1)=="A"' 1IEP.pdb > xtal_lig.pdb

# 2. Add missing heavy atoms, add hydrogens at pH 7.4, drop water and all heterogens
pdbfixer protA.pdb --output=protA_H.pdb --add-atoms=all --keep-heterogens=none --ph=7.4

# 3. Check pKa values of titratable residues in the pocket (written to protA_H.pka)
propka3 protA_H.pdb

# 4. Assign bond orders to the crystal ligand to get a reference SDF (used for the box and RMSD)
python make_ref.py "$SMI" xtal_lig.pdb xtal_lig.sdf

# 5. Receptor PDBQT + box: centered on the crystal ligand, padded by 5 A on each side
#    To change a protonation state add -n, e.g. -n A:<resnum>=HIP
mk_prepare_receptor.py --read_pdb protA_H.pdb -o rec -p -v \
    --box_enveloping xtal_lig.sdf --padding 5
#    Writes rec.pdbqt, rec.box.txt (Vina config) and rec.box.pdb (view the box in PyMOL)

# 6. Ligand: protonation state at pH 7.4 and 3D conformer from SMILES, then PDBQT
scrub.py "$SMI" -o lig_scrub.sdf --ph 7.4 --skip_tautomers
#    scrub.py writes unnamed molecules; without --multimol_prefix a single molecule becomes the hidden file lig_pdbqt/.pdbqt
mk_prepare_ligand.py -i lig_scrub.sdf --multimol_outdir lig_pdbqt --multimol_prefix lig

# 7. Redocking: 3 random seeds x exhaustiveness 32
mkdir -p out
for lig in lig_pdbqt/*.pdbqt; do
  name=$(basename "$lig" .pdbqt)
  for seed in 1 2 3; do
    vina --receptor rec.pdbqt --ligand "$lig" --config rec.box.txt \
      --exhaustiveness 32 --num_modes 9 --energy_range 3 --seed "$seed" \
      --out "out/${name}_s${seed}.pdbqt" | tee "out/${name}_s${seed}.log"
    mk_export.py "out/${name}_s${seed}.pdbqt" -s "out/${name}_s${seed}.sdf"
  done
done

# 8. Score and RMSD to the crystal pose for every pose
python rmsd_table.py xtal_lig.sdf out > redock_rmsd.tsv
sort -t$'\t' -k3,3g redock_rmsd.tsv | head
make_ref.pypython
# make_ref.py: assign bond orders to the PDB ligand from a SMILES template
import sys
from rdkit import Chem
from rdkit.Chem import AllChem

smi, pdb_in, sdf_out = sys.argv[1:4]
template = Chem.MolFromSmiles(smi)
lig = Chem.MolFromPDBFile(pdb_in, removeHs=True)
ref = AllChem.AssignBondOrdersFromTemplate(template, lig)
Chem.MolToMolFile(ref, sdf_out)
print("heavy atoms:", ref.GetNumHeavyAtoms())
rmsd_table.pypython
# rmsd_table.py: in-place (no superposition), symmetry-aware heavy-atom RMSD
import glob, os, sys
from rdkit import Chem
from rdkit.Chem import rdMolAlign

def heavy_neutral(m):
    # Remove H and formal charges so different protonation states still match
    m = Chem.RemoveHs(m)
    for a in m.GetAtoms():
        if a.GetFormalCharge() != 0:
            # A protonated N keeps one explicit H after RemoveHs; clearing only the charge raises a valence error
            a.SetFormalCharge(0)
            a.SetNumExplicitHs(0)
            a.SetNoImplicit(False)
    Chem.SanitizeMol(m)
    return m

ref = heavy_neutral(Chem.MolFromMolFile(sys.argv[1]))
print("file\tpose\tvina_score\trmsd_to_xtal")
for sdf in sorted(glob.glob(os.path.join(sys.argv[2], "*.sdf"))):
    pdbqt = sdf[:-4] + ".pdbqt"
    scores = [float(l.split()[3]) for l in open(pdbqt) if l.startswith("REMARK VINA RESULT")]
    poses = []
    for m in Chem.SDMolSupplier(sdf, removeHs=False):
        if m is None:
            continue
        for conf in m.GetConformers():
            p = Chem.Mol(m, confId=conf.GetId())
            poses.append(p)
    for i, p in enumerate(poses):
        rmsd = rdMolAlign.CalcRMS(heavy_neutral(p), ref)
        print(f"{os.path.basename(sdf)}\t{i+1}\t{scores[i]:.2f}\t{rmsd:.2f}")
batch_dock.py (Python API for many ligands)python
# Batch docking: compute maps once and reuse them for every ligand
from vina import Vina
import glob, os

v = Vina(sf_name="vina", cpu=0, seed=42)
v.set_receptor("rec.pdbqt")
os.makedirs("out_batch", exist_ok=True)
# Without a ligand loaded, compute_vina_maps builds maps for every atom type in the force field, so they are reused across ligands
v.compute_vina_maps(center=[15.19, 53.90, 16.92], box_size=[22, 22, 22])  # replace with the values in rec.box.txt

for lig in sorted(glob.glob("lib_pdbqt/*.pdbqt")):
    v.set_ligand_from_file(lig)
    v.dock(exhaustiveness=16, n_poses=20)
    v.write_poses(os.path.join("out_batch", os.path.basename(lig)), n_poses=9, energy_range=3.0, overwrite=True)
    print(lig, v.energies(n_poses=1)[0][0])

Validation

The −4.25, −5.0 and −7.0 kcal/mol thresholds common in network pharmacology papers have no single source, and scores from different docking programs cannot share a threshold. When comparing molecules of different size, also report ligand efficiency LE = −score / heavy-atom count; 0.3 kcal/mol per heavy atom is a common reference, and Vina scores become more negative as molecules grow.

  1. 01

    Redocking RMSD < 2 Å

    Dock the co-crystal ligand back into its own structure. The symmetry-aware heavy-atom RMSD between the best pose and the crystal pose should be below 2 Å. This threshold appears in the original Vina paper (Trott & Olson 2010) and in the PoseBusters benchmark, where Vina met it for 58% of the 85 Astex Diverse systems. Compute RMSD in place in the receptor frame: RDKit CalcRMS does not superimpose, while GetBestRMS first aligns the ligand onto the reference and underestimates the value.

  2. 02

    If redocking fails, check in this order

    Box units and position; ligand and receptor protonation states; higher exhaustiveness or other seeds; ligand ring conformations; receptor structure quality. If the crystal pose is not a minimum of the scoring function (compare vina --score_only and --local_only; both modes require the ligand coordinates to be inside the box, so prepare a PDBQT from the crystal ligand with hydrogens), a larger search will not help; change the scoring function or the method. Tested on 1IEP on this page: the crystal pose scores −12.51 with --score_only and −13.24 kcal/mol after --local_only, and the best docked pose scores −12.8 kcal/mol, with all three within 1 Å RMSD.

  3. 03

    Positive control

    Dock a known active (ideally with an experimental Kd or IC50) with the same receptor, box and parameters, and compare new molecules against its score. In the network pharmacology papers reviewed by Che and Zhang, none used a positive control.

  4. 04

    Agreement across seeds

    When the top poses from 3 seeds lie within 2 Å RMSD of each other, the search has converged. If changing only the seed changes the score a lot, shrink the box or raise exhaustiveness first.

Vina score (kcal/mol)Converted by ΔG = RT ln Kd (298 K)Interpretation
−5about 216 µMThe most common "binds" threshold in network pharmacology papers; converted, it is very weak binding
−6about 40 µM
−7about 7.4 µM
−8about 1.4 µM
−9about 0.25 µMThe Vina standard error on its benchmark set is 2.85 kcal/mol, about 2 orders of magnitude in Kd
The conversion only conveys orders of magnitude; the Vina score is not an experimental estimate of binding free energy.

Result analysis

PyMOL figure and complex exporttext
# Run in the PyMOL command line
load protA_H.pdb, rec
load out/lig-1_s1.sdf, poses
load xtal_lig.sdf, xtal
split_states poses, prefix=pose
delete poses
hide everything
show cartoon, rec
set cartoon_transparency, 0.5
select pocket, byres (rec within 4 of pose0001)
show sticks, pocket and not name N+C+O
show sticks, pose0001 or xtal
color grey70, xtal and elem C
color green, pose0001 and elem C
distance hb, pose0001, pocket, mode=2
label pocket and name CA, "%s%s" % (resn, resi)
orient pose0001
set ray_opaque_background, 0
png pose1.png, width=2400, height=1800, dpi=300, ray=1

# Export the complex for PLIP / LigPlot+: mark the ligand as HETATM with one residue name
alter pose0001, resn="LIG"
alter pose0001, chain="L"
alter pose0001, resi="900"
alter pose0001, type="HETATM"
save complex_pose1.pdb, rec or pose0001
PLIP interaction analysisbash
# Interaction tables (txt + xml) and a PyMOL session; -p also renders images
plip -f complex_pose1.pdb -t -x -y -o plip_pose1
  1. 01

    Read the output table

    affinity is the Vina score (kcal/mol). rmsd l.b. and rmsd u.b. are distances from the top pose of the same run and have nothing to do with the crystal structure; u.b. matches atoms one-to-one without symmetry, l.b. matches each atom to the nearest atom of the same element. The idea that "a smaller docking RMSD is better" confuses these two kinds of RMSD.

  2. 02

    Choose a pose

    Do not just take rank 1. Check whether rank 1 recurs across seeds. When the top scores differ by much less than the Vina scoring error (2.85 kcal/mol), prefer the pose that reproduces known key interactions (in 1IEP, imatinib hydrogen-bonds to the hinge Met318 backbone and the gatekeeper Thr315). Discard poses that are mostly solvent-exposed or pressed against the box edge.

  3. 03

    Export SDF

    mk_export.py restores bond orders, formal charges and all hydrogens from the SMILES stored in the PDBQT header. The SDF can go directly to PyMOL, PLIP, RDKit and downstream molecular dynamics.

  4. 04

    3D figure

    Use the PyMOL commands below to draw the pocket, hydrogen bonds and an overlay with the crystal pose. If Vina 1.2.x output displays incompletely in PyMOL, the file usually contains NUL characters; view the SDF instead.

  5. 05

    2D interaction diagrams

    PLIP reports residues and distances for hydrogen bonds, hydrophobic contacts, π stacking, salt bridges and halogen bonds. LigPlot+ and PoseView (proteins.plus) draw 2D diagrams, and Discovery Studio Visualizer can as well. All of them expect the receptor and ligand in one PDB file with the ligand as HETATM.

Writing the paper

Reviewers need the following to reproduce a docking study. A missing box center and size is the most common gap in network pharmacology papers.

  • Software and versions: AutoDock Vina 1.2.7, Meeko 0.8.0, molscrub 0.3.0, PDBFixer, etc.
  • Receptor: PDB ID, chain, resolution; which waters, ions and ligands were removed, which metals and cofactors were kept; which residues were rebuilt.
  • Protonation: target pH, tools used (PDBFixer, PROPKA), residue states set manually.
  • Ligands: source (e.g. PubChem CID), protonation and 3D generation method, number of states enumerated.
  • Box: center coordinates and dimensions (Å), and the basis for the center (co-crystal ligand, literature residues, P2Rank).
  • Parameters: scoring function, exhaustiveness, num_modes, energy_range, random seeds and number of repeats.
  • Validation: redocking RMSD of the co-crystal ligand; positive control molecule and its score.
  • Results: best score per molecule across seeds (mean ± SD), the basis for pose selection, interacting residue table and 3D figures.

Troubleshooting

Error messageCauseFix
Command line parse error: unrecognised option '--log'Vina 1.2.x removed --logvina ... | tee dock.log or > dock.log
WARNING: Search space volume is greater than 27000 Angstrom^3 (See FAQ)Box size entered in AutoDock4 grid points, or an oversized blind-docking boxMultiply grid points by 0.375 to get Å; raise exhaustiveness if a large box is really needed
Vina runtime error: The ligand is outside the grid box. Increase the size of the grid box or center it accordingly around the ligand.--score_only and --local_only do no global search and require the input ligand to be inside the box; coordinates generated by scrub.py from SMILES sit near the originAdd hydrogens to the crystal ligand, prepare a PDBQT with mk_prepare_ligand.py and score that; normal docking is unaffected
ATOM syntax incorrect: "CG0" is not a valid AutoDock typeVina 1.1.2 reading the macrocycle pseudo-atoms written by MeekoUpgrade to Vina 1.2.x
Atom type 9.00 -17.40 is not a valid AutoDock type (atom types are case-sensitive)MGLTools prepare_ligand.py / prepare_receptor.py (without the 4) write the legacy PDBQ / PDBQS formatsUse Meeko, or prepare_ligand4.py / prepare_receptor4.py
Atom type Xx is not a valid AutoDock typeThe ligand or receptor contains an element without Vina parameters, or the element symbol has the wrong case (e.g. CL)Check the element column; metal complexes need custom atom types
PDBQT parsing error: Unknown or inappropriate tag found in rigid receptor.The receptor PDBQT contains ROOT/BRANCH records, typically from converting the receptor with Open Babel without -xrRegenerate the receptor with mk_prepare_receptor.py
PDBQT parsing error: Unexpected multi-MODEL tag found in flex residue or ligand PDBQT file. Use "vina_split" to split flex residues or ligands in multiple PDBQT files.A multi-MODEL docking output was used as ligand inputSplit it with vina_split, or export with mk_export.py and take a single pose
Template matching failed for: ['A:238', ...]Meeko receptor template matching failed: missing heavy atoms, non-standard residues or unknown ligandsAdd atoms with PDBFixer; use --add_templates for non-standard residues; remove residues outside the box with --delete_bad_res_from_box_radius
Affinity map for atom type A is not presentWith AD4 scoring, the GPF did not generate a map for that atom typeRegenerate the GPF with mk_prepare_receptor.py -g, or add the type to the ligand_types line
Error: could not open "conf.txt" for reading.The file is really conf.txt.txt, or it is not in the current directoryShow file extensions and rename it, or use an absolute path
boost thread resource errorThe cluster node is configured to restrict thread creationAsk the administrator to adjust the thread limit
Residues with alternate location: ['A:709']The receptor PDB contains residues with alternate locations (altloc)Add --default_altloc A to mk_prepare_receptor.py, or --wanted_altloc A:709=A for that residue only; pick the higher-occupancy conformer
RDKit molecule has implicit Hs. Need explicit Hs.Wrong formal charges or bond orders in the ligand SDF, for example a deprotonated O still at charge 0, so RDKit infers hydrogens with no coordinatesFix formal charges and bond orders in an editor such as Avogadro, export SDF, and check the M CHG lines at the end of the file
Element K doesn't have an implemented covalent radiusThe receptor contains an element Meeko does not support, such as K⁺Delete the ion if it is far from the pocket
The following error messages were reproduced on this page with Vina 1.2.7 and Meeko 0.8.0: --log, the 27000 ų warning (60×60×60 box), ligand is outside the grid box, the rigid receptor tag, multi-MODEL, Template matching failed (NZ atom of Lys271 deleted) and could not open. The other rows come from the listed issues and source code and were not reproduced locally. The last three rows come from a Keinsci forum post; the error strings were checked against the Meeko source.

Tools common in China

These lessons come from the Keinsci computational chemistry forum, Sobereva's blog and Chinese Q&A sites, and were checked against tool documentation or the original papers.

CB-Dock2 removes metals and cofactors

The CB-Dock2 paper states that the server adds missing side-chain atoms and hydrogens and removes all crystal waters and HETATM records, which includes active-site metal ions and cofactors. Pockets containing zinc, magnesium, NAD and similar groups should be docked with a local workflow. Ligand 3D conformers are generated with RDKit.

CB-Dock2's high success rate mostly comes from templates

CB-Dock2 first searches BioLiP for co-crystal structures with similar ligands (FP2 similarity ≥ 0.4) and docks by template; only when none is found does it fall back to cavity detection plus Vina docking. On the Astex set, 82 of 85 cases used template docking, with an 85.9% top-pose success rate; the original cavity-only CB-Dock reaches about 70%. Molecules without similar ligands in the PDB (most single compounds from traditional Chinese medicine) can only take the second route. Vina scores shown on the web page come from a different receptor preparation and program version than local Vina 1.2.x runs, so do not put them in the same table.

Protonating metalloproteins and AutoDock4Zn

A Keinsci forum user reproduced the official Vina AutoDock4Zn example and obtained −12.94 kcal/mol for the best pose, matching the official value of about −13 kcal/mol. His lessons: add hydrogens to metalloproteins in ChimeraX with addh hbond true metalDist 3.95, which leaves O and N atoms within 3.95 Å of a metal unprotonated so coordinating residues are not wrongly protonated; keep ADFRsuite out of the conda environment and call its pythonsh and autogrid4 by full path, so they are not mixed up with the autogrid4 in conda.

Protoss for protonation states

Sobereva recommends Protoss on proteins.plus for assigning protein and ligand protonation states, with particular attention to histidine: its pKa is close to 7, and when it may hydrogen-bond with the ligand, the state that favours the hydrogen bond should be chosen. On the same site, PoseView draws 2D interaction diagrams, and DoGSiteScorer finds pockets and reports a Drug Score that helps set the docking region.

The ligand leaves when MD starts from a docked pose

Sobereva's assessment: the top-scoring docked pose is clearly less reliable than a high-resolution crystal structure, and least reliable when the protein itself is predicted. If the ligand leaves soon after MD starts, the top-scoring pose is probably wrong; try a pose that looks reasonable but did not score first, or a different docking program. Another option is to add weak distance restraints on key hydrogen bonds during an initial equilibration, then remove them after the pocket relaxes and run the production simulation; keeping the restraints in production invites criticism from reviewers.

Discovery Studio will not draw the 2D diagram

The error Invalid selection for 2D ligand. ... The maximum number of atoms in the ligand is specified in the preferences means the ligand exceeds the default atom limit. Raise the maximum number of atoms under Edit > Preferences > Ligand Definition. A Tieba user reported that peptide ligands longer than about 7 residues are not recognised, for the same reason (community post).

Hand off to an agent

Example instruction: "Use AutoDock Vina to dock these 5 compounds (SMILES attached) into the ATP pocket of PDB 1IEP. First validate by redocking the co-crystal imatinib, then use imatinib as the positive control, with 3 random seeds per molecule. Deliver a score table, an RMSD table, PyMOL figures and PLIP interaction tables."

The agent installs Vina 1.2.7, Meeko and molscrub in the workspace (RDKit, OpenMM and AmberTools are preinstalled), prepares the receptor and ligands as described here, redocks and checks the RMSD, runs the batch docking, exports SDF files, renders figures and compiles the interaction tables. Deliverables include scripts such as run_redock.sh, rec.pdbqt and rec.box.txt, docking outputs and logs for each seed, redock_rmsd.tsv, a score summary, PNG figures and PLIP reports. The agent reviews the results adversarially, for example checking that redocking really falls within 2 Å and that seeds agree.

You still need to check whether pocket residue protonation states match the experimental conditions, whether the box matches the binding site reported in the literature, whether the key interactions of the chosen pose have experimental support, and whether the positive control is appropriate. For molecular dynamics follow-up, the preinstalled GROMACS can run in the same workspace.

References

FAQ

What docking score (affinity) counts as good?

There is no universal threshold. Converted by ΔG = RT ln Kd, −5 kcal/mol is about 216 µM, −7 about 7 µM and −9 about 0.25 µM, and the Vina score has a standard error of about 2.85 kcal/mol. The reliable approach is to compare against a known active positive control under the same receptor, box and parameters, and to report the mean over several seeds.

Is a smaller docking RMSD always better?

First identify which RMSD it is. rmsd l.b./u.b. in the Vina output table is the distance from the top pose of the same run; it shows whether poses cluster, not accuracy. Accuracy is measured by the heavy-atom RMSD between the redocked pose and the crystal pose, with < 2 Å counted as success.

What does exhaustiveness mean and what value should I use?

exhaustiveness is the number of independent Monte Carlo runs in Vina. The default is 8, runtime is roughly proportional to it, and it also sets how many CPU threads can be used. Start at 32 for single molecules with at least 3 random seeds; for virtual screening, pre-screen at the default 8 and re-dock top hits at 32.

Can I dock into an AlphaFold-predicted structure?

Yes, but accuracy is lower than with experimental structures. Trim low-pLDDT segments, find the pocket with P2Rank in -c alphafold mode, and test by docking a known ligand. A study on GPCRs found that pose accuracy with AF2 models is similar to traditional homology models and clearly lower than with experimental structures.

How does molecular docking differ from molecular dynamics?

Docking searches ligand poses in a rigid receptor and scores them within minutes, giving a static pose. Molecular dynamics simulates a solvated, flexible system for tens to hundreds of nanoseconds to test whether the docked pose is stable and key interactions persist. The usual workflow is to dock first and then run MD on the chosen pose; see the GROMACS protein-ligand tutorial.

How should docking be done in a network pharmacology paper to hold up?

Dock to a specified binding site instead of blind docking, report the box center and size, redock the co-crystal ligand and report the RMSD, include a positive control, use several random seeds, phrase conclusions as "predicted to bind", and follow up with molecular dynamics or experiments.

Hand docking and follow-up validation to Scientify

Describe the receptor, ligands and question. The scientific agent installs Vina and Meeko in an isolated cloud computer, runs redocking validation, multi-seed docking, figures and interaction analysis, then continues with molecular dynamics in the preinstalled GROMACS. Scripts, parameters and logs stay in the workspace for reproduction. New users get $5 of free credit.