Metadata-Version: 2.4
Name: OCDocker
Version: 0.15.3
Summary: OCDocker is a Python package for molecular docking automation, virtual screening and AI consensus scoring.
Author-email: Artur Duque Rossi <arturossi10@gmail.com>
License-Expression: BSD-3-Clause
Project-URL: Homepage, https://github.com/Arturossi/OCDocker
Project-URL: Repository, https://github.com/Arturossi/OCDocker
Project-URL: Issues, https://github.com/Arturossi/OCDocker/issues
Keywords: docking,virtual screening,AI,bioinformatics,drug discovery
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: POSIX :: Linux
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: configargparse>=1.7
Requires-Dist: joblib>=1.4.2
Requires-Dist: packaging>=25.0
Requires-Dist: pydantic>=2.11.4
Requires-Dist: pydantic-settings>=2.9.1
Requires-Dist: pyyaml>=6.0.2
Requires-Dist: requests>=2.32.3
Requires-Dist: rich>=13.9.1
Requires-Dist: tqdm>=4.66.5
Provides-Extra: analysis
Requires-Dist: colorcet>=3.2.1; extra == "analysis"
Requires-Dist: dcor>=0.6; extra == "analysis"
Requires-Dist: fsspec>=2024.10.0; extra == "analysis"
Requires-Dist: gmpy2>=2.1.5; extra == "analysis"
Requires-Dist: graphviz>=0.20.3; extra == "analysis"
Requires-Dist: h5py>=3.11.0; extra == "analysis"
Requires-Dist: imageio>=2.35.1; extra == "analysis"
Requires-Dist: ipython>=8.28.0; extra == "analysis"
Requires-Dist: lime>=0.2.0.1; extra == "analysis"
Requires-Dist: llvmlite>=0.43.0; extra == "analysis"
Requires-Dist: matplotlib>=3.9.2; extra == "analysis"
Requires-Dist: mpmath>=1.3.0; extra == "analysis"
Requires-Dist: networkx>=3.3; extra == "analysis"
Requires-Dist: numba>=0.60.0; extra == "analysis"
Requires-Dist: numpy>=1.26.4; extra == "analysis"
Requires-Dist: pandas>=2.2.3; extra == "analysis"
Requires-Dist: pillow>=10.4.0; extra == "analysis"
Requires-Dist: pingouin>=0.5.5; extra == "analysis"
Requires-Dist: rustworkx>=0.15.1; extra == "analysis"
Requires-Dist: scikit-image>=0.24.0; extra == "analysis"
Requires-Dist: scipy>=1.14.1; extra == "analysis"
Requires-Dist: seaborn>=0.13.2; extra == "analysis"
Requires-Dist: shap>=0.44.0; extra == "analysis"
Requires-Dist: statsmodels>=0.14.3; extra == "analysis"
Requires-Dist: sympy>=1.13.3; extra == "analysis"
Requires-Dist: tifffile>=2024.9.20; extra == "analysis"
Provides-Extra: api
Requires-Dist: fastapi>=0.115.0; extra == "api"
Requires-Dist: starlette>=1.3.1; extra == "api"
Requires-Dist: uvicorn>=0.32.0; extra == "api"
Provides-Extra: build
Requires-Dist: build>=1.2.2.post1; extra == "build"
Requires-Dist: setuptools>=80.8.0; extra == "build"
Requires-Dist: twine>=6.1.0; extra == "build"
Requires-Dist: wheel>=0.47.0; extra == "build"
Provides-Extra: cloud
Requires-Dist: boto3>=1.35.31; extra == "cloud"
Requires-Dist: dropbox>=12.0.2; extra == "cloud"
Requires-Dist: google-cloud-storage>=2.18.2; extra == "cloud"
Provides-Extra: db
Requires-Dist: psycopg>=3.2.0; extra == "db"
Requires-Dist: pymysql>=1.1.1; extra == "db"
Requires-Dist: sqlalchemy>=2.0.35; extra == "db"
Requires-Dist: sqlalchemy-utils>=0.41.2; extra == "db"
Provides-Extra: dev
Requires-Dist: coverage>=7.8.1; extra == "dev"
Requires-Dist: detect-secrets>=1.5.0; extra == "dev"
Requires-Dist: mypy>=1.0.0; extra == "dev"
Requires-Dist: pre-commit>=4.0.1; extra == "dev"
Requires-Dist: py-mini-racer>=0.6.0; extra == "dev"
Requires-Dist: pytest>=8.3.3; extra == "dev"
Requires-Dist: pytest-cov>=6.1.1; extra == "dev"
Requires-Dist: pytest-order>=1.3.0; extra == "dev"
Requires-Dist: ruff>=0.8.0; extra == "dev"
Provides-Extra: docking
Requires-Dist: biopython>=1.84; extra == "docking"
Requires-Dist: numpy>=1.26.4; extra == "docking"
Requires-Dist: openbabel-wheel>=3.1.0; extra == "docking"
Requires-Dist: pandas>=2.2.3; extra == "docking"
Requires-Dist: pdb2pqr>=3.7.1; extra == "docking"
Requires-Dist: rdkit!=2026.3.3,>=2024.09.1; extra == "docking"
Requires-Dist: scikit-learn>=1.5.2; extra == "docking"
Requires-Dist: scipy>=1.14.1; extra == "docking"
Requires-Dist: six>=1.17.0; extra == "docking"
Requires-Dist: spyrmsd>=0.8.0; extra == "docking"
Provides-Extra: docs
Requires-Dist: furo; extra == "docs"
Requires-Dist: myst-parser>=4.0.1; extra == "docs"
Requires-Dist: sphinx>=8.2.3; extra == "docs"
Requires-Dist: sphinx-argparse>=0.5.2; extra == "docs"
Requires-Dist: sphinx-rtd-theme>=3.0.2; extra == "docs"
Provides-Extra: gpu
Requires-Dist: cupy-cuda11x>=13.0.0; sys_platform != "darwin" and extra == "gpu"
Provides-Extra: mcp
Requires-Dist: httpx>=0.28.1; extra == "mcp"
Requires-Dist: mcp<2.0.0,>=1.28.0; extra == "mcp"
Provides-Extra: ml
Requires-Dist: lightgbm>=4.6.0; extra == "ml"
Requires-Dist: numpy>=1.26.4; extra == "ml"
Requires-Dist: optuna>=3.6.1; extra == "ml"
Requires-Dist: optuna-dashboard>=0.16.2; extra == "ml"
Requires-Dist: optuna-integration>=4.0.0; extra == "ml"
Requires-Dist: pandas>=2.2.3; extra == "ml"
Requires-Dist: scikit-learn>=1.5.2; extra == "ml"
Requires-Dist: scipy>=1.14.1; extra == "ml"
Requires-Dist: torch>=2.4.1; extra == "ml"
Requires-Dist: torchaudio>=2.4.1; extra == "ml"
Requires-Dist: torchsummary; extra == "ml"
Requires-Dist: torchviz; extra == "ml"
Requires-Dist: torchvision>=0.19.1; extra == "ml"
Requires-Dist: visualtorch>=0.2.3; extra == "ml"
Requires-Dist: xgboost>=2.1.1; extra == "ml"
Provides-Extra: workflow
Requires-Dist: snakemake>=7.32.4; extra == "workflow"
Requires-Dist: snakemake-logger-plugin-snkmt>=0.1.6; extra == "workflow"
Provides-Extra: all
Requires-Dist: biopython>=1.84; extra == "all"
Requires-Dist: boto3>=1.35.31; extra == "all"
Requires-Dist: colorcet>=3.2.1; extra == "all"
Requires-Dist: cupy-cuda11x>=13.0.0; sys_platform != "darwin" and extra == "all"
Requires-Dist: dcor>=0.6; extra == "all"
Requires-Dist: dropbox>=12.0.2; extra == "all"
Requires-Dist: fastapi>=0.115.0; extra == "all"
Requires-Dist: fsspec>=2024.10.0; extra == "all"
Requires-Dist: gmpy2>=2.1.5; extra == "all"
Requires-Dist: google-cloud-storage>=2.18.2; extra == "all"
Requires-Dist: graphviz>=0.20.3; extra == "all"
Requires-Dist: h5py>=3.11.0; extra == "all"
Requires-Dist: httpx>=0.28.1; extra == "all"
Requires-Dist: imageio>=2.35.1; extra == "all"
Requires-Dist: ipython>=8.28.0; extra == "all"
Requires-Dist: lightgbm>=4.6.0; extra == "all"
Requires-Dist: lime>=0.2.0.1; extra == "all"
Requires-Dist: llvmlite>=0.43.0; extra == "all"
Requires-Dist: matplotlib>=3.9.2; extra == "all"
Requires-Dist: mcp<2.0.0,>=1.28.0; extra == "all"
Requires-Dist: mpmath>=1.3.0; extra == "all"
Requires-Dist: networkx>=3.3; extra == "all"
Requires-Dist: numba>=0.60.0; extra == "all"
Requires-Dist: numpy>=1.26.4; extra == "all"
Requires-Dist: openbabel-wheel>=3.1.0; extra == "all"
Requires-Dist: optuna>=3.6.1; extra == "all"
Requires-Dist: optuna-dashboard>=0.16.2; extra == "all"
Requires-Dist: optuna-integration>=4.0.0; extra == "all"
Requires-Dist: pandas>=2.2.3; extra == "all"
Requires-Dist: pdb2pqr>=3.7.1; extra == "all"
Requires-Dist: pillow>=10.4.0; extra == "all"
Requires-Dist: pingouin>=0.5.5; extra == "all"
Requires-Dist: psycopg>=3.2.0; extra == "all"
Requires-Dist: pymysql>=1.1.1; extra == "all"
Requires-Dist: rdkit!=2026.3.3,>=2024.09.1; extra == "all"
Requires-Dist: rustworkx>=0.15.1; extra == "all"
Requires-Dist: scikit-image>=0.24.0; extra == "all"
Requires-Dist: scikit-learn>=1.5.2; extra == "all"
Requires-Dist: scipy>=1.14.1; extra == "all"
Requires-Dist: seaborn>=0.13.2; extra == "all"
Requires-Dist: shap>=0.44.0; extra == "all"
Requires-Dist: six>=1.17.0; extra == "all"
Requires-Dist: snakemake>=7.32.4; extra == "all"
Requires-Dist: snakemake-logger-plugin-snkmt>=0.1.6; extra == "all"
Requires-Dist: spyrmsd>=0.8.0; extra == "all"
Requires-Dist: sqlalchemy>=2.0.35; extra == "all"
Requires-Dist: sqlalchemy-utils>=0.41.2; extra == "all"
Requires-Dist: starlette>=1.3.1; extra == "all"
Requires-Dist: statsmodels>=0.14.3; extra == "all"
Requires-Dist: sympy>=1.13.3; extra == "all"
Requires-Dist: tifffile>=2024.9.20; extra == "all"
Requires-Dist: torch>=2.4.1; extra == "all"
Requires-Dist: torchaudio>=2.4.1; extra == "all"
Requires-Dist: torchsummary; extra == "all"
Requires-Dist: torchviz; extra == "all"
Requires-Dist: torchvision>=0.19.1; extra == "all"
Requires-Dist: uvicorn>=0.32.0; extra == "all"
Requires-Dist: visualtorch>=0.2.3; extra == "all"
Requires-Dist: xgboost>=2.1.1; extra == "all"
Provides-Extra: full
Requires-Dist: biopython>=1.84; extra == "full"
Requires-Dist: boto3>=1.35.31; extra == "full"
Requires-Dist: colorcet>=3.2.1; extra == "full"
Requires-Dist: cupy-cuda11x>=13.0.0; sys_platform != "darwin" and extra == "full"
Requires-Dist: dcor>=0.6; extra == "full"
Requires-Dist: dropbox>=12.0.2; extra == "full"
Requires-Dist: fastapi>=0.115.0; extra == "full"
Requires-Dist: fsspec>=2024.10.0; extra == "full"
Requires-Dist: furo; extra == "full"
Requires-Dist: gmpy2>=2.1.5; extra == "full"
Requires-Dist: google-cloud-storage>=2.18.2; extra == "full"
Requires-Dist: graphviz>=0.20.3; extra == "full"
Requires-Dist: h5py>=3.11.0; extra == "full"
Requires-Dist: httpx>=0.28.1; extra == "full"
Requires-Dist: imageio>=2.35.1; extra == "full"
Requires-Dist: ipython>=8.28.0; extra == "full"
Requires-Dist: lightgbm>=4.6.0; extra == "full"
Requires-Dist: lime>=0.2.0.1; extra == "full"
Requires-Dist: llvmlite>=0.43.0; extra == "full"
Requires-Dist: matplotlib>=3.9.2; extra == "full"
Requires-Dist: mcp<2.0.0,>=1.28.0; extra == "full"
Requires-Dist: mpmath>=1.3.0; extra == "full"
Requires-Dist: myst-parser>=4.0.1; extra == "full"
Requires-Dist: networkx>=3.3; extra == "full"
Requires-Dist: numba>=0.60.0; extra == "full"
Requires-Dist: numpy>=1.26.4; extra == "full"
Requires-Dist: openbabel-wheel>=3.1.0; extra == "full"
Requires-Dist: optuna>=3.6.1; extra == "full"
Requires-Dist: optuna-dashboard>=0.16.2; extra == "full"
Requires-Dist: optuna-integration>=4.0.0; extra == "full"
Requires-Dist: pandas>=2.2.3; extra == "full"
Requires-Dist: pillow>=10.4.0; extra == "full"
Requires-Dist: pingouin>=0.5.5; extra == "full"
Requires-Dist: psycopg>=3.2.0; extra == "full"
Requires-Dist: pymysql>=1.1.1; extra == "full"
Requires-Dist: rdkit!=2026.3.3,>=2024.09.1; extra == "full"
Requires-Dist: rustworkx>=0.15.1; extra == "full"
Requires-Dist: scikit-image>=0.24.0; extra == "full"
Requires-Dist: scikit-learn>=1.5.2; extra == "full"
Requires-Dist: scipy>=1.14.1; extra == "full"
Requires-Dist: seaborn>=0.13.2; extra == "full"
Requires-Dist: shap>=0.44.0; extra == "full"
Requires-Dist: six>=1.17.0; extra == "full"
Requires-Dist: snakemake>=7.32.4; extra == "full"
Requires-Dist: snakemake-logger-plugin-snkmt>=0.1.6; extra == "full"
Requires-Dist: spyrmsd>=0.8.0; extra == "full"
Requires-Dist: sphinx>=8.2.3; extra == "full"
Requires-Dist: sphinx-argparse>=0.5.2; extra == "full"
Requires-Dist: sphinx-rtd-theme>=3.0.2; extra == "full"
Requires-Dist: sqlalchemy>=2.0.35; extra == "full"
Requires-Dist: sqlalchemy-utils>=0.41.2; extra == "full"
Requires-Dist: starlette>=1.3.1; extra == "full"
Requires-Dist: statsmodels>=0.14.3; extra == "full"
Requires-Dist: sympy>=1.13.3; extra == "full"
Requires-Dist: tifffile>=2024.9.20; extra == "full"
Requires-Dist: torch>=2.4.1; extra == "full"
Requires-Dist: torchaudio>=2.4.1; extra == "full"
Requires-Dist: torchsummary; extra == "full"
Requires-Dist: torchviz; extra == "full"
Requires-Dist: torchvision>=0.19.1; extra == "full"
Requires-Dist: uvicorn>=0.32.0; extra == "full"
Requires-Dist: visualtorch>=0.2.3; extra == "full"
Requires-Dist: xgboost>=2.1.1; extra == "full"
Dynamic: license-file

[![codecov](https://codecov.io/gh/Arturossi/OCDocker/graph/badge.svg)](https://codecov.io/gh/Arturossi/OCDocker)
![CI](https://img.shields.io/github/actions/workflow/status/Arturossi/OCDocker/type-check.yml)
![Python](https://img.shields.io/pypi/pyversions/ocdocker)
![PyPI](https://img.shields.io/pypi/v/ocdocker)
![Issues](https://img.shields.io/github/issues/Arturossi/OCDocker)
![Last commit](https://img.shields.io/github/last-commit/Arturossi/OCDocker)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.21330171.svg)](https://doi.org/10.5281/zenodo.21330171)

![OCDocker](./OCDocker.png "OCDocker")

OCDocker
========

OCDocker is a Python toolkit and CLI for molecular docking, virtual screening,
pose clustering, rescoring, and OCScore model development. It is designed to run
as a command-line tool, Python API, or scheduler-friendly workflow component.

What it provides:

- Docking workflows for AutoDock Vina, Smina, Gnina, and PLANTS.
- Pipeline stages for preparation, docking, collection, RMSD clustering,
  rescoring, and export.
- Database support for PostgreSQL, MySQL, and SQLite.
- OCScore training, ablation, cross-validation, SHAP, plotting, and scoring
  utilities.
- Reproducibility helpers, environment diagnostics, and Docker/Singularity
  wrappers.

Documentation
-------------

- Manual: [MANUAL.md](MANUAL.md)
- Sphinx docs: [docs/source/index.rst](docs/source/index.rst)
- Installation details: [docs/source/installation.rst](docs/source/installation.rst)
- Optional dependencies: [docs/source/optional_dependencies.rst](docs/source/optional_dependencies.rst)
- Database setup: [docs/source/database_setup.md](docs/source/database_setup.md)
- External tools: [docs/source/external_tools.md](docs/source/external_tools.md)
- Containers: [docs/source/container_usage.md](docs/source/container_usage.md)
- OCScore replication: [OCSCORE_REPLICATION.md](OCSCORE_REPLICATION.md)
- OCScore production protocol: [docs/ocscore-production-protocol.md](docs/ocscore-production-protocol.md)
- Error handling: [docs/ERROR_HANDLING.md](docs/ERROR_HANDLING.md)

Installation
------------

OCDocker is easiest to run inside a conda or mamba environment.

```bash
mamba create -n ocdocker python=3.11 -y
conda activate ocdocker
pip install ocdocker
```

For development from source:

```bash
git clone https://github.com/Arturossi/OCDocker.git
cd OCDocker
mamba create -n ocdocker python=3.11 -y
conda activate ocdocker
./scripts/vendor_oddt.sh
pip install -e ".[all,dev]"
```

`scripts/vendor_oddt.sh` pulls in [our ODDT fork](https://github.com/Arturossi/oddt), which carries fixes on top of
upstream ODDT that OCDocker's rescoring depends on. It has to run before `pip install -e` because the `oddt`
package is bundled as source (`[tool.setuptools.packages.find]` picks up the local `oddt/` directory it creates),
not installed as a normal dependency -- PyPI rejects uploads whose metadata references a git dependency, so a
plain `pip install ocdocker` gets the fork the same way, just vendored in at release-build time instead of by hand.
Skipping this step leaves `import oddt` resolving to whatever (if any) vanilla `oddt` package happens to already be
on your `PYTHONPATH`, which does not have the fixes this project relies on.

Minimal system packages for Ubuntu/Debian:

```bash
sudo apt-get install openbabel libopenbabel-dev swig cmake g++
```

Feature-specific extras:

```bash
pip install "ocdocker[docking]"   # docking workflows
pip install "ocdocker[db]"        # PostgreSQL/MySQL storage
pip install "ocdocker[ml]"        # OCScore training and scoring
pip install "ocdocker[analysis]"  # plots, statistics, SHAP helpers
pip install "ocdocker[workflow]"  # Snakemake integration
pip install "ocdocker[all]"       # all runtime stacks
```

Quick Start
-----------

Use SQLite for local tests and quick experiments:

```bash
export OCDOCKER_DB_BACKEND=sqlite
ocdocker doctor
```

Run a single docking engine:

```bash
ocdocker vs \
  --engine vina \
  --receptor path/to/receptor.pdb \
  --ligand path/to/ligand.sdf \
  --box path/to/box.pdb \
  --timeout 600
```

Run the full docking pipeline:

```bash
ocdocker pipeline \
  --receptor path/to/receptor.pdb \
  --ligand path/to/ligand.sdf \
  --box path/to/box.pdb \
  --engines vina,smina,plants \
  --outdir runs/example
```

Run scheduler-friendly pipeline stages:

```bash
ocdocker pipeline prepare --help
ocdocker pipeline dock --help
ocdocker pipeline collect --help
ocdocker pipeline cluster --help
ocdocker pipeline rescore --help
ocdocker pipeline export --help
```

OCScore
-------

OCScore workflows are available under `ocdocker ocscore`.

```bash
ocdocker ocscore reduce --help
ocdocker ocscore train --help
ocdocker ocscore score --help
```

For the full reproducible protocol, including reduction, training, ablations,
statistics, plots, and SHAP analysis, use:

- [OCSCORE_REPLICATION.md](OCSCORE_REPLICATION.md)
- [docs/ocscore-production-protocol.md](docs/ocscore-production-protocol.md)
- [examples/18_run_full_pipeline.sh](examples/18_run_full_pipeline.sh)

Configuration
-------------

Create a starter config:

```bash
ocdocker init-config --conf OCDocker.cfg
```

Common environment variables:

- `OCDOCKER_CONFIG`: path to `OCDocker.cfg` or `OCDocker.yml`.
- `OCDOCKER_DB_BACKEND`: `postgresql`, `mysql`, or `sqlite`.
- `OCDOCKER_SQLITE_PATH`: custom SQLite database path.
- `OCDOCKER_TIMEOUT`: default external-tool timeout in seconds.
- `OCDOCKER_THREADS`: scheduler-provided worker count.
- `OCDOCKER_TMP_DIR`: job-local temporary directory.

For server databases, see [docs/source/database_setup.md](docs/source/database_setup.md).

Containers
-----------

Docker and Singularity helpers live under `containers/`.

Docker wrapper:

```bash
containers/docker/install_docker.sh --install-ocd
export OCDOCKER_DB_PASS='<db_password>'
ocd doctor
```

Use MySQL instead of the default PostgreSQL service:

```bash
export OCDOCKER_DB_BACKEND=mysql
export OCDOCKER_DB_PASS='<db_password>'
export MYSQL_ROOT_PASSWORD='<root_password>'
ocd doctor
```

More details: [docs/source/container_usage.md](docs/source/container_usage.md).

Diagnostics and Reproducibility
-------------------------------

Check the environment:

```bash
ocdocker doctor --conf OCDocker.cfg
```

Generate a reproducibility manifest:

```bash
ocdocker manifest --conf OCDocker.cfg --output reproducibility_manifest.json
```

Testing
-------

```bash
pytest -q
pytest --cov=OCDocker --cov-report=term-missing
```

External docking binaries are not required for most unit tests. End-to-end
docking runs require the configured tools to be available on the system or in the
container.

License
-------

OCDocker is released under the [BSD 3-Clause License](LICENSE). Copyright is held by
**Federal University of Rio de Janeiro (UFRJ)**, **Artur Duque Rossi**, and
**Pedro Henrique Monteiro Torres** only (see [NOTICE](NOTICE)). You may use,
modify, and redistribute the software for any purpose, including commercial
work, provided you include the BSD license notice. Please credit UFRJ and the
copyright holders in publications. Community contributors are acknowledged in
[COLLABORATORS.md](COLLABORATORS.md).

Community
---------

- Code of Conduct: [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)
- Contributing: [CONTRIBUTING.md](CONTRIBUTING.md)
- Security: [SECURITY.md](SECURITY.md)
- Collaborators: [COLLABORATORS.md](COLLABORATORS.md)
