From afded37125d2ce669e05646dc3e320b36f6bede0 Mon Sep 17 00:00:00 2001 From: Alex Mestiashvili Date: Wed, 11 Dec 2024 18:03:03 +0100 Subject: [PATCH 1/5] Update setup.py, fix and build openababel bindings Other requirements are SWIG and openbabel dev files --- setup.py | 111 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 84 insertions(+), 27 deletions(-) diff --git a/setup.py b/setup.py index 3768e62..f588495 100644 --- a/setup.py +++ b/setup.py @@ -1,32 +1,89 @@ from setuptools import setup, find_packages +from setuptools.command.build_ext import build_ext +from setuptools.command.install import install +from distutils.command.build import build from plip.basic import config +class CustomBuild(build): + """Ensure build_ext runs first in build command.""" + def run(self): + self.run_command('build_ext') + build.run(self) + +class CustomInstall(install): + """Ensure build_ext runs first in install command.""" + def run(self): + self.run_command('build_ext') + install.run(self) + +class CustomBuildExt(build_ext): + """ A workaround to build openbabel python3 bindings, for details see: + https://github.com/openbabel/openbabel/issues/2408 + """ + + def run(self): + import requests + import tarfile + import tempfile + import shutil + import fileinput + import subprocess + import sys + + openbabel_pypi_url='https://files.pythonhosted.org/packages/9d/3f/f08f5d1422d74ed0e1e612870b343bfcc26313bdf9efec9165c3ea4b3ae2/openbabel-3.1.1.1.tar.gz' + + def install(package): + subprocess.check_call([sys.executable, '-m', 'pip', 'install', '--user', package]) + + print (f"Downloading openbabel package from : {openbabel_pypi_url}") + obtar=requests.get(openbabel_pypi_url) + obtmpdir = tempfile.mkdtemp() + obtmp = obtmpdir+'/openbabel-3.1.1.1.tar' + open(obtmp,'wb').write(obtar.content) + print(f"Saving openbable tar.gz to {obtmpdir}") + versfile = obtmpdir+'/openbabel-3.1.1.1/openbabel/__init__.py' + + with tarfile.open(obtmp,mode='r') as tf: + tf.extractall(obtmpdir) + + print ('Fix versions: s/3.1.1.1/3.1.1/ to make StrictVersion() happy') + print ('See https://github.com/openbabel/openbabel/issues/2408 for more details') + with fileinput.input(files=versfile,inplace=True) as f: + for line in f: + op = line.replace('__version__ = "3.1.1.1"', '__version__ = "3.1.1"') + print(op, end='') + + install(obtmpdir+'/openbabel-3.1.1.1/') + print (f"Cleanup tmpdir: {obtmpdir}") + shutil.rmtree(obtmpdir) + setup(name='plip', - version=config.__version__, - description='PLIP - Fully automated protein-ligand interaction profiler', - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Science/Research', - 'Natural Language :: English', - 'License :: OSI Approved :: GNU General Public License v2 (GPLv2)', - 'Programming Language :: Python :: 3.6', - 'Topic :: Scientific/Engineering :: Bio-Informatics' - ], - url='https://github.com/pharmai/plip', - author='PharmAI GmbH', - author_email='hello@pharm.ai', - license='GPLv2', - packages=find_packages(), - scripts=['plip/plipcmd.py'], - install_requires=[ - 'openbabel', - 'numpy', - 'lxml' - ], - entry_points={ - "console_scripts": [ - "plip = plip.plipcmd:main" - ] - }, - zip_safe=False) + version=config.__version__, + description='PLIP - Fully automated protein-ligand interaction profiler', + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Science/Research', + 'Natural Language :: English', + 'License :: OSI Approved :: GNU General Public License v2 (GPLv2)', + 'Programming Language :: Python :: 3.6', + 'Topic :: Scientific/Engineering :: Bio-Informatics' + ], + url='https://github.com/pharmai/plip', + author='PharmAI GmbH', + author_email='hello@pharm.ai', + license='GPLv2', + packages=find_packages(), + scripts=['plip/plipcmd.py'], + cmdclass={'build': CustomBuild, 'build_ext': CustomBuildExt, 'install': CustomInstall}, + install_requires=[ + 'requests', + 'numpy', + 'lxml' + ], + entry_points={ + "console_scripts": [ + "plip = plip.plipcmd:main" + ] + }, + zip_safe=False) From 1f309f8ba953fca582c1d4aa91f0a8f46daf97c4 Mon Sep 17 00:00:00 2001 From: Alex Mestiashvili Date: Thu, 12 Dec 2024 11:38:48 +0100 Subject: [PATCH 2/5] Update setup.py, attempt to build ob bindings only if not loadable --- setup.py | 91 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 52 insertions(+), 39 deletions(-) diff --git a/setup.py b/setup.py index f588495..0c85fa8 100644 --- a/setup.py +++ b/setup.py @@ -5,6 +5,50 @@ from plip.basic import config +def install_pkg_via_pip(package): + import subprocess + subprocess.check_call([sys.executable, '-m', 'pip', 'install', '--user', package]) + +def build_ob_py_bindings(): + """ Fix openbabel issue (https://github.com/openbabel/openbabel/issues/2408) manually + - Download openbabel bindings from pypi + - extract to a tmpdir + - fix version in $tmpdir/openbabel-3.1.1.1/openbabel/__init__.py to have 2 dot version only + - install the fixed version with setuptools/pip + - cleanup the tmpdir + """ + import requests + import tarfile + import tempfile + import shutil + import fileinput + import subprocess + import sys + + openbabel_pypi_url='https://files.pythonhosted.org/packages/9d/3f/f08f5d1422d74ed0e1e612870b343bfcc26313bdf9efec9165c3ea4b3ae2/openbabel-3.1.1.1.tar.gz' + + print (f"Downloading openbabel package from : {openbabel_pypi_url}") + obtar=requests.get(openbabel_pypi_url) + obtmpdir = tempfile.mkdtemp() + obtmp = obtmpdir+'/openbabel-3.1.1.1.tar' + open(obtmp,'wb').write(obtar.content) + print(f"Saving openbabel tar.gz to {obtmpdir}") + versfile = obtmpdir+'/openbabel-3.1.1.1/openbabel/__init__.py' + + with tarfile.open(obtmp,mode='r') as tf: + tf.extractall(obtmpdir) + + print ('Fix versions: s/3.1.1.1/3.1.1/ to make StrictVersion() in openbabel\'s setup.py happy') + print ('See https://github.com/openbabel/openbabel/issues/2408 for more details') + with fileinput.input(files=versfile,inplace=True) as f: + for line in f: + op = line.replace('__version__ = "3.1.1.1"', '__version__ = "3.1.1"') + print(op, end='') + + install_pkg_via_pip(obtmpdir+'/openbabel-3.1.1.1/') + print (f"Cleanup tmpdir: {obtmpdir}") + shutil.rmtree(obtmpdir) + class CustomBuild(build): """Ensure build_ext runs first in build command.""" def run(self): @@ -18,45 +62,15 @@ def run(self): install.run(self) class CustomBuildExt(build_ext): - """ A workaround to build openbabel python3 bindings, for details see: - https://github.com/openbabel/openbabel/issues/2408 - """ - + """ Check if openbabel bindings are installed || build them """ def run(self): - import requests - import tarfile - import tempfile - import shutil - import fileinput - import subprocess - import sys - - openbabel_pypi_url='https://files.pythonhosted.org/packages/9d/3f/f08f5d1422d74ed0e1e612870b343bfcc26313bdf9efec9165c3ea4b3ae2/openbabel-3.1.1.1.tar.gz' - - def install(package): - subprocess.check_call([sys.executable, '-m', 'pip', 'install', '--user', package]) - - print (f"Downloading openbabel package from : {openbabel_pypi_url}") - obtar=requests.get(openbabel_pypi_url) - obtmpdir = tempfile.mkdtemp() - obtmp = obtmpdir+'/openbabel-3.1.1.1.tar' - open(obtmp,'wb').write(obtar.content) - print(f"Saving openbable tar.gz to {obtmpdir}") - versfile = obtmpdir+'/openbabel-3.1.1.1/openbabel/__init__.py' - - with tarfile.open(obtmp,mode='r') as tf: - tf.extractall(obtmpdir) - - print ('Fix versions: s/3.1.1.1/3.1.1/ to make StrictVersion() happy') - print ('See https://github.com/openbabel/openbabel/issues/2408 for more details') - with fileinput.input(files=versfile,inplace=True) as f: - for line in f: - op = line.replace('__version__ = "3.1.1.1"', '__version__ = "3.1.1"') - print(op, end='') - - install(obtmpdir+'/openbabel-3.1.1.1/') - print (f"Cleanup tmpdir: {obtmpdir}") - shutil.rmtree(obtmpdir) + try: import openbabel + except ModuleNotFoundError: + try: import requests + except ModuleNotFoundError: + install_pkg_via_pip('requests') + build_ob_py_bindings() + return setup(name='plip', version=config.__version__, @@ -77,7 +91,6 @@ def install(package): scripts=['plip/plipcmd.py'], cmdclass={'build': CustomBuild, 'build_ext': CustomBuildExt, 'install': CustomInstall}, install_requires=[ - 'requests', 'numpy', 'lxml' ], From 0906cb5bf6d405198f3f86f998137db4edaa51be Mon Sep 17 00:00:00 2001 From: Alex Mestiashvili Date: Thu, 12 Dec 2024 11:58:41 +0100 Subject: [PATCH 3/5] Fix indentation in setup.py --- setup.py | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/setup.py b/setup.py index 0c85fa8..a905b6e 100644 --- a/setup.py +++ b/setup.py @@ -73,30 +73,30 @@ def run(self): return setup(name='plip', - version=config.__version__, - description='PLIP - Fully automated protein-ligand interaction profiler', - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Science/Research', - 'Natural Language :: English', - 'License :: OSI Approved :: GNU General Public License v2 (GPLv2)', - 'Programming Language :: Python :: 3.6', - 'Topic :: Scientific/Engineering :: Bio-Informatics' - ], - url='https://github.com/pharmai/plip', - author='PharmAI GmbH', - author_email='hello@pharm.ai', - license='GPLv2', - packages=find_packages(), - scripts=['plip/plipcmd.py'], - cmdclass={'build': CustomBuild, 'build_ext': CustomBuildExt, 'install': CustomInstall}, - install_requires=[ - 'numpy', - 'lxml' - ], - entry_points={ - "console_scripts": [ - "plip = plip.plipcmd:main" - ] - }, - zip_safe=False) + version=config.__version__, + description='PLIP - Fully automated protein-ligand interaction profiler', + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Science/Research', + 'Natural Language :: English', + 'License :: OSI Approved :: GNU General Public License v2 (GPLv2)', + 'Programming Language :: Python :: 3.6', + 'Topic :: Scientific/Engineering :: Bio-Informatics' + ], + url='https://github.com/pharmai/plip', + author='PharmAI GmbH', + author_email='hello@pharm.ai', + license='GPLv2', + packages=find_packages(), + scripts=['plip/plipcmd.py'], + cmdclass={'build': CustomBuild, 'build_ext': CustomBuildExt, 'install': CustomInstall}, + install_requires=[ + 'numpy', + 'lxml' + ], + entry_points={ + "console_scripts": [ + "plip = plip.plipcmd:main" + ] + }, + zip_safe=False) From 1d5ad0eab057a9cde7948fdd0e7d76d6f584d50a Mon Sep 17 00:00:00 2001 From: Alex Mestiashvili Date: Thu, 12 Dec 2024 15:37:42 +0100 Subject: [PATCH 4/5] Update Dockerfile Use Debian stable as the base, no need to build openbabel, since it is in the recent state since Bullseye --- Dockerfile | 82 +++++++----------------------------------------------- 1 file changed, 10 insertions(+), 72 deletions(-) diff --git a/Dockerfile b/Dockerfile index bc7c7ae..d428975 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,86 +1,24 @@ -FROM ubuntu:18.04 AS builder - -ARG OPENBABEL_TAG="openbabel-3-0-0" -ARG RDKIT_TAG="Release_2019_09_3" -ARG MMTF_TAG="v1.0.0" -ARG PYMOL_TAG="v2.3.0" +FROM debian:stable LABEL maintainer="PharmAI GmbH " \ org.label-schema.name="PLIP: The Protein-Ligand Interaction Profiler" \ org.label-schema.description="https://www.doi.org/10.1093/nar/gkv315" +ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y \ - cmake \ - git \ - g++ \ - imagemagick \ - libboost-all-dev \ - libeigen3-dev \ - libfreetype6-dev \ - libghc-zlib-dev \ - libglew-dev \ - libglm-dev \ - libmsgpack-dev \ - libnetcdf-dev \ - libxml2-dev \ - libpng-dev \ - libpython3-all-dev \ - python3 \ + pymol \ + python3-distutils \ python3-lxml \ - python3-numpy \ - python3-pyqt5.qtopengl \ - swig - -# build OpenBabel -WORKDIR /src -RUN git clone -b $OPENBABEL_TAG \ - https://github.com/openbabel/openbabel.git -WORKDIR /src/openbabel/build -RUN cmake .. \ - -DPYTHON_EXECUTABLE=/usr/bin/python3.6 \ - -DPYTHON_BINDINGS=ON \ - -DCMAKE_INSTALL_PREFIX=/usr/local \ - -DRUN_SWIG=ON -RUN make -j$(nproc --all) install - -# build RDkit -#WORKDIR /src -#RUN git clone -b $RDKIT_TAG \ -# https://github.com/rdkit/rdkit.git -#WORKDIR /src/rdkit/build -#RUN cmake .. \ -# -DCMAKE_BUILD_TYPE=Release \ -# -DRDK_BUILD_INCHI_SUPPORT=ON \ -# -DPYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython3.6m.so \ -# -DPYTHON_INCLUDE_DIR=/usr/include/python3.6 \ -# -DPYTHON_EXECUTABLE=/usr/bin/python3.6 -#RUN make -j$(nproc --all) install -#ENV RDBASE /src/rdkit -#ENV LD_LIBRARY_PATH /usr/local/lib/:$RDBASE/lib -#ENV PYTHONPATH $PYTHONPATH:$RDBASE - -# build mmtf-cpp -WORKDIR /src -RUN git clone -b $MMTF_TAG \ - https://github.com/rcsb/mmtf-cpp.git -WORKDIR /src/mmtf-cpp/build -RUN cmake .. -RUN make -j$(nproc --all) install - -# build PyMOL -WORKDIR /src -RUN git clone -b $PYMOL_TAG \ - https://github.com/schrodinger/pymol-open-source -WORKDIR /src/pymol-open-source -RUN python3 setup.py build install \ - --prefix=/usr/local \ - --jobs=$(nproc --all) + python3-openbabel \ + python3-pymol; \ + apt-get clean && rm -rf /var/lib/apt/lists/* # copy PLIP source code WORKDIR /src ADD plip/ plip/ RUN chmod +x plip/plipcmd.py -ENV PYTHONPATH $PYTHONPATH:/src +ENV PYTHONPATH=/src + # execute tests WORKDIR /src/plip/test @@ -89,4 +27,4 @@ RUN ./run_all_tests.sh WORKDIR / # set entry point to plipcmd.py -ENTRYPOINT ["python3", "/src/plip/plipcmd.py"] \ No newline at end of file +ENTRYPOINT ["python3", "/src/plip/plipcmd.py"] From 6aaed141aac56dcddbf66f5543b84e58f61f733f Mon Sep 17 00:00:00 2001 From: Alex Mestiashvili Date: Thu, 12 Dec 2024 15:44:38 +0100 Subject: [PATCH 5/5] Make Dockerfile modifications in a diferent branch, keep the old file so far --- Dockerfile | 82 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 72 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index d428975..bc7c7ae 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,24 +1,86 @@ -FROM debian:stable +FROM ubuntu:18.04 AS builder + +ARG OPENBABEL_TAG="openbabel-3-0-0" +ARG RDKIT_TAG="Release_2019_09_3" +ARG MMTF_TAG="v1.0.0" +ARG PYMOL_TAG="v2.3.0" LABEL maintainer="PharmAI GmbH " \ org.label-schema.name="PLIP: The Protein-Ligand Interaction Profiler" \ org.label-schema.description="https://www.doi.org/10.1093/nar/gkv315" -ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y \ - pymol \ - python3-distutils \ + cmake \ + git \ + g++ \ + imagemagick \ + libboost-all-dev \ + libeigen3-dev \ + libfreetype6-dev \ + libghc-zlib-dev \ + libglew-dev \ + libglm-dev \ + libmsgpack-dev \ + libnetcdf-dev \ + libxml2-dev \ + libpng-dev \ + libpython3-all-dev \ + python3 \ python3-lxml \ - python3-openbabel \ - python3-pymol; \ - apt-get clean && rm -rf /var/lib/apt/lists/* + python3-numpy \ + python3-pyqt5.qtopengl \ + swig + +# build OpenBabel +WORKDIR /src +RUN git clone -b $OPENBABEL_TAG \ + https://github.com/openbabel/openbabel.git +WORKDIR /src/openbabel/build +RUN cmake .. \ + -DPYTHON_EXECUTABLE=/usr/bin/python3.6 \ + -DPYTHON_BINDINGS=ON \ + -DCMAKE_INSTALL_PREFIX=/usr/local \ + -DRUN_SWIG=ON +RUN make -j$(nproc --all) install + +# build RDkit +#WORKDIR /src +#RUN git clone -b $RDKIT_TAG \ +# https://github.com/rdkit/rdkit.git +#WORKDIR /src/rdkit/build +#RUN cmake .. \ +# -DCMAKE_BUILD_TYPE=Release \ +# -DRDK_BUILD_INCHI_SUPPORT=ON \ +# -DPYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython3.6m.so \ +# -DPYTHON_INCLUDE_DIR=/usr/include/python3.6 \ +# -DPYTHON_EXECUTABLE=/usr/bin/python3.6 +#RUN make -j$(nproc --all) install +#ENV RDBASE /src/rdkit +#ENV LD_LIBRARY_PATH /usr/local/lib/:$RDBASE/lib +#ENV PYTHONPATH $PYTHONPATH:$RDBASE + +# build mmtf-cpp +WORKDIR /src +RUN git clone -b $MMTF_TAG \ + https://github.com/rcsb/mmtf-cpp.git +WORKDIR /src/mmtf-cpp/build +RUN cmake .. +RUN make -j$(nproc --all) install + +# build PyMOL +WORKDIR /src +RUN git clone -b $PYMOL_TAG \ + https://github.com/schrodinger/pymol-open-source +WORKDIR /src/pymol-open-source +RUN python3 setup.py build install \ + --prefix=/usr/local \ + --jobs=$(nproc --all) # copy PLIP source code WORKDIR /src ADD plip/ plip/ RUN chmod +x plip/plipcmd.py -ENV PYTHONPATH=/src - +ENV PYTHONPATH $PYTHONPATH:/src # execute tests WORKDIR /src/plip/test @@ -27,4 +89,4 @@ RUN ./run_all_tests.sh WORKDIR / # set entry point to plipcmd.py -ENTRYPOINT ["python3", "/src/plip/plipcmd.py"] +ENTRYPOINT ["python3", "/src/plip/plipcmd.py"] \ No newline at end of file