diff --git a/.coveragerc b/.coveragerc index da2347b..469af0c 100644 --- a/.coveragerc +++ b/.coveragerc @@ -13,6 +13,3 @@ exclude_lines = # Don't complain if non-runnable code isn't run: if 0: if __name__ == .__main__.: - - # OpenBabel2 - except ImportError: diff --git a/CHANGELOG.md b/CHANGELOG.md index 60b5993..84dd7fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ Date: XXX/XX/XXX Contributors: @RMeli +### Improved + +* Documentation on loading RDKit and Open Babel molecules [PR #77 | @RMeli] + ### Changed * Version of several GitHub actions [PR #76 | @RMeli] @@ -15,10 +19,21 @@ Contributors: @RMeli * Minimum Python version to `3.7` to match CI [PR #76 | @RMeli] * Code according to `black==23.3.0` [PR #76 | @RMeli] +### Added + +* Pin to `sphinx<7` to avoid compatibility with RTD theme [PR #77 | @RMeli] + ### Removed +* Outdated information about RDKit from the documentation [PR #84 | @RMeli] +* Support for Open Babel 2 [PR #84 | @RMeli] * LGTM badge and code annotations [PR #76 | @RMeli] +### Added + +* `extras_require` to `setup.py` for RDKit and Open Babel [PR #84 | @RMeli] +* Error message when `spyrmsd` is used as module but neither OpenBabel nor RDKit are installed [PR #81 | @RMeli] + ------------------------------------------------------------------------------ ## Version 0.5.2 diff --git a/README.md b/README.md index cf55bd5..9c952e4 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,8 @@ If you find `spyrmsd` useful, please consider citing the following paper: _Note_: `spyrmsd` will install [NetworkX](https://networkx.github.io/) (multi-platform). You can install [graph-tool](https://graph-tool.skewed.de/) on macOS and Linux for higher performance. +_Note_: If `spyrmsd` is used as a standalone tool, it is required to install either [RDKit](https://rdkit.org/) or [Open Babel](http://openbabel.org/). Neither is automatically installed with `pip` nor `conda`. + ### PyPI ```bash @@ -80,8 +82,6 @@ Additionally, one of the following packages is required to use `spyrmsd` as a st * [Open Babel](http://openbabel.org/) * [RDKit](https://rdkit.org/) -_Note_: [RDKit](https://rdkit.org/) is not available on PyPI ([Why the RDKit isn't available on PyPi](https://rdkit.blogspot.com/2019/11/why-rdkit-isnt-available-on-pypi.html)). See [RDKit Installation](http://www.rdkit.org/docs/Install.html) for installation instructions. - ## Usage ### Standalone Tool diff --git a/devtools/conda-envs/spyrmsd-all.yaml b/devtools/conda-envs/spyrmsd-all.yaml index fd25e13..c4fc680 100644 --- a/devtools/conda-envs/spyrmsd-all.yaml +++ b/devtools/conda-envs/spyrmsd-all.yaml @@ -33,7 +33,7 @@ dependencies: - codecov # Doc - - sphinx + - sphinx<7 - sphinx_rtd_theme - pip: - duecredit diff --git a/devtools/conda-envs/spyrmsd-docs.yaml b/devtools/conda-envs/spyrmsd-docs.yaml index f1e4568..aa214ed 100644 --- a/devtools/conda-envs/spyrmsd-docs.yaml +++ b/devtools/conda-envs/spyrmsd-docs.yaml @@ -17,5 +17,5 @@ dependencies: - rdkit # Doc - - sphinx + - sphinx<7 - sphinx_rtd_theme diff --git a/docs/README.md b/docs/README.md index 31e9ecf..b893b55 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,7 +4,7 @@ The docs for this project are built with [Sphinx](http://www.sphinx-doc.org/en/m ## Installation -Ensure that Sphinx and the ReadTheDocs theme are installed: +Ensure that Sphinx and the [Read the Docs](https://sphinx-rtd-theme.readthedocs.io/en/stable/index.html) theme are installed: ```bash conda install sphinx sphinx_rtd_theme @@ -20,6 +20,15 @@ Create API documentation automatically with `sphinx-apidoc`: sphinx-apidoc -f -M -e -T -o source/api ../spyrmsd ``` +### Convert Tutorial Jupyter Notebooks to HTML + +Jupyter Notebooks need to be converted to HTML: + +```bash +pip install pandoc +jupyter nbconvert --to rst tutorial.ipynb +``` + ### Build Documentation Use the `Makefile` to compile static HTML pages: diff --git a/docs/source/installation.rst b/docs/source/installation.rst index a79d617..31497c3 100644 --- a/docs/source/installation.rst +++ b/docs/source/installation.rst @@ -59,13 +59,9 @@ Additionally, one of the following packages is required to use ``spyrmsd`` as a * `Open Babel`_ * RDKit_ -.. note:: - RDKit_ has to be installed using ``conda`` (see `Why the RDKit isn't available on PyPi`_). - .. _PyPI: https://pypi.org/project/spyrmsd/ .. _conda-forge: https://github.com/conda-forge/spyrmsd-feedstock .. _RDKit: https://rdkit.org/ -.. _Why the RDKit isn't available on PyPi: https://rdkit.blogspot.com/2019/11/why-rdkit-isnt-available-on-pypi.html .. _Open Babel: http://openbabel.org/ .. _graph-tool: https://graph-tool.skewed.de/ .. _NetworkX: https://networkx.github.io/ diff --git a/docs/source/tutorials/tutorial.ipynb b/docs/source/tutorials/tutorial.ipynb index bb92090..5b626ea 100644 --- a/docs/source/tutorials/tutorial.ipynb +++ b/docs/source/tutorials/tutorial.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -9,7 +10,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -17,6 +18,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -24,6 +26,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -37,6 +40,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -44,6 +48,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -52,7 +57,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -60,6 +65,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -68,7 +74,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -76,6 +82,66 @@ ] }, { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Loading RDKit or OpenBabel Molecules" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`spyrmsd` natively supports Open Babel and RDKit (if installed). The `Molecule` class provides `from_openbabel()` and `from_rdkit()` constructors." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + ":241: RuntimeWarning: to-Python converter for std::__1::pair already registered; second conversion method ignored.\n", + "[18:44:03] Molecule does not have explicit Hs. Consider calling AddHs()\n", + "[18:44:03] Molecule does not have explicit Hs. Consider calling AddHs()\n" + ] + }, + { + "data": { + "text/plain": [ + "[0.019162902039384797]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from rdkit import Chem\n", + "from rdkit.Chem import AllChem\n", + "\n", + "rdmol1 = Chem.MolFromSmiles(\"c1ccccc1\")\n", + "rdmol2 = Chem.MolFromSmiles(\"c1ccccc1\")\n", + "AllChem.EmbedMolecule(rdmol1)\n", + "AllChem.EmbedMolecule(rdmol2)\n", + "\n", + "from spyrmsd.molecule import Molecule\n", + "from spyrmsd.rmsd import rmsdwrapper\n", + "\n", + "mol1 = Molecule.from_rdkit(rdmol1)\n", + "mol2 = Molecule.from_rdkit(rdmol2)\n", + "\n", + "rmsdwrapper(mol1, mol2)" + ] + }, + { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -83,6 +149,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -91,7 +158,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -100,7 +167,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -109,6 +176,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -116,6 +184,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -124,7 +193,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -135,7 +204,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -145,6 +214,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -153,7 +223,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -178,6 +248,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -185,6 +256,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -193,14 +265,14 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "[1.2012368667355435, 1.0533413220699535, 1.153253104575529, 1.036542688936588, 0.8407673221224143, 1.1758143217869736, 0.7817315189656655, 1.0933314311267845, 1.0260767175206462, 0.9586369647000478]\n" + "[1.2012368667355435, 1.0533413220699535, 1.153253104575529, 1.036542688936588, 0.8407673221224187, 1.1758143217869736, 0.7817315189656655, 1.0933314311267845, 1.0260767175206462, 0.9586369647000478]\n" ] } ], @@ -235,7 +307,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.11.4" } }, "nbformat": 4, diff --git a/docs/source/tutorials/tutorial.rst b/docs/source/tutorials/tutorial.rst index 3c1e218..7154a1a 100644 --- a/docs/source/tutorials/tutorial.rst +++ b/docs/source/tutorials/tutorial.rst @@ -39,6 +39,47 @@ molecules we need to use ``io.loadallmols``: mols = io.loadallmols("molecules/1a4k_dock.sdf") +Loading RDKit or OpenBabel Molecules +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``spyrmsd`` natively supports Open Babel and RDKit (if installed). The +``Molecule`` class provides ``from_openbabel()`` and ``from_rdkit()`` +constructors. + +.. code:: ipython3 + + from rdkit import Chem + from rdkit.Chem import AllChem + + rdmol1 = Chem.MolFromSmiles("c1ccccc1") + rdmol2 = Chem.MolFromSmiles("c1ccccc1") + AllChem.EmbedMolecule(rdmol1) + AllChem.EmbedMolecule(rdmol2) + + from spyrmsd.molecule import Molecule + from spyrmsd.rmsd import rmsdwrapper + + mol1 = Molecule.from_rdkit(rdmol1) + mol2 = Molecule.from_rdkit(rdmol2) + + rmsdwrapper(mol1, mol2) + + +.. parsed-literal:: + + :241: RuntimeWarning: to-Python converter for std::__1::pair already registered; second conversion method ignored. + [18:44:03] Molecule does not have explicit Hs. Consider calling AddHs() + [18:44:03] Molecule does not have explicit Hs. Consider calling AddHs() + + + + +.. parsed-literal:: + + [0.019162902039384797] + + + Removing Hydrogen Atoms ~~~~~~~~~~~~~~~~~~~~~~~ @@ -86,7 +127,7 @@ reference molecule and all other molecules: adj_ref, adj, ) - + print(RMSD) @@ -112,10 +153,11 @@ molecular structures: adj, minimize=True, ) - + print(RMSD) .. parsed-literal:: - [1.2012368667355435, 1.0533413220699535, 1.153253104575529, 1.036542688936588, 0.8407673221224143, 1.1758143217869736, 0.7817315189656655, 1.0933314311267845, 1.0260767175206462, 0.9586369647000478] + [1.2012368667355435, 1.0533413220699535, 1.153253104575529, 1.036542688936588, 0.8407673221224187, 1.1758143217869736, 0.7817315189656655, 1.0933314311267845, 1.0260767175206462, 0.9586369647000478] + diff --git a/pyproject.toml b/pyproject.toml index 4ecfd74..2cf8457 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ module = "spyrmsd" dist-name = "spyrmsd" description-file = "README.md" author = "Rocco Meli" -author-email = "rocco.meli@biodtp.ox.ac.uk" +author-email = "rocco.meli@cscs.ch" home-page = "https://spyrmsd.readthedocs.io" classifiers = [ "License :: OSI Approved :: MIT License", diff --git a/setup.py b/setup.py index 9e8a507..3bdc46e 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ # Self-descriptive entries which should always be present name="spyrmsd", author="Rocco Meli", - author_email="rocco.meli@biodtp.ox.ac.uk", + author_email="rocco.meli@cscs.ch", description=short_description[0], long_description=long_description, long_description_content_type="text/markdown", @@ -32,7 +32,7 @@ include_package_data=True, url="https://spyrmsd.readthedocs.io", install_requires=["numpy", "scipy", "networkx>=2"], - extras_require={"bib": ["duecredit"]}, + extras_require={"bib": ["duecredit"], "rdkit": ["rdkit"], "openbabel": ["openbabel"]}, platforms=["Linux", "Mac OS-X", "Unix", "Windows"], python_requires=">=3.7", ) diff --git a/spyrmsd/__main__.py b/spyrmsd/__main__.py index 418def7..b56104c 100644 --- a/spyrmsd/__main__.py +++ b/spyrmsd/__main__.py @@ -4,6 +4,8 @@ if __name__ == "__main__": import argparse as ap + import importlib.util + import sys from spyrmsd import io @@ -27,6 +29,14 @@ args = parser.parse_args() + if ( + importlib.util.find_spec("openbabel") is None + and importlib.util.find_spec("rdkit") is None + ): + raise ImportError( + "OpenBabel or RDKit not found. Please install OpenBabel or RDKit to use sPyRMSD as a standalone tool." + ) + try: ref = io.loadmol(args.reference) except OSError: diff --git a/spyrmsd/optional/obabel.py b/spyrmsd/optional/obabel.py index b0b979e..b373a8e 100644 --- a/spyrmsd/optional/obabel.py +++ b/spyrmsd/optional/obabel.py @@ -4,14 +4,8 @@ from spyrmsd import molecule, utils -try: - # 3.0 - from openbabel import openbabel as ob - from openbabel import pybel -except ImportError: - # 2.0 - import openbabel as ob - import pybel +from openbabel import openbabel as ob +from openbabel import pybel def load(fname: str):