A FastAPI-based web application for structure-based molecular docking using GNINA, with real-time progress tracking, optional post-processing analyses, and PyMOL session generation.
- Flexible ligand input: SMILES strings or SDF files (2D or 3D)
- Automatic 2D→3D conversion: OpenBabel-based 3D coordinate generation and protonation at target pH
- Dual-GPU docking: Load-balanced across two GPUs via
CUDA_VISIBLE_DEVICES - Real-time progress: WebSocket-based live updates during docking
- Optional post-processing (per pose, written as SDF fields):
MCS_RMSD— MCS-aligned RMSD vs reference ligand (RDKit, heavy atoms only)Shape_Sim— 3D shape Tanimoto similarity vs reference ligand (RDKit)Ref_Sim— 2D Morgan ECFP4 Tanimoto similarity vs reference ligand (RDKit)PLIF_Sim— Protein-Ligand Interaction Fingerprint Tanimoto similarity vs reference ligand (ODDT)PB_Flags— PoseBusters failure count (config='mol')
- Protein preparation: Optional integrated pipeline — fetch by PDB ID or upload, select chains and reference ligand, auto-populates docking inputs. Pipeline: PDBFixer repair → PDBFixer protonation → ASN/GLN/HIS rotamer optimisation → two-stage OpenMM minimization (stage 1: H positions optimised to convergence with all heavy atoms restrained; stage 2: sidechain relaxation with backbone-only restraints)
- PyMOL session: Headless PyMOL generates a
.psefile with protein rainbow cartoon, binding site surface, reference ligand (green sticks), and docked poses - Named sessions: User-defined session name propagated to output SDF, PSE, and ZIP filenames
- DataWarrior-compatible SDF output: Correct protonation states (COO⁻, NH₃⁺), proper block formatting, DockingRank field
- GNINA ≥ 1.3
- OpenBabel ≥ 3.1 (with tetrazole phmodel fix — see below)
- PyMOL (open-source or commercial, headless-capable)
Main app (gnina_webapp env):
conda create -n gnina_webapp python=3.10
conda activate gnina_webapp
conda install -c conda-forge rdkit openbabel
pip install -r requirements.txt
pip install posebusters # optional, for PB_FlagsProtein preparation (openmmdl env — only needed for the Protein Preparation feature):
conda create -n openmmdl python=3.10
conda activate openmmdl
conda install -c conda-forge biopython pdbfixer openmmThe protein preparation pipeline (protprep.py) is called as a subprocess using the openmmdl Python interpreter. Set the OPENMMDL_PYTHON environment variable if it is installed at a non-default path:
export OPENMMDL_PYTHON=/path/to/envs/openmmdl/bin/pythonconda activate gnina_webapp
python gnina_webapp.pyThen open http://localhost:9000 in your browser.
To keep the app running across sessions and restart it automatically on reboot, use a systemd service. Create /etc/systemd/system/gnina-webapp.service:
[Unit]
Description=GNINA Docking Web App
After=network.target
[Service]
Type=simple
User=YOUR_USERNAME
WorkingDirectory=/path/to/gnina/webapp
ExecStart=/path/to/conda/envs/gnina_webapp/bin/python gnina_webapp.py
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.targetThen enable and start it:
sudo systemctl daemon-reload
sudo systemctl enable gnina-webapp
sudo systemctl start gnina-webapp
sudo systemctl status gnina-webapp # check it's runningLogs are accessible via:
journalctl -u gnina-webapp -f| Field | Description |
|---|---|
| Protein Preparation | Optional: upload or fetch PDB, select chains/reference ligand, runs PDBFixer + OpenMM minimization, auto-fills receptor and reference inputs |
| Receptor (PDB) | Protein structure for docking |
| Reference ligand (SDF) | Defines the binding site (autobox); used as reference for post-processing metrics |
| Ligands (SDF or SMILES) | Molecules to dock |
| Session name | Prefix for output filenames |
| LigPrep pH | Target pH for OpenBabel protonation |
| Poses per ligand | Number of docked poses to generate |
| Exhaustiveness | GNINA search exhaustiveness (1–64) |
| CNN scoring | GNINA CNN scoring mode |
A ZIP file containing:
{session_name}.sdf— all docked poses with scoring and optional post-processing fields, ready for DataWarrior{session_name}.pse— PyMOL session (if requested)
| Field | Description |
|---|---|
minimizedAffinity |
Vina-style binding affinity (kcal/mol) |
CNNscore |
GNINA CNN pose quality score |
CNNaffinity |
GNINA CNN predicted affinity |
CNN_VS |
GNINA CNN virtual screening score |
DockingRank |
Pose rank within each ligand |
MCS_RMSD |
MCS-aligned RMSD to reference (Å) |
Shape_Sim |
3D shape Tanimoto similarity to reference (0–1) |
Ref_Sim |
2D ECFP4 Tanimoto similarity to reference (0–1) |
PLIF_Sim |
Protein-Ligand Interaction Fingerprint Tanimoto similarity to reference (0–1) |
PB_Flags |
Number of failed PoseBusters checks |
Key settings near the top of gnina_webapp.py:
GNINA_PATH = "/opt/gnina/gnina.1.3.2"
PYMOL_PATH = "/path/to/pymol"
DOCK_GPU_ID = 1 # CUDA device index for docking
N_GPU = 1 # Number of GPUs to useOpenBabel ≥ 3.1 can double-protonate tetrazoles. Apply this fix to
/usr/local/share/openbabel/3.1.1/phmodel.txt (adjust path for your install):
TRANSFORM c1[nH:1]nnn1 >> c1[n-:1]nnn1 4.89
TRANSFORM c1n[nH:1]nn1 >> c1n[n-:1]nn1 4.89
The --device flag is ignored in GNINA 1.3.2. GPU selection is done via
CUDA_VISIBLE_DEVICES on the subprocess instead.