diff --git a/CITATION.cff b/CITATION.cff index c05ac24..188e629 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -39,7 +39,7 @@ repository-code: "https://github.com/bioexcel/biobb" title: "BioExcel Building Blocks, a software library for interoperable biomolecular simulation workflows" doi: "10.1038/s41597-019-0177-4" url: "https://mmb.irbbarcelona.org/biobb/" -version: 4.2.0 +version: 5.0.0 preferred-citation: type: "article" authors: diff --git a/README.md b/README.md index 8b28b48..8200cee 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![](https://img.shields.io/conda/vn/bioconda/biobb_vs?label=Conda)](https://anaconda.org/bioconda/biobb_vs) [![](https://img.shields.io/conda/dn/bioconda/biobb_vs?label=Conda%20Downloads)](https://anaconda.org/bioconda/biobb_vs) [![](https://img.shields.io/badge/Docker-Quay.io-blue)](https://quay.io/repository/biocontainers/biobb_vs?tab=tags) -[![](https://img.shields.io/badge/Singularity-GalaxyProject-blue)](https://depot.galaxyproject.org/singularity/biobb_vs:4.2.0--pyhdfd78af_0) +[![](https://img.shields.io/badge/Singularity-GalaxyProject-blue)](https://depot.galaxyproject.org/singularity/biobb_vs:5.0.0--pyhdfd78af_0) [![](https://img.shields.io/badge/OS-Unix%20%7C%20MacOS-blue)](https://github.com/bioexcel/biobb_vs) [![](https://img.shields.io/pypi/pyversions/biobb-vs.svg?label=Python%20Versions)](https://pypi.org/project/biobb-vs/) @@ -42,7 +42,7 @@ The latest documentation of this package can be found in our readthedocs site: > At the time of publishing the current version, **autodock_vina has not been compiled for the new ARM mac M1/M2 chips**. So the vina.autodock_vina_run only work in these computers through docker containers. ### Version -v4.2.0 2024.1 +v5.0.0 2024.1 ### Installation Using PIP: @@ -52,7 +52,7 @@ Using PIP: * Installation: - pip install "biobb_vs>=4.2.0" + pip install "biobb_vs>=5.0.0" * Usage: [Python API documentation](https://biobb-vs.readthedocs.io/en/latest/modules.html) @@ -62,7 +62,7 @@ Using ANACONDA: * Installation: - conda install -c bioconda "biobb_vs>=4.2.0" + conda install -c bioconda "biobb_vs>=5.0.0" * Usage: With conda installation BioBBs can be used with the [Python API documentation](https://biobb-vs.readthedocs.io/en/latest/modules.html) and the [Command Line documentation](https://biobb-vs.readthedocs.io/en/latest/command_line.html) @@ -72,13 +72,13 @@ Using DOCKER: * Installation: - docker pull quay.io/biocontainers/biobb_vs:4.2.0--pyhdfd78af_0 + docker pull quay.io/biocontainers/biobb_vs:5.0.0--pyhdfd78af_0 * Usage: - docker run quay.io/biocontainers/biobb_vs:4.2.0--pyhdfd78af_0 + docker run quay.io/biocontainers/biobb_vs:5.0.0--pyhdfd78af_0 Using SINGULARITY: @@ -87,7 +87,7 @@ Using SINGULARITY: * Installation: - singularity pull --name biobb_vs.sif https://depot.galaxyproject.org/singularity/biobb_vs:4.2.0--pyhdfd78af_0 + singularity pull --name biobb_vs.sif https://depot.galaxyproject.org/singularity/biobb_vs:5.0.0--pyhdfd78af_0 * Usage: diff --git a/biobb_vs/__init__.py b/biobb_vs/__init__.py index 742d883..f8cab32 100644 --- a/biobb_vs/__init__.py +++ b/biobb_vs/__init__.py @@ -1,6 +1,5 @@ -from . import fpocket -from . import vina -from . import utils +from . import fpocket, utils, vina + name = "biobb_vs" __all__ = ["fpocket", "vina", "utils"] -__version__ = "4.2.0" +__version__ = "5.0.0" diff --git a/biobb_vs/docs/source/change_log.md b/biobb_vs/docs/source/change_log.md index eb0081f..25bc1aa 100644 --- a/biobb_vs/docs/source/change_log.md +++ b/biobb_vs/docs/source/change_log.md @@ -1,5 +1,19 @@ # Biobb Virtual Screening changelog +## What's new in version [5.0.0](https://github.com/bioexcel/biobb_vs/releases/tag/v5.0.0)? + +### Changes + +* [FIX](all): Accept lists in different formats on input properties. +* [CI/CD](env.yaml): Update biobb_common version. +* [CI/CD](linting_and_testing.yml): Update set-up micromamba. +* [CI/CD](linting_and_testing): Update GA test workflow to Python >3.9 +* [DOCS](.readthedocs.yaml): Updating to Python 3.9 +* [CI/CD](GITIGNORE): Update .gitignore to include the new file extensions to ignore +* [FEATURE](__init__): Importing submodules when a module is loaded +* [CI/CD](conf.yml): Change test conf.yml to adapt to new settings configuration +* [FEATURE] New sandbox_path property + ## What's new in version [4.2.0](https://github.com/bioexcel/biobb_vs/releases/tag/v4.2.0)? In version 4.2.0 the dependency biobb_common has been updated to 4.2.0 version. @@ -16,7 +30,7 @@ In version 4.1.2 the code has been updated for being compatible with biopython 1 * Fpocket fixed to 4.1 version. ## What's new in version [4.1.1](https://github.com/bioexcel/biobb_vs/releases/tag/v4.1.1)? -In version 4.1.1 some minor bugs have been fixed. +In version 4.1.1 some minor bugs have been fixed. ### New features @@ -30,7 +44,7 @@ In version 4.1.0 the dependency biobb_common has been updated to 4.1.0 version. * Update to biobb_common 4.1.0 (general) ## What's new in version [4.0.0](https://github.com/bioexcel/biobb_vs/releases/tag/v4.0.0)? -In version 4.0.0 the dependency biobb_common has been updated to 4.0.0 version. Also Autodock Vina has been updated from 1.1.2 to 1.2.3. +In version 4.0.0 the dependency biobb_common has been updated to 4.0.0 version. Also Autodock Vina has been updated from 1.1.2 to 1.2.3. ### New features @@ -46,35 +60,35 @@ In version 3.9.0 the dependency biobb_common has been updated to 3.9.0 version. * All inputs/outputs are checked for correct file format, extension and type (general) ## What's new in version [3.8.1](https://github.com/bioexcel/biobb_vs/releases/tag/v3.8.1)? -In version 3.8.1 the AutoDockVinaRun and FPocketRun tools have added the ability to be executed through docker. +In version 3.8.1 the AutoDockVinaRun and FPocketRun tools have added the ability to be executed through docker. ### New features * Added docker containers for AutoDockVinaRun and FPocketRun tools ## What's new in version [3.8.0](https://github.com/bioexcel/biobb_vs/releases/tag/v3.8.0)? -In version 3.8.0 the dependency biobb_common has been updated to 3.8.1 version. +In version 3.8.0 the dependency biobb_common has been updated to 3.8.1 version. ### New features * Update to biobb_common 3.8.0 (general) ## What's new in version [3.7.1](https://github.com/bioexcel/biobb_vs/releases/tag/v3.7.1)? -In version 3.7.1 some minor bugs have been fixed. +In version 3.7.1 some minor bugs have been fixed. ### Other changes * Minor bug fixes in AutoDockVinaRun ## What's new in version [3.7.0](https://github.com/bioexcel/biobb_vs/releases/tag/v3.7.0)? -In version 3.7.0 the dependency biobb_common has been updated to 3.7.0 version. +In version 3.7.0 the dependency biobb_common has been updated to 3.7.0 version. ### New features * Update to biobb_common 3.7.0 (general) ## What's new in version [3.6.0](https://github.com/bioexcel/biobb_vs/releases/tag/v3.6.0)? -In version 3.6.0 the dependency biobb_common has been updated to 3.6.0 version. +In version 3.6.0 the dependency biobb_common has been updated to 3.6.0 version. ### New features diff --git a/biobb_vs/docs/source/conf.py b/biobb_vs/docs/source/conf.py index ec01d51..c44aeab 100644 --- a/biobb_vs/docs/source/conf.py +++ b/biobb_vs/docs/source/conf.py @@ -18,26 +18,26 @@ # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.insert(0, str(Path('../../').resolve())) +sys.path.insert(0, str(Path("../../").resolve())) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +# needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.coverage', - 'sphinx.ext.mathjax', - 'sphinx.ext.ifconfig', - 'sphinx.ext.viewcode', - 'sphinx.ext.napoleon', - 'sphinx_rtd_theme', - 'recommonmark' + "sphinx.ext.autodoc", + "sphinx.ext.coverage", + "sphinx.ext.mathjax", + "sphinx.ext.ifconfig", + "sphinx.ext.viewcode", + "sphinx.ext.napoleon", + "sphinx_rtd_theme", + "recommonmark", ] # Using Google docstring style @@ -45,40 +45,39 @@ napoleon_google_docstring = True - # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # source_suffix = ['.rst', '.md'] # -- Integrate markdown --------------------------------------------------- -#source_parsers = { +# source_parsers = { # '.md': 'recommonmark.parser.CommonMarkParser', -#} +# } -source_suffix = ['.rst', '.md'] +source_suffix = [".rst", ".md"] # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = u'biobb_vs' -copyright = u'2024, Bioexcel Project' -author = u'Bioexcel Project' +project = "biobb_vs" +copyright = "2024, Bioexcel Project" +author = "Bioexcel Project" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = u'4.2.0' +version = "5.0.0" # The full version, including alpha/beta/rc tags. -release = u'4.2.0' +release = "5.0.0" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -89,37 +88,37 @@ # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = [] +exclude_patterns: list = [] # The reST default role (used for this markup: `text`) to use for all # documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False +# keep_warnings = False # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False @@ -127,162 +126,161 @@ # -- Options for HTML output ---------------------------------------------- def setup(app): - app.add_css_file('theme_overrides.css') - app.add_js_file('theme_overrides.js') + app.add_css_file("theme_overrides.css") + app.add_js_file("theme_overrides.js") # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'sphinx_rtd_theme' +html_theme = "sphinx_rtd_theme" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +# html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +# html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -#html_title = None +# html_title = None # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +# html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +# html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. -#html_extra_path = [] +# html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' +# html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +# html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True +# html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None # Language to be used for generating the HTML full-text search index. # Sphinx supports the following languages: # 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' # 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' -#html_search_language = 'en' +# html_search_language = 'en' # A dictionary with options for the search language support, empty by default. # Now only 'ja' uses this config value -#html_search_options = {'type': 'default'} +# html_search_options = {'type': 'default'} # The name of a javascript file (relative to the configuration directory) that # implements a search results scorer. If empty, the default will be used. -#html_search_scorer = 'scorer.js' +# html_search_scorer = 'scorer.js' # Output file base name for HTML help builder. -htmlhelp_basename = 'biobb_vs_doc' +htmlhelp_basename = "biobb_vs_doc" # -- Options for LaTeX output --------------------------------------------- -latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', - -# Latex figure (float) alignment -#'figure_align': 'htbp', +latex_elements: dict = { + # The paper size ('letterpaper' or 'a4paper'). + #'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + #'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + #'preamble': '', + # Latex figure (float) alignment + #'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'biobb_vs.tex', u'biobb_vs Documentation', - u'Bioexcel Project', 'manual'), + ( + master_doc, + "biobb_vs.tex", + "biobb_vs Documentation", + "Bioexcel Project", + "manual", + ), ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'biobb_vs', u'biobb_vs Documentation', - [author], 1) -] +man_pages = [(master_doc, "biobb_vs", "biobb_vs Documentation", [author], 1)] # If true, show URL addresses after external links. -#man_show_urls = False +# man_show_urls = False # -- Options for Texinfo output ------------------------------------------- @@ -291,19 +289,25 @@ def setup(app): # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'biobb_vs', u'biobb_vs Documentation', - author, 'biobb_vs', 'biobb_vs molecular dynamics ml building blocks', - 'Miscellaneous'), + ( + master_doc, + "biobb_vs", + "biobb_vs Documentation", + author, + "biobb_vs", + "biobb_vs molecular dynamics ml building blocks", + "Miscellaneous", + ), ] # Documents to append as an appendix to all manuals. -#texinfo_appendices = [] +# texinfo_appendices = [] # If false, no module index is generated. -#texinfo_domain_indices = True +# texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' +# texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False +# texinfo_no_detailmenu = False diff --git a/biobb_vs/docs/source/readme.md b/biobb_vs/docs/source/readme.md index 8b28b48..8200cee 100644 --- a/biobb_vs/docs/source/readme.md +++ b/biobb_vs/docs/source/readme.md @@ -3,7 +3,7 @@ [![](https://img.shields.io/conda/vn/bioconda/biobb_vs?label=Conda)](https://anaconda.org/bioconda/biobb_vs) [![](https://img.shields.io/conda/dn/bioconda/biobb_vs?label=Conda%20Downloads)](https://anaconda.org/bioconda/biobb_vs) [![](https://img.shields.io/badge/Docker-Quay.io-blue)](https://quay.io/repository/biocontainers/biobb_vs?tab=tags) -[![](https://img.shields.io/badge/Singularity-GalaxyProject-blue)](https://depot.galaxyproject.org/singularity/biobb_vs:4.2.0--pyhdfd78af_0) +[![](https://img.shields.io/badge/Singularity-GalaxyProject-blue)](https://depot.galaxyproject.org/singularity/biobb_vs:5.0.0--pyhdfd78af_0) [![](https://img.shields.io/badge/OS-Unix%20%7C%20MacOS-blue)](https://github.com/bioexcel/biobb_vs) [![](https://img.shields.io/pypi/pyversions/biobb-vs.svg?label=Python%20Versions)](https://pypi.org/project/biobb-vs/) @@ -42,7 +42,7 @@ The latest documentation of this package can be found in our readthedocs site: > At the time of publishing the current version, **autodock_vina has not been compiled for the new ARM mac M1/M2 chips**. So the vina.autodock_vina_run only work in these computers through docker containers. ### Version -v4.2.0 2024.1 +v5.0.0 2024.1 ### Installation Using PIP: @@ -52,7 +52,7 @@ Using PIP: * Installation: - pip install "biobb_vs>=4.2.0" + pip install "biobb_vs>=5.0.0" * Usage: [Python API documentation](https://biobb-vs.readthedocs.io/en/latest/modules.html) @@ -62,7 +62,7 @@ Using ANACONDA: * Installation: - conda install -c bioconda "biobb_vs>=4.2.0" + conda install -c bioconda "biobb_vs>=5.0.0" * Usage: With conda installation BioBBs can be used with the [Python API documentation](https://biobb-vs.readthedocs.io/en/latest/modules.html) and the [Command Line documentation](https://biobb-vs.readthedocs.io/en/latest/command_line.html) @@ -72,13 +72,13 @@ Using DOCKER: * Installation: - docker pull quay.io/biocontainers/biobb_vs:4.2.0--pyhdfd78af_0 + docker pull quay.io/biocontainers/biobb_vs:5.0.0--pyhdfd78af_0 * Usage: - docker run quay.io/biocontainers/biobb_vs:4.2.0--pyhdfd78af_0 + docker run quay.io/biocontainers/biobb_vs:5.0.0--pyhdfd78af_0 Using SINGULARITY: @@ -87,7 +87,7 @@ Using SINGULARITY: * Installation: - singularity pull --name biobb_vs.sif https://depot.galaxyproject.org/singularity/biobb_vs:4.2.0--pyhdfd78af_0 + singularity pull --name biobb_vs.sif https://depot.galaxyproject.org/singularity/biobb_vs:5.0.0--pyhdfd78af_0 * Usage: diff --git a/biobb_vs/docs/source/schema.html b/biobb_vs/docs/source/schema.html index 98314ea..7a23ad6 100644 --- a/biobb_vs/docs/source/schema.html +++ b/biobb_vs/docs/source/schema.html @@ -10,7 +10,7 @@ "applicationSubCategory": "http://www.edamontology.org/topic_3892", "citation": "https://www.nature.com/articles/s41597-019-0177-4", "license": "https://www.apache.org/licenses/LICENSE-2.0", - "softwareVersion": "4.2.0", + "softwareVersion": "5.0.0", "applicationSuite": "BioBB BioExcel Building Blocks", "codeRepository": "https://github.com/bioexcel/biobb_vs", "isAccessibleForFree": "True", diff --git a/biobb_vs/json_schemas/biobb_vs.json b/biobb_vs/json_schemas/biobb_vs.json index db29668..b676a95 100644 --- a/biobb_vs/json_schemas/biobb_vs.json +++ b/biobb_vs/json_schemas/biobb_vs.json @@ -4,87 +4,87 @@ "github": "https://github.com/bioexcel/biobb_vs", "readthedocs": "https://biobb-vs.readthedocs.io/en/latest/", "conda": "https://anaconda.org/bioconda/biobb_vs", - "docker": "https://quay.io/biocontainers/biobb_vs:4.2.0--pyhdfd78af_0", - "singularity": "https://depot.galaxyproject.org/singularity/biobb_vs:4.2.0--pyhdfd78af_0", - "version": "4.2.0", + "docker": "https://quay.io/biocontainers/biobb_vs:5.0.0--pyhdfd78af_0", + "singularity": "https://depot.galaxyproject.org/singularity/biobb_vs:5.0.0--pyhdfd78af_0", + "version": "5.0.0", "rest": true, - "tools" : [ + "tools": [ { - "block" : "AutoDockVinaRun", - "tool" : "AutoDock Vina", - "desc" : "Wrapper of the AutoDock Vina software.", - "exec" : "autodock_vina_run", + "block": "AutoDockVinaRun", + "tool": "AutoDock Vina", + "desc": "Wrapper of the AutoDock Vina software.", + "exec": "autodock_vina_run", "docs": "https://biobb-vs.readthedocs.io/en/latest/vina.html#module-vina.autodock_vina_run", "rest": true }, { - "block" : "BindingSite", - "tool" : "in house using biopython", - "desc" : "This class finds the binding site of the input_pdb.", - "exec" : "bindingsite", + "block": "BindingSite", + "tool": "in house using biopython", + "desc": "This class finds the binding site of the input_pdb.", + "exec": "bindingsite", "docs": "https://biobb-vs.readthedocs.io/en/latest/utils.html#module-utils.bindingsite", "rest": true }, { - "block" : "Box", - "tool" : "in house", - "desc" : "This class sets the center and the size of a rectangular parallelepiped box around a set of residues or a pocket.", - "exec" : "box", + "block": "Box", + "tool": "in house", + "desc": "This class sets the center and the size of a rectangular parallelepiped box around a set of residues or a pocket.", + "exec": "box", "docs": "https://biobb-vs.readthedocs.io/en/latest/utils.html#module-utils.box", "rest": true }, { - "block" : "BoxResidues", - "tool" : "in house using biopython", - "desc" : "This class sets the center and the size of a rectangular parallelepiped box around a set of residues.", - "exec" : "box_residues", + "block": "BoxResidues", + "tool": "in house using biopython", + "desc": "This class sets the center and the size of a rectangular parallelepiped box around a set of residues.", + "exec": "box_residues", "docs": "https://biobb-vs.readthedocs.io/en/latest/utils.html#module-utils.box_residues", "rest": true }, { - "block" : "ExtractModelPDBQT", - "tool" : "in house using biopython", - "desc" : "Extracts a model from a PDBQT file with several models.", - "exec" : "extract_model_pdbqt", + "block": "ExtractModelPDBQT", + "tool": "in house using biopython", + "desc": "Extracts a model from a PDBQT file with several models.", + "exec": "extract_model_pdbqt", "docs": "https://biobb-vs.readthedocs.io/en/latest/utils.html#module-utils.extract_model_pdbqt", "rest": true }, { - "block" : "FPocketRun", - "tool" : "fpocket", - "desc" : "Wrapper of the fpocket software for finding the binding sites of a structure.", - "exec" : "fpocket_run", + "block": "FPocketRun", + "tool": "fpocket", + "desc": "Wrapper of the fpocket software for finding the binding sites of a structure.", + "exec": "fpocket_run", "docs": "https://biobb-vs.readthedocs.io/en/latest/fpocket.html#module-fpocket.fpocket_run", "rest": true }, { - "block" : "FPocketFilter", - "tool" : "in house", - "desc" : "Performs a search over the outputs of the fpocket building block.", - "exec" : "fpocket_filter", + "block": "FPocketFilter", + "tool": "in house", + "desc": "Performs a search over the outputs of the fpocket building block.", + "exec": "fpocket_filter", "docs": "https://biobb-vs.readthedocs.io/en/latest/fpocket.html#module-fpocket.fpocket_filter", "rest": true }, { - "block" : "FPocketSelect", - "tool" : "in house", - "desc" : "Selects a single pocket in the outputs of the fpocket building block..", - "exec" : "fpocket_select", + "block": "FPocketSelect", + "tool": "in house", + "desc": "Selects a single pocket in the outputs of the fpocket building block..", + "exec": "fpocket_select", "docs": "https://biobb-vs.readthedocs.io/en/latest/fpocket.html#module-fpocket.fpocket_select", "rest": true } ], - "dep_pypi" : [ - "install_requires=['biobb_common==4.2.0']", - "python_requires='>=3.8'" - ], - "dep_conda" : [ - "python >=3.8", - "biobb_common ==4.2.0", + "dep_pypi": [ + "install_requires=['biobb_common==5.0.0']", + "python_requires='>=3.9'" + ], + "dep_conda": [ + "python >=3.9", + "biobb_common ==5.0.0", "vina ==1.2.3", "fpocket ==4.1" ], - "keywords" : [ + "keywords": [ "virtual screening", "autodock", "vina", diff --git a/biobb_vs/utils/__init__.py b/biobb_vs/utils/__init__.py index c37edcf..7a67531 100644 --- a/biobb_vs/utils/__init__.py +++ b/biobb_vs/utils/__init__.py @@ -1,6 +1,4 @@ -from . import bindingsite -from . import box -from . import box_residues -from . import extract_model_pdbqt +from . import bindingsite, box, box_residues, extract_model_pdbqt + name = "utils" __all__ = ["bindingsite", "box", "box_residues", "extract_model_pdbqt"] diff --git a/biobb_vs/utils/bindingsite.py b/biobb_vs/utils/bindingsite.py index ce849d3..069ab8e 100755 --- a/biobb_vs/utils/bindingsite.py +++ b/biobb_vs/utils/bindingsite.py @@ -1,27 +1,37 @@ #!/usr/bin/env python3 """Module containing the BindingSite class and the command line interface.""" + import argparse -from typing import Optional import re +import warnings from pathlib import PurePath -from biobb_common.generic.biobb_object import BiobbObject +from typing import Optional + +from Bio import BiopythonDeprecationWarning from biobb_common.configuration import settings +from biobb_common.generic.biobb_object import BiobbObject from biobb_common.tools import file_utils as fu from biobb_common.tools.file_utils import launchlogger -from biobb_vs.utils.common import check_input_path, check_output_path, get_pdb_sequence, get_ligand_residues, align_sequences, calculate_alignment_identity, get_residue_by_id -from Bio import BiopythonDeprecationWarning -import warnings +from biobb_vs.utils.common import ( + align_sequences, + calculate_alignment_identity, + check_input_path, + check_output_path, + get_ligand_residues, + get_pdb_sequence, + get_residue_by_id, +) + with warnings.catch_warnings(): warnings.simplefilter("ignore", BiopythonDeprecationWarning) - import Bio.PDB - import Bio.pairwise2 # try: # import Bio.SubsMat.MatrixInfo # except ImportError: - import Bio.Align.substitution_matrices + import Bio.pairwise2 + import Bio.PDB class BindingSite(BiobbObject): @@ -73,8 +83,14 @@ class BindingSite(BiobbObject): """ - def __init__(self, input_pdb_path, input_clusters_zip, output_pdb_path, - properties=None, **kwargs) -> None: + def __init__( + self, + input_pdb_path, + input_clusters_zip, + output_pdb_path, + properties=None, + **kwargs, + ) -> None: properties = properties or {} # Call parent class constructor @@ -83,17 +99,20 @@ def __init__(self, input_pdb_path, input_clusters_zip, output_pdb_path, # Input/Output files self.io_dict = { - "in": {"input_pdb_path": input_pdb_path, "input_clusters_zip": input_clusters_zip}, - "out": {"output_pdb_path": output_pdb_path} + "in": { + "input_pdb_path": input_pdb_path, + "input_clusters_zip": input_clusters_zip, + }, + "out": {"output_pdb_path": output_pdb_path}, } # Properties specific for BB - self.ligand = properties.get('ligand', None) - self.radius = float(properties.get('radius', 5.0)) - self.max_num_ligands = properties.get('max_num_ligands', 15) - self.matrix_name = properties.get('matrix_name', 'BLOSUM62') - self.gap_open = properties.get('gap_open', -10.0) - self.gap_extend = properties.get('gap_extend', -0.5) + self.ligand = properties.get("ligand", None) + self.radius = float(properties.get("radius", 5.0)) + self.max_num_ligands = properties.get("max_num_ligands", 15) + self.matrix_name = properties.get("matrix_name", "BLOSUM62") + self.gap_open = properties.get("gap_open", -10.0) + self.gap_extend = properties.get("gap_extend", -0.5) self.properties = properties # Check the properties @@ -101,10 +120,26 @@ def __init__(self, input_pdb_path, input_clusters_zip, output_pdb_path, self.check_arguments() def check_data_params(self, out_log, err_log): - """ Checks all the input/output paths and parameters """ - self.io_dict["in"]["input_pdb_path"] = check_input_path(self.io_dict["in"]["input_pdb_path"], "input_pdb_path", self.out_log, self.__class__.__name__) - self.io_dict["in"]["input_clusters_zip"] = check_input_path(self.io_dict["in"]["input_clusters_zip"], "input_clusters_zip", self.out_log, self.__class__.__name__) - self.io_dict["out"]["output_pdb_path"] = check_output_path(self.io_dict["out"]["output_pdb_path"], "output_pdb_path", False, self.out_log, self.__class__.__name__) + """Checks all the input/output paths and parameters""" + self.io_dict["in"]["input_pdb_path"] = check_input_path( + self.io_dict["in"]["input_pdb_path"], + "input_pdb_path", + self.out_log, + self.__class__.__name__, + ) + self.io_dict["in"]["input_clusters_zip"] = check_input_path( + self.io_dict["in"]["input_clusters_zip"], + "input_clusters_zip", + self.out_log, + self.__class__.__name__, + ) + self.io_dict["out"]["output_pdb_path"] = check_output_path( + self.io_dict["out"]["output_pdb_path"], + "output_pdb_path", + False, + self.out_log, + self.__class__.__name__, + ) @launchlogger def launch(self) -> int: @@ -119,10 +154,16 @@ def launch(self) -> int: self.stage_files() # Parse structure - fu.log('Loading input PDB structure %s' % (self.io_dict["in"]["input_pdb_path"]), self.out_log, self.global_log) + fu.log( + "Loading input PDB structure %s" % (self.io_dict["in"]["input_pdb_path"]), + self.out_log, + self.global_log, + ) structure_name = PurePath(self.io_dict["in"]["input_pdb_path"]).name parser = Bio.PDB.PDBParser(QUIET=True) - structPDB = parser.get_structure(structure_name, self.io_dict["in"]["input_pdb_path"]) + structPDB = parser.get_structure( + structure_name, self.io_dict["in"]["input_pdb_path"] + ) if len(structPDB): structPDB = structPDB[0] @@ -130,7 +171,11 @@ def launch(self) -> int: # Use only one chain n_chains = structPDB.get_list() if len(n_chains) != 1: - fu.log('More than one chain found in the input PDB structure. Using only the first chain to find the binding site', self.out_log, self.global_log) + fu.log( + "More than one chain found in the input PDB structure. Using only the first chain to find the binding site", + self.out_log, + self.global_log, + ) # get first chain in case there is more than one chain for struct_chain in structPDB.get_chains(): structPDB = struct_chain @@ -138,42 +183,66 @@ def launch(self) -> int: # Get AA sequence structPDB_seq = get_pdb_sequence(structPDB) if len(structPDB_seq) == 0: - fu.log(self.__class__.__name__ + ': Cannot extract AA sequence from the input PDB structure %s. Wrong format?' % self.io_dict["in"]["input_pdb_path"], self.out_log) - raise SystemExit(self.__class__.__name__ + ': Cannot extract AA sequence from the input PDB structure %s. Wrong format?' % self.io_dict["in"]["input_pdb_path"]) + fu.log( + self.__class__.__name__ + + ": Cannot extract AA sequence from the input PDB structure %s. Wrong format?" + % self.io_dict["in"]["input_pdb_path"], + self.out_log, + ) + raise SystemExit( + self.__class__.__name__ + + ": Cannot extract AA sequence from the input PDB structure %s. Wrong format?" + % self.io_dict["in"]["input_pdb_path"] + ) else: - fu.log('Found %s residues in %s' % (len(structPDB_seq), self.io_dict["in"]["input_pdb_path"]), self.out_log) + fu.log( + "Found %s residues in %s" + % (len(structPDB_seq), self.io_dict["in"]["input_pdb_path"]), + self.out_log, + ) # create temporary folder for decompressing the input_clusters_zip file unique_dir = PurePath(fu.create_unique_dir()) - fu.log('Creating %s temporary folder' % unique_dir, self.out_log, self.global_log) + fu.log( + "Creating %s temporary folder" % unique_dir, self.out_log, self.global_log + ) # decompress the input_clusters_zip file - cluster_list = fu.unzip_list(zip_file=self.io_dict["in"]["input_clusters_zip"], dest_dir=unique_dir, out_log=self.out_log) + cluster_list = fu.unzip_list( + zip_file=self.io_dict["in"]["input_clusters_zip"], + dest_dir=str(unique_dir), + out_log=self.out_log, + ) clusterPDB_ligands_aligned = [] clusterPDB_ligands_num = 0 - fu.log('Iterating on all clusters:', self.out_log) + fu.log("Iterating on all clusters:", self.out_log) for idx, cluster_path in enumerate(cluster_list): - cluster_name = PurePath(cluster_path).stem - fu.log(' ', self.out_log) - fu.log('------------ Iteration #%s --------------' % (idx + 1), self.out_log) - fu.log('Cluster member: %s' % cluster_name, self.out_log) + fu.log(" ", self.out_log) + fu.log( + "------------ Iteration #%s --------------" % (idx + 1), self.out_log + ) + fu.log("Cluster member: %s" % cluster_name, self.out_log) # Load and Parse PDB clusterPDB = {} clusterPDB = parser.get_structure(cluster_name, cluster_path)[0] # Use only the first chain - for cluster_chain in clusterPDB.get_chains(): + for cluster_chain in clusterPDB.get_chains(): # type: ignore clusterPDB = cluster_chain # Looking for ligands clusterPDB_ligands = get_ligand_residues(clusterPDB) if (len(clusterPDB_ligands)) == 0: - fu.log('No ligands found that could guide the binding site search. Ignoring this member: %s' % cluster_name, self.out_log) + fu.log( + "No ligands found that could guide the binding site search. Ignoring this member: %s" + % cluster_name, + self.out_log, + ) continue # Selecting the largest ligand, if more than one @@ -185,15 +254,27 @@ def launch(self) -> int: if lig.get_resname() == self.ligand: clusterPDB_ligand = lig lig_atoms_num = len(lig.get_list()) - fu.log('Ligand found: %s (%s atoms)' % (lig.get_resname(), lig_atoms_num), self.out_log) + fu.log( + "Ligand found: %s (%s atoms)" + % (lig.get_resname(), lig_atoms_num), + self.out_log, + ) else: - fu.log('Ligand %s not found in %s cluster member, skipping this cluster' % (self.ligand, cluster_name), self.out_log) + fu.log( + "Ligand %s not found in %s cluster member, skipping this cluster" + % (self.ligand, cluster_name), + self.out_log, + ) continue else: if len(clusterPDB_ligands) > 1: for lig_res in clusterPDB_ligands: lig_res_atoms_num = len(lig_res.get_list()) - fu.log('Ligand found: %s (%s atoms)' % (lig_res.get_resname(), lig_res_atoms_num), self.out_log) + fu.log( + "Ligand found: %s (%s atoms)" + % (lig_res.get_resname(), lig_res_atoms_num), + self.out_log, + ) if lig_res_atoms_num > lig_atoms_num: clusterPDB_ligand = lig_res lig_atoms_num = lig_res_atoms_num @@ -201,7 +282,11 @@ def launch(self) -> int: clusterPDB_ligand = clusterPDB_ligands[0] lig_atoms_num = len(clusterPDB_ligands[0].get_list()) - fu.log('Member accepted. Valid ligand found: %s (%s atoms)' % (clusterPDB_ligand.get_resname(), lig_atoms_num), self.out_log) + fu.log( + "Member accepted. Valid ligand found: %s (%s atoms)" + % (clusterPDB_ligand.get_resname(), lig_atoms_num), # type: ignore + self.out_log, + ) # Mapping residues by sequence alignment to match structPDB-clusterPDB paired residues @@ -209,13 +294,25 @@ def launch(self) -> int: clusterPDB_seq = get_pdb_sequence(clusterPDB) # Pairwise align - aln, residue_map = align_sequences(structPDB_seq, clusterPDB_seq, self.matrix_name, self.gap_open, self.gap_extend) - fu.log('Matching residues to input PDB structure. Alignment is:\n%s' % (aln[1]), self.out_log) + aln, residue_map = align_sequences( + structPDB_seq, + clusterPDB_seq, + self.matrix_name, + self.gap_open, + self.gap_extend, + ) + fu.log( + "Matching residues to input PDB structure. Alignment is:\n%s" + % (aln[1]), + self.out_log, + ) # Calculate (gapless) sequence identity - seq_identity, gap_seq_identity = calculate_alignment_identity(aln[0], aln[1]) - fu.log('Sequence identity (%%): %s' % (seq_identity), self.out_log) - fu.log('Gap less identity (%%): %s' % (gap_seq_identity), self.out_log) + seq_identity, gap_seq_identity = calculate_alignment_identity( + aln[0], aln[1] + ) + fu.log("Sequence identity (%%): %s" % (seq_identity), self.out_log) + fu.log("Gap less identity (%%): %s" % (gap_seq_identity), self.out_log) # Selecting aligned CA atoms from first model, first chain @@ -224,28 +321,47 @@ def launch(self) -> int: for struct_res in residue_map: try: - cluster_atoms.append(clusterPDB[residue_map[struct_res]]['CA']) - struct_atoms.append(get_residue_by_id(structPDB, struct_res)['CA']) + cluster_atoms.append(clusterPDB[residue_map[struct_res]]["CA"]) + struct_atoms.append(get_residue_by_id(structPDB, struct_res)["CA"]) except KeyError: - fu.log('Cannot find CA atom for residue %s (input PDB %s)' % (get_residue_by_id(structPDB, struct_res).get_resname(), struct_res), self.out_log) + fu.log( + "Cannot find CA atom for residue %s (input PDB %s)" + % ( + get_residue_by_id(structPDB, struct_res).get_resname(), + struct_res, + ), + self.out_log, + ) pass if len(cluster_atoms) == 0: - fu.log(self.__class__.__name__ + ': Cannot find CA atoms (1st model, 1st chain) in cluster member %s when aligning against %s. Ignoring this member.' % (cluster_name, structure_name), self.out_log) - raise SystemExit(self.__class__.__name__ + ': Cannot find CA atoms (1st model, 1st chain) in cluster member %s when aligning against %s. Ignoring this member.' % (cluster_name, structure_name)) + fu.log( + self.__class__.__name__ + + ": Cannot find CA atoms (1st model, 1st chain) in cluster member %s when aligning against %s. Ignoring this member." + % (cluster_name, structure_name), + self.out_log, + ) + raise SystemExit( + self.__class__.__name__ + + ": Cannot find CA atoms (1st model, 1st chain) in cluster member %s when aligning against %s. Ignoring this member." + % (cluster_name, structure_name) + ) else: - fu.log('Superimposing %s aligned protein residues' % (len(cluster_atoms)), self.out_log) + fu.log( + "Superimposing %s aligned protein residues" % (len(cluster_atoms)), + self.out_log, + ) # Align against input structure si = Bio.PDB.Superimposer() si.set_atoms(struct_atoms, cluster_atoms) - si.apply(clusterPDB.get_atoms()) - fu.log('RMSD: %s' % (si.rms), self.out_log) + si.apply(clusterPDB.get_atoms()) # type: ignore + fu.log("RMSD: %s" % (si.rms), self.out_log) # Save transformed structure (and ligand) - clusterPDB_ligand_aligned = clusterPDB[clusterPDB_ligand.get_id()] - fu.log('Saving transformed ligand coordinates', self.out_log) + clusterPDB_ligand_aligned = clusterPDB[clusterPDB_ligand.get_id()] # type: ignore + fu.log("Saving transformed ligand coordinates", self.out_log) clusterPDB_ligands_aligned.append(clusterPDB_ligand_aligned) @@ -256,17 +372,26 @@ def launch(self) -> int: if clusterPDB_ligands_num > self.max_num_ligands: break - fu.log(' ', self.out_log) - fu.log('----------------------------------------', self.out_log) - fu.log('All transformed ligand coordinates saved, getting binding site residues', self.out_log) + fu.log(" ", self.out_log) + fu.log("----------------------------------------", self.out_log) + fu.log( + "All transformed ligand coordinates saved, getting binding site residues", + self.out_log, + ) # Select binding site atoms as those around cluster superimposed ligands - fu.log('Defining binding site residues as those %sÅ around the %s cluster superimposed ligands' % (self.radius, clusterPDB_ligands_num), self.out_log) + fu.log( + "Defining binding site residues as those %sÅ around the %s cluster superimposed ligands" + % (self.radius, clusterPDB_ligands_num), + self.out_log, + ) # select Atoms from aligned ligands clusterPDB_ligands_aligned2 = [res for res in clusterPDB_ligands_aligned] - clusterPDB_ligands_aligned_atoms = Bio.PDB.Selection.unfold_entities(clusterPDB_ligands_aligned2, 'A') + clusterPDB_ligands_aligned_atoms = Bio.PDB.Selection.unfold_entities( + clusterPDB_ligands_aligned2, "A" + ) # select Atoms from input PDB structure structPDB_atoms = [atom for atom in structPDB.get_atoms()] @@ -276,18 +401,22 @@ def launch(self) -> int: structPDB_neighbors = Bio.PDB.NeighborSearch(structPDB_atoms) for ligand_atom in clusterPDB_ligands_aligned_atoms: # look for PDB atoms 5A around each ligand atom - k_l = structPDB_neighbors.search(ligand_atom.coord, self.radius, 'R') + k_l = structPDB_neighbors.search(ligand_atom.coord, self.radius, "R") for k in k_l: structPDB_bs_residues_raw[k.get_id()] = k.get_full_id() # Save binding site to PDB io = Bio.PDB.PDBIO() - fu.log('Writing binding site residues into %s' % (self.io_dict["out"]["output_pdb_path"]), self.out_log) + fu.log( + "Writing binding site residues into %s" + % (self.io_dict["out"]["output_pdb_path"]), + self.out_log, + ) # unselect input PDB atoms not in binding site structPDB_bs_atoms = 0 - p = re.compile('H_|W_|W') + p = re.compile("H_|W_|W") residue_ids_to_remove = [] for res in structPDB.get_residues(): if res.id not in structPDB_bs_residues_raw.keys(): @@ -312,10 +441,9 @@ def launch(self) -> int: # Copy files to host self.copy_to_host() - self.tmp_files.extend([ - self.stage_io_dict.get("unique_dir", ""), - str(unique_dir) - ]) + self.tmp_files.extend( + [self.stage_io_dict.get("unique_dir", ""), str(unique_dir)] + ) self.remove_tmp_files() self.check_arguments(output_files_created=True, raise_exception=False) @@ -323,37 +451,63 @@ def launch(self) -> int: return 0 -def bindingsite(input_pdb_path: str, input_clusters_zip: str, output_pdb_path: str, properties: Optional[dict] = None, **kwargs) -> int: +def bindingsite( + input_pdb_path: str, + input_clusters_zip: str, + output_pdb_path: str, + properties: Optional[dict] = None, + **kwargs, +) -> int: """Execute the :class:`BindingSite ` class and execute the :meth:`launch() ` method.""" - return BindingSite(input_pdb_path=input_pdb_path, - input_clusters_zip=input_clusters_zip, - output_pdb_path=output_pdb_path, - properties=properties, **kwargs).launch() + return BindingSite( + input_pdb_path=input_pdb_path, + input_clusters_zip=input_clusters_zip, + output_pdb_path=output_pdb_path, + properties=properties, + **kwargs, + ).launch() def main(): """Command line execution of this building block. Please check the command line documentation.""" - parser = argparse.ArgumentParser(description="Finds the binding site of the input_pdb file based on the ligands' location of similar structures (members of the sequence identity cluster)", formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, width=99999)) - parser.add_argument('--config', required=False, help='Configuration file') + parser = argparse.ArgumentParser( + description="Finds the binding site of the input_pdb file based on the ligands' location of similar structures (members of the sequence identity cluster)", + formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, width=99999), + ) + parser.add_argument("--config", required=False, help="Configuration file") # Specific args of each building block - required_args = parser.add_argument_group('required arguments') - required_args.add_argument('--input_pdb_path', required=True, help='Path to the PDB structure where the binding site is to be found. Accepted formats: pdb.') - required_args.add_argument('--input_clusters_zip', required=True, help='Path to the ZIP file with all the PDB members of the identity cluster. Accepted formats: zip.') - required_args.add_argument('--output_pdb_path', required=True, help='Path to the PDB containig the residues belonging to the binding site. Accepted formats: pdb.') + required_args = parser.add_argument_group("required arguments") + required_args.add_argument( + "--input_pdb_path", + required=True, + help="Path to the PDB structure where the binding site is to be found. Accepted formats: pdb.", + ) + required_args.add_argument( + "--input_clusters_zip", + required=True, + help="Path to the ZIP file with all the PDB members of the identity cluster. Accepted formats: zip.", + ) + required_args.add_argument( + "--output_pdb_path", + required=True, + help="Path to the PDB containig the residues belonging to the binding site. Accepted formats: pdb.", + ) args = parser.parse_args() args.config = args.config or "{}" properties = settings.ConfReader(config=args.config).get_prop_dic() # Specific call of each building block - bindingsite(input_pdb_path=args.input_pdb_path, - input_clusters_zip=args.input_clusters_zip, - output_pdb_path=args.output_pdb_path, - properties=properties) + bindingsite( + input_pdb_path=args.input_pdb_path, + input_clusters_zip=args.input_clusters_zip, + output_pdb_path=args.output_pdb_path, + properties=properties, + ) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/biobb_vs/utils/box.py b/biobb_vs/utils/box.py index c900dd4..6de1bed 100755 --- a/biobb_vs/utils/box.py +++ b/biobb_vs/utils/box.py @@ -1,15 +1,22 @@ #!/usr/bin/env python3 """Module containing the Box class and the command line interface.""" + import argparse +from pathlib import PurePath from typing import Optional + import numpy as np -from pathlib import PurePath -from biobb_common.generic.biobb_object import BiobbObject from biobb_common.configuration import settings +from biobb_common.generic.biobb_object import BiobbObject from biobb_common.tools import file_utils as fu from biobb_common.tools.file_utils import launchlogger -from biobb_vs.utils.common import check_input_path, check_output_path, get_box_coordinates + +from biobb_vs.utils.common import ( + check_input_path, + check_output_path, + get_box_coordinates, +) class Box(BiobbObject): @@ -50,8 +57,9 @@ class Box(BiobbObject): """ - def __init__(self, input_pdb_path, output_pdb_path, - properties=None, **kwargs) -> None: + def __init__( + self, input_pdb_path, output_pdb_path, properties=None, **kwargs + ) -> None: properties = properties or {} # Call parent class constructor @@ -61,12 +69,12 @@ def __init__(self, input_pdb_path, output_pdb_path, # Input/Output files self.io_dict = { "in": {"input_pdb_path": input_pdb_path}, - "out": {"output_pdb_path": output_pdb_path} + "out": {"output_pdb_path": output_pdb_path}, } # Properties specific for BB - self.offset = float(properties.get('offset', 2.0)) - self.box_coordinates = float(properties.get('box_coordinates', False)) + self.offset = float(properties.get("offset", 2.0)) + self.box_coordinates = float(properties.get("box_coordinates", False)) self.properties = properties # Check the properties @@ -74,9 +82,20 @@ def __init__(self, input_pdb_path, output_pdb_path, self.check_arguments() def check_data_params(self, out_log, err_log): - """ Checks all the input/output paths and parameters """ - self.io_dict["in"]["input_pdb_path"] = check_input_path(self.io_dict["in"]["input_pdb_path"], "input_pdb_path", self.out_log, self.__class__.__name__) - self.io_dict["out"]["output_pdb_path"] = check_output_path(self.io_dict["out"]["output_pdb_path"], "output_pdb_path", False, self.out_log, self.__class__.__name__) + """Checks all the input/output paths and parameters""" + self.io_dict["in"]["input_pdb_path"] = check_input_path( + self.io_dict["in"]["input_pdb_path"], + "input_pdb_path", + self.out_log, + self.__class__.__name__, + ) + self.io_dict["out"]["output_pdb_path"] = check_output_path( + self.io_dict["out"]["output_pdb_path"], + "output_pdb_path", + False, + self.out_log, + self.__class__.__name__, + ) @launchlogger def launch(self) -> int: @@ -91,11 +110,21 @@ def launch(self) -> int: self.stage_files() # check if cavity (pdb) or pocket (pqr) - input_type = PurePath(self.io_dict["in"]["input_pdb_path"]).suffix.lstrip('.') - if input_type == 'pdb': - fu.log('Loading residue PDB selection from %s' % (self.io_dict["in"]["input_pdb_path"]), self.out_log, self.global_log) + input_type = PurePath(self.io_dict["in"]["input_pdb_path"]).suffix.lstrip(".") + if input_type == "pdb": + fu.log( + "Loading residue PDB selection from %s" + % (self.io_dict["in"]["input_pdb_path"]), + self.out_log, + self.global_log, + ) else: - fu.log('Loading pocket PQR selection from %s' % (self.io_dict["in"]["input_pdb_path"]), self.out_log, self.global_log) + fu.log( + "Loading pocket PQR selection from %s" + % (self.io_dict["in"]["input_pdb_path"]), + self.out_log, + self.global_log, + ) # get input_pdb_path atoms coordinates selection_atoms_num = 0 @@ -113,43 +142,80 @@ def launch(self) -> int: # Compute binding site box size # compute box center - selection_box_center = [np.average(x_coordslist), np.average(y_coordslist), np.average(z_coordslist)] - fu.log('Binding site center (Angstroms): %10.3f%10.3f%10.3f' % (selection_box_center[0], selection_box_center[1], selection_box_center[2]), self.out_log, self.global_log) + selection_box_center = [ + np.average(x_coordslist), + np.average(y_coordslist), + np.average(z_coordslist), + ] + fu.log( + "Binding site center (Angstroms): %10.3f%10.3f%10.3f" + % ( + selection_box_center[0], + selection_box_center[1], + selection_box_center[2], + ), + self.out_log, + self.global_log, + ) # compute box size - selection_coords_max = np.amax([x_coordslist, y_coordslist, z_coordslist], axis=1) + selection_coords_max = np.amax( + [x_coordslist, y_coordslist, z_coordslist], axis=1 + ) selection_box_size = selection_coords_max - selection_box_center if self.offset: - fu.log('Adding %.1f Angstroms offset' % (self.offset), self.out_log, self.global_log) + fu.log( + "Adding %.1f Angstroms offset" % (self.offset), + self.out_log, + self.global_log, + ) selection_box_size = [c + self.offset for c in selection_box_size] - fu.log('Binding site size (Angstroms): %10.3f%10.3f%10.3f' % (selection_box_size[0], selection_box_size[1], selection_box_size[2]), self.out_log, self.global_log) + fu.log( + "Binding site size (Angstroms): %10.3f%10.3f%10.3f" + % (selection_box_size[0], selection_box_size[1], selection_box_size[2]), + self.out_log, + self.global_log, + ) # compute volume vol = np.prod(selection_box_size) * 2**3 - fu.log('Volume (cubic Angstroms): %.0f' % (vol), self.out_log, self.global_log) + fu.log("Volume (cubic Angstroms): %.0f" % (vol), self.out_log, self.global_log) # add box details as PDB remarks - remarks = "REMARK BOX CENTER:%10.3f%10.3f%10.3f" % (selection_box_center[0], selection_box_center[1], selection_box_center[2]) - remarks += " SIZE:%10.3f%10.3f%10.3f" % (selection_box_size[0], selection_box_size[1], selection_box_size[2]) + remarks = "REMARK BOX CENTER:%10.3f%10.3f%10.3f" % ( + selection_box_center[0], + selection_box_center[1], + selection_box_center[2], + ) + remarks += " SIZE:%10.3f%10.3f%10.3f" % ( + selection_box_size[0], + selection_box_size[1], + selection_box_size[2], + ) selection_box_coords_txt = "" # add (optional) box coordinates as 8 ATOM records if self.box_coordinates: - fu.log('Adding box coordinates', self.out_log, self.global_log) - selection_box_coords_txt = get_box_coordinates(selection_box_center, selection_box_size) + fu.log("Adding box coordinates", self.out_log, self.global_log) + selection_box_coords_txt = get_box_coordinates( + selection_box_center, selection_box_size + ) - with open(self.io_dict["out"]["output_pdb_path"], 'w') as f: + with open(self.io_dict["out"]["output_pdb_path"], "w") as f: f.seek(0, 0) - f.write(remarks.rstrip('\r\n') + '\n' + selection_box_coords_txt) + f.write(remarks.rstrip("\r\n") + "\n" + selection_box_coords_txt) - fu.log('Saving output PDB file (with box setting annotations): %s' % (self.io_dict["out"]["output_pdb_path"]), self.out_log, self.global_log) + fu.log( + "Saving output PDB file (with box setting annotations): %s" + % (self.io_dict["out"]["output_pdb_path"]), + self.out_log, + self.global_log, + ) # Copy files to host self.copy_to_host() - self.tmp_files.extend([ - self.stage_io_dict.get("unique_dir", "") - ]) + self.tmp_files.extend([self.stage_io_dict.get("unique_dir", "")]) self.remove_tmp_files() self.check_arguments(output_files_created=True, raise_exception=False) @@ -157,34 +223,55 @@ def launch(self) -> int: return 0 -def box(input_pdb_path: str, output_pdb_path: str, properties: Optional[dict] = None, **kwargs) -> int: +def box( + input_pdb_path: str, + output_pdb_path: str, + properties: Optional[dict] = None, + **kwargs, +) -> int: """Execute the :class:`Box ` class and execute the :meth:`launch() ` method.""" - return Box(input_pdb_path=input_pdb_path, - output_pdb_path=output_pdb_path, - properties=properties, **kwargs).launch() + return Box( + input_pdb_path=input_pdb_path, + output_pdb_path=output_pdb_path, + properties=properties, + **kwargs, + ).launch() def main(): """Command line execution of this building block. Please check the command line documentation.""" - parser = argparse.ArgumentParser(description="Sets the center and the size of a rectangular parallelepiped box around a set of residues from a given PDB or a pocket from a given PQR.", formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, width=99999)) - parser.add_argument('--config', required=False, help='Configuration file') + parser = argparse.ArgumentParser( + description="Sets the center and the size of a rectangular parallelepiped box around a set of residues from a given PDB or a pocket from a given PQR.", + formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, width=99999), + ) + parser.add_argument("--config", required=False, help="Configuration file") # Specific args of each building block - required_args = parser.add_argument_group('required arguments') - required_args.add_argument('--input_pdb_path', required=True, help='PDB file containing a selection of residue numbers or PQR file containing the pocket. Accepted formats: pdb, pqr.') - required_args.add_argument('--output_pdb_path', required=True, help='PDB including the annotation of the box center and size as REMARKs. Accepted formats: pdb.') + required_args = parser.add_argument_group("required arguments") + required_args.add_argument( + "--input_pdb_path", + required=True, + help="PDB file containing a selection of residue numbers or PQR file containing the pocket. Accepted formats: pdb, pqr.", + ) + required_args.add_argument( + "--output_pdb_path", + required=True, + help="PDB including the annotation of the box center and size as REMARKs. Accepted formats: pdb.", + ) args = parser.parse_args() args.config = args.config or "{}" properties = settings.ConfReader(config=args.config).get_prop_dic() # Specific call of each building block - box(input_pdb_path=args.input_pdb_path, + box( + input_pdb_path=args.input_pdb_path, output_pdb_path=args.output_pdb_path, - properties=properties) + properties=properties, + ) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/biobb_vs/utils/extract_model_pdbqt.py b/biobb_vs/utils/extract_model_pdbqt.py index 94c4ba7..613b2b1 100755 --- a/biobb_vs/utils/extract_model_pdbqt.py +++ b/biobb_vs/utils/extract_model_pdbqt.py @@ -1,26 +1,28 @@ #!/usr/bin/env python3 """Module containing the ExtractModelPDBQT class and the command line interface.""" + import argparse -from typing import Optional +import warnings from pathlib import PurePath -from biobb_common.generic.biobb_object import BiobbObject +from typing import Optional + +from Bio import BiopythonDeprecationWarning from biobb_common.configuration import settings +from biobb_common.generic.biobb_object import BiobbObject from biobb_common.tools import file_utils as fu from biobb_common.tools.file_utils import launchlogger + from biobb_vs.utils.common import check_input_path, check_output_path -from Bio import BiopythonDeprecationWarning -import warnings with warnings.catch_warnings(): warnings.simplefilter("ignore", BiopythonDeprecationWarning) - import Bio.PDB - import Bio.pairwise2 # try: # import Bio.SubsMat.MatrixInfo # except ImportError: - import Bio.Align.substitution_matrices + import Bio.pairwise2 + import Bio.PDB class ExtractModelPDBQT(BiobbObject): @@ -60,8 +62,9 @@ class ExtractModelPDBQT(BiobbObject): """ - def __init__(self, input_pdbqt_path, output_pdbqt_path, - properties=None, **kwargs) -> None: + def __init__( + self, input_pdbqt_path, output_pdbqt_path, properties=None, **kwargs + ) -> None: properties = properties or {} # Call parent class constructor @@ -71,11 +74,11 @@ def __init__(self, input_pdbqt_path, output_pdbqt_path, # Input/Output files self.io_dict = { "in": {"input_pdbqt_path": input_pdbqt_path}, - "out": {"output_pdbqt_path": output_pdbqt_path} + "out": {"output_pdbqt_path": output_pdbqt_path}, } # Properties specific for BB - self.model = properties.get('model', 1) + self.model = properties.get("model", 1) self.properties = properties # Check the properties @@ -83,9 +86,20 @@ def __init__(self, input_pdbqt_path, output_pdbqt_path, self.check_arguments() def check_data_params(self, out_log, err_log): - """ Checks all the input/output paths and parameters """ - self.io_dict["in"]["input_pdbqt_path"] = check_input_path(self.io_dict["in"]["input_pdbqt_path"], "input_pdbqt_path", out_log, self.__class__.__name__) - self.io_dict["out"]["output_pdbqt_path"] = check_output_path(self.io_dict["out"]["output_pdbqt_path"], "output_pdbqt_path", False, out_log, self.__class__.__name__) + """Checks all the input/output paths and parameters""" + self.io_dict["in"]["input_pdbqt_path"] = check_input_path( + self.io_dict["in"]["input_pdbqt_path"], + "input_pdbqt_path", + out_log, + self.__class__.__name__, + ) + self.io_dict["out"]["output_pdbqt_path"] = check_output_path( + self.io_dict["out"]["output_pdbqt_path"], + "output_pdbqt_path", + False, + out_log, + self.__class__.__name__, + ) @launchlogger def launch(self) -> int: @@ -102,41 +116,60 @@ def launch(self) -> int: if self.restart: output_file_list = [self.io_dict["out"]["output_pdbqt_path"]] if fu.check_complete_files(output_file_list): - fu.log('Restart is enabled, this step: %s will the skipped' % self.step, self.out_log, self.global_log) + fu.log( + "Restart is enabled, this step: %s will the skipped" % self.step, + self.out_log, + self.global_log, + ) return 0 structure_name = PurePath(self.io_dict["in"]["input_pdbqt_path"]).name parser = Bio.PDB.PDBParser(QUIET=True) - structPDB = parser.get_structure(structure_name, self.io_dict["in"]["input_pdbqt_path"]) + structPDB = parser.get_structure( + structure_name, self.io_dict["in"]["input_pdbqt_path"] + ) models = [] for model in structPDB.get_models(): models.append(model.id + 1) if self.model not in models: - fu.log(self.__class__.__name__ + ': Selected model %d not found in %s structure.' % (self.model, self.io_dict["in"]["input_pdbqt_path"]), self.out_log) - raise SystemExit(self.__class__.__name__ + ': Selected model %d not found in %s structure.' % (self.model, self.io_dict["in"]["input_pdbqt_path"])) + fu.log( + self.__class__.__name__ + + ": Selected model %d not found in %s structure." + % (self.model, self.io_dict["in"]["input_pdbqt_path"]), + self.out_log, + ) + raise SystemExit( + self.__class__.__name__ + + ": Selected model %d not found in %s structure." + % (self.model, self.io_dict["in"]["input_pdbqt_path"]) + ) save = False lines = 0 - with open(self.io_dict["in"]["input_pdbqt_path"], "r") as input_pdb, open(self.io_dict["out"]["output_pdbqt_path"], "w") as output_pdb: + with open(self.io_dict["in"]["input_pdbqt_path"], "r") as input_pdb, open( + self.io_dict["out"]["output_pdbqt_path"], "w" + ) as output_pdb: for line in input_pdb: - if line.startswith('MODEL') and line.split()[1] == str(self.model): + if line.startswith("MODEL") and line.split()[1] == str(self.model): save = True - if line.startswith('ENDMDL'): + if line.startswith("ENDMDL"): save = False - if save and not line.startswith('MODEL'): + if save and not line.startswith("MODEL"): lines = lines + 1 output_pdb.write(line) - fu.log('Saving model %d to %s' % (self.model, self.io_dict["out"]["output_pdbqt_path"]), self.out_log) + fu.log( + "Saving model %d to %s" + % (self.model, self.io_dict["out"]["output_pdbqt_path"]), + self.out_log, + ) # Copy files to host self.copy_to_host() - self.tmp_files.extend([ - self.stage_io_dict.get("unique_dir", "") - ]) + self.tmp_files.extend([self.stage_io_dict.get("unique_dir", "")]) self.remove_tmp_files() self.check_arguments(output_files_created=True, raise_exception=False) @@ -144,34 +177,55 @@ def launch(self) -> int: return 0 -def extract_model_pdbqt(input_pdbqt_path: str, output_pdbqt_path: str, properties: Optional[dict] = None, **kwargs) -> int: +def extract_model_pdbqt( + input_pdbqt_path: str, + output_pdbqt_path: str, + properties: Optional[dict] = None, + **kwargs, +) -> int: """Execute the :class:`ExtractModelPDBQT ` class and execute the :meth:`launch() ` method.""" - return ExtractModelPDBQT(input_pdbqt_path=input_pdbqt_path, - output_pdbqt_path=output_pdbqt_path, - properties=properties, **kwargs).launch() + return ExtractModelPDBQT( + input_pdbqt_path=input_pdbqt_path, + output_pdbqt_path=output_pdbqt_path, + properties=properties, + **kwargs, + ).launch() def main(): """Command line execution of this building block. Please check the command line documentation.""" - parser = argparse.ArgumentParser(description="Extracts a model from a PDBQT file with several models.", formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, width=99999)) - parser.add_argument('--config', required=False, help='Configuration file') + parser = argparse.ArgumentParser( + description="Extracts a model from a PDBQT file with several models.", + formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, width=99999), + ) + parser.add_argument("--config", required=False, help="Configuration file") # Specific args of each building block - required_args = parser.add_argument_group('required arguments') - required_args.add_argument('--input_pdbqt_path', required=True, help='Input PDBQT file. Accepted formats: pdbqt.') - required_args.add_argument('--output_pdbqt_path', required=True, help='Output PDBQT file. Accepted formats: pdbqt.') + required_args = parser.add_argument_group("required arguments") + required_args.add_argument( + "--input_pdbqt_path", + required=True, + help="Input PDBQT file. Accepted formats: pdbqt.", + ) + required_args.add_argument( + "--output_pdbqt_path", + required=True, + help="Output PDBQT file. Accepted formats: pdbqt.", + ) args = parser.parse_args() args.config = args.config or "{}" properties = settings.ConfReader(config=args.config).get_prop_dic() # Specific call of each building block - extract_model_pdbqt(input_pdbqt_path=args.input_pdbqt_path, - output_pdbqt_path=args.output_pdbqt_path, - properties=properties) + extract_model_pdbqt( + input_pdbqt_path=args.input_pdbqt_path, + output_pdbqt_path=args.output_pdbqt_path, + properties=properties, + ) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/biobb_vs/vina/__init__.py b/biobb_vs/vina/__init__.py index 956f788..dbc831c 100644 --- a/biobb_vs/vina/__init__.py +++ b/biobb_vs/vina/__init__.py @@ -1,3 +1,4 @@ from . import autodock_vina_run + name = "vina" __all__ = ["autodock_vina_run"] diff --git a/biobb_vs/vina/autodock_vina_run.py b/biobb_vs/vina/autodock_vina_run.py index fd8e255..2811888 100755 --- a/biobb_vs/vina/autodock_vina_run.py +++ b/biobb_vs/vina/autodock_vina_run.py @@ -1,12 +1,15 @@ #!/usr/bin/env python3 """Module containing the AutoDockVinaRun class and the command line interface.""" + import argparse -from typing import Optional import os -from biobb_common.generic.biobb_object import BiobbObject +from typing import Optional + from biobb_common.configuration import settings +from biobb_common.generic.biobb_object import BiobbObject from biobb_common.tools.file_utils import launchlogger + from biobb_vs.vina.common import check_input_path, check_output_path @@ -64,8 +67,16 @@ class AutoDockVinaRun(BiobbObject): """ - def __init__(self, input_ligand_pdbqt_path, input_receptor_pdbqt_path, input_box_path, output_pdbqt_path, - output_log_path=None, properties=None, **kwargs) -> None: + def __init__( + self, + input_ligand_pdbqt_path, + input_receptor_pdbqt_path, + input_box_path, + output_pdbqt_path, + output_log_path=None, + properties=None, + **kwargs, + ) -> None: properties = properties or {} # Call parent class constructor @@ -74,17 +85,24 @@ def __init__(self, input_ligand_pdbqt_path, input_receptor_pdbqt_path, input_box # Input/Output files self.io_dict = { - "in": {"input_ligand_pdbqt_path": input_ligand_pdbqt_path, "input_receptor_pdbqt_path": input_receptor_pdbqt_path, "input_box_path": input_box_path}, - "out": {"output_pdbqt_path": output_pdbqt_path, "output_log_path": output_log_path} + "in": { + "input_ligand_pdbqt_path": input_ligand_pdbqt_path, + "input_receptor_pdbqt_path": input_receptor_pdbqt_path, + "input_box_path": input_box_path, + }, + "out": { + "output_pdbqt_path": output_pdbqt_path, + "output_log_path": output_log_path, + }, } # Properties specific for BB - self.cpu = properties.get('cpu', 1) - self.exhaustiveness = properties.get('exhaustiveness', 8) - self.num_modes = properties.get('num_modes', 9) - self.min_rmsd = properties.get('min_rmsd', 1) - self.energy_range = properties.get('energy_range', 3) - self.binary_path = properties.get('binary_path', 'vina') + self.cpu = properties.get("cpu", 1) + self.exhaustiveness = properties.get("exhaustiveness", 8) + self.num_modes = properties.get("num_modes", 9) + self.min_rmsd = properties.get("min_rmsd", 1) + self.energy_range = properties.get("energy_range", 3) + self.binary_path = properties.get("binary_path", "vina") self.properties = properties # Check the properties @@ -92,22 +110,61 @@ def __init__(self, input_ligand_pdbqt_path, input_receptor_pdbqt_path, input_box self.check_arguments() def check_data_params(self, out_log, err_log): - """ Checks all the input/output paths and parameters """ - self.io_dict["in"]["input_ligand_pdbqt_path"] = check_input_path(self.io_dict["in"]["input_ligand_pdbqt_path"], "input_ligand_pdbqt_path", self.out_log, self.__class__.__name__) - self.io_dict["in"]["input_receptor_pdbqt_path"] = check_input_path(self.io_dict["in"]["input_receptor_pdbqt_path"], "input_receptor_pdbqt_path", self.out_log, self.__class__.__name__) - self.io_dict["in"]["input_box_path"] = check_input_path(self.io_dict["in"]["input_box_path"], "input_box_path", self.out_log, self.__class__.__name__) - self.io_dict["out"]["output_pdbqt_path"] = check_output_path(self.io_dict["out"]["output_pdbqt_path"], "output_pdbqt_path", False, self.out_log, self.__class__.__name__) - self.io_dict["out"]["output_log_path"] = check_output_path(self.io_dict["out"]["output_log_path"], "output_log_path", True, self.out_log, self.__class__.__name__) + """Checks all the input/output paths and parameters""" + self.io_dict["in"]["input_ligand_pdbqt_path"] = check_input_path( + self.io_dict["in"]["input_ligand_pdbqt_path"], + "input_ligand_pdbqt_path", + self.out_log, + self.__class__.__name__, + ) + self.io_dict["in"]["input_receptor_pdbqt_path"] = check_input_path( + self.io_dict["in"]["input_receptor_pdbqt_path"], + "input_receptor_pdbqt_path", + self.out_log, + self.__class__.__name__, + ) + self.io_dict["in"]["input_box_path"] = check_input_path( + self.io_dict["in"]["input_box_path"], + "input_box_path", + self.out_log, + self.__class__.__name__, + ) + self.io_dict["out"]["output_pdbqt_path"] = check_output_path( + self.io_dict["out"]["output_pdbqt_path"], + "output_pdbqt_path", + False, + self.out_log, + self.__class__.__name__, + ) + self.io_dict["out"]["output_log_path"] = check_output_path( + self.io_dict["out"]["output_log_path"], + "output_log_path", + True, + self.out_log, + self.__class__.__name__, + ) def calculate_box(self, box_file_path): - with open(box_file_path, 'r') as box_file: + with open(box_file_path, "r") as box_file: for line in box_file: line = line.rstrip(os.linesep) if line.startswith("REMARK BOX CENTER"): fields = line.split() center = fields[3:6] size = fields[-3:] - return list(map(str, [center[0], center[1], center[2], size[0], size[1], size[2]])) + return list( + map( + str, + [ + center[0], + center[1], + center[2], + size[0], + size[1], + size[2], + ], + ) + ) return list(map(str, [0, 0, 0, 0, 0, 0])) @launchlogger @@ -123,26 +180,44 @@ def launch(self) -> int: self.stage_files() # calculating box position and size - x0, y0, z0, sidex, sidey, sidez = self.calculate_box(self.io_dict["in"]["input_box_path"]) + x0, y0, z0, sidex, sidey, sidez = self.calculate_box( + self.io_dict["in"]["input_box_path"] + ) # in case ligand or receptor end with END, remove last line # check_input_autodock(self.io_dict["in"]["input_ligand_pdbqt_path"], self.out_log) # check_input_autodock(self.io_dict["in"]["input_receptor_pdbqt_path"], self.out_log) # create cmd - self.cmd = [self.binary_path, - '--ligand', self.stage_io_dict["in"]["input_ligand_pdbqt_path"], - '--receptor', self.stage_io_dict["in"]["input_receptor_pdbqt_path"], - '--center_x=' + x0, '--center_y=' + y0, '--center_z=' + z0, - '--size_x=' + sidex, '--size_y=' + sidey, '--size_z=' + sidez, - '--cpu', str(self.cpu), - '--exhaustiveness', str(self.exhaustiveness), - '--num_modes', str(self.num_modes), - '--min_rmsd', str(self.min_rmsd), - '--energy_range', str(self.energy_range), - '--out', self.stage_io_dict["out"]["output_pdbqt_path"], - '--verbosity', '1', - '>', self.stage_io_dict["out"]["output_log_path"]] + self.cmd = [ + self.binary_path, + "--ligand", + self.stage_io_dict["in"]["input_ligand_pdbqt_path"], + "--receptor", + self.stage_io_dict["in"]["input_receptor_pdbqt_path"], + "--center_x=" + x0, + "--center_y=" + y0, + "--center_z=" + z0, + "--size_x=" + sidex, + "--size_y=" + sidey, + "--size_z=" + sidez, + "--cpu", + str(self.cpu), + "--exhaustiveness", + str(self.exhaustiveness), + "--num_modes", + str(self.num_modes), + "--min_rmsd", + str(self.min_rmsd), + "--energy_range", + str(self.energy_range), + "--out", + self.stage_io_dict["out"]["output_pdbqt_path"], + "--verbosity", + "1", + ">", + self.stage_io_dict["out"]["output_log_path"], + ] # Run Biobb block self.run_biobb() @@ -151,9 +226,7 @@ def launch(self) -> int: self.copy_to_host() # remove temporary folder(s) - self.tmp_files.extend([ - self.stage_io_dict.get("unique_dir", "") - ]) + self.tmp_files.extend([self.stage_io_dict.get("unique_dir", "")]) self.remove_tmp_files() self.check_arguments(output_files_created=True, raise_exception=False) @@ -161,43 +234,79 @@ def launch(self) -> int: return self.return_code -def autodock_vina_run(input_ligand_pdbqt_path: str, input_receptor_pdbqt_path: str, input_box_path: str, output_pdbqt_path: str, output_log_path: Optional[str] = None, properties: Optional[dict] = None, **kwargs) -> int: +def autodock_vina_run( + input_ligand_pdbqt_path: str, + input_receptor_pdbqt_path: str, + input_box_path: str, + output_pdbqt_path: str, + output_log_path: Optional[str] = None, + properties: Optional[dict] = None, + **kwargs, +) -> int: """Execute the :class:`AutoDockVinaRun ` class and execute the :meth:`launch() ` method.""" - return AutoDockVinaRun(input_ligand_pdbqt_path=input_ligand_pdbqt_path, - input_receptor_pdbqt_path=input_receptor_pdbqt_path, - input_box_path=input_box_path, - output_pdbqt_path=output_pdbqt_path, - output_log_path=output_log_path, - properties=properties, **kwargs).launch() + return AutoDockVinaRun( + input_ligand_pdbqt_path=input_ligand_pdbqt_path, + input_receptor_pdbqt_path=input_receptor_pdbqt_path, + input_box_path=input_box_path, + output_pdbqt_path=output_pdbqt_path, + output_log_path=output_log_path, + properties=properties, + **kwargs, + ).launch() def main(): """Command line execution of this building block. Please check the command line documentation.""" - parser = argparse.ArgumentParser(description="Prepares input ligand for an Autodock Vina Virtual Screening.", formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, width=99999)) - parser.add_argument('--config', required=False, help='Configuration file') + parser = argparse.ArgumentParser( + description="Prepares input ligand for an Autodock Vina Virtual Screening.", + formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, width=99999), + ) + parser.add_argument("--config", required=False, help="Configuration file") # Specific args of each building block - required_args = parser.add_argument_group('required arguments') - required_args.add_argument('--input_ligand_pdbqt_path', required=True, help='Path to the input PDBQT ligand. Accepted formats: pdbqt.') - required_args.add_argument('--input_receptor_pdbqt_path', required=True, help='Path to the input PDBQT receptor. Accepted formats: pdbqt.') - required_args.add_argument('--input_box_path', required=True, help='Path to the PDB containig the residues belonging to the binding site. Accepted formats: pdb.') - required_args.add_argument('--output_pdbqt_path', required=True, help='Path to the output PDBQT file. Accepted formats: pdbqt.') - parser.add_argument('--output_log_path', required=False, help='Path to the log file. Accepted formats: log.') + required_args = parser.add_argument_group("required arguments") + required_args.add_argument( + "--input_ligand_pdbqt_path", + required=True, + help="Path to the input PDBQT ligand. Accepted formats: pdbqt.", + ) + required_args.add_argument( + "--input_receptor_pdbqt_path", + required=True, + help="Path to the input PDBQT receptor. Accepted formats: pdbqt.", + ) + required_args.add_argument( + "--input_box_path", + required=True, + help="Path to the PDB containig the residues belonging to the binding site. Accepted formats: pdb.", + ) + required_args.add_argument( + "--output_pdbqt_path", + required=True, + help="Path to the output PDBQT file. Accepted formats: pdbqt.", + ) + parser.add_argument( + "--output_log_path", + required=False, + help="Path to the log file. Accepted formats: log.", + ) args = parser.parse_args() args.config = args.config or "{}" properties = settings.ConfReader(config=args.config).get_prop_dic() # Specific call of each building block - autodock_vina_run(input_ligand_pdbqt_path=args.input_ligand_pdbqt_path, - input_receptor_pdbqt_path=args.input_receptor_pdbqt_path, - input_box_path=args.input_box_path, - output_pdbqt_path=args.output_pdbqt_path, - output_log_path=args.output_log_path, - properties=properties) + autodock_vina_run( + input_ligand_pdbqt_path=args.input_ligand_pdbqt_path, + input_receptor_pdbqt_path=args.input_receptor_pdbqt_path, + input_box_path=args.input_box_path, + output_pdbqt_path=args.output_pdbqt_path, + output_log_path=args.output_log_path, + properties=properties, + ) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/biobb_vs/vina/common.py b/biobb_vs/vina/common.py index 79fec69..07ae02a 100644 --- a/biobb_vs/vina/common.py +++ b/biobb_vs/vina/common.py @@ -1,57 +1,77 @@ -""" Common functions for package biobb_vs.vina """ +"""Common functions for package biobb_vs.vina""" + from pathlib import Path, PurePath -from biobb_common.tools import file_utils as fu +from biobb_common.tools import file_utils as fu # CHECK PARAMETERS + def check_input_path(path, argument, out_log, classname): - """ Checks input file """ + """Checks input file""" if not Path(path).exists(): - fu.log(classname + ': Unexisting %s file, exiting' % argument, out_log) - raise SystemExit(classname + ': Unexisting %s file' % argument) + fu.log(classname + ": Unexisting %s file, exiting" % argument, out_log) + raise SystemExit(classname + ": Unexisting %s file" % argument) file_extension = PurePath(path).suffix if not is_valid_file(file_extension[1:], argument): - fu.log(classname + ': Format %s in %s file is not compatible' % (file_extension[1:], argument), out_log) - raise SystemExit(classname + ': Format %s in %s file is not compatible' % (file_extension[1:], argument)) + fu.log( + classname + + ": Format %s in %s file is not compatible" + % (file_extension[1:], argument), + out_log, + ) + raise SystemExit( + classname + + ": Format %s in %s file is not compatible" + % (file_extension[1:], argument) + ) return path def check_output_path(path, argument, optional, out_log, classname): - """ Checks output file """ + """Checks output file""" if optional and not path: return None if PurePath(path).parent and not Path(PurePath(path).parent).exists(): - fu.log(classname + ': Unexisting %s folder, exiting' % argument, out_log) - raise SystemExit(classname + ': Unexisting %s folder' % argument) + fu.log(classname + ": Unexisting %s folder, exiting" % argument, out_log) + raise SystemExit(classname + ": Unexisting %s folder" % argument) file_extension = PurePath(path).suffix if not is_valid_file(file_extension[1:], argument): - fu.log(classname + ': Format %s in %s file is not compatible' % (file_extension[1:], argument), out_log) - raise SystemExit(classname + ': Format %s in %s file is not compatible' % (file_extension[1:], argument)) + fu.log( + classname + + ": Format %s in %s file is not compatible" + % (file_extension[1:], argument), + out_log, + ) + raise SystemExit( + classname + + ": Format %s in %s file is not compatible" + % (file_extension[1:], argument) + ) return path def is_valid_file(ext, argument): - """ Checks if file format is compatible """ + """Checks if file format is compatible""" formats = { - 'input_ligand_path': ['pdb'], - 'output_ligand_path': ['pdbqt'], - 'input_receptor_path': ['pdb'], - 'output_receptor_path': ['pdbqt'], - 'input_ligand_pdbqt_path': ['pdbqt'], - 'input_receptor_pdbqt_path': ['pdbqt'], - 'input_box_path': ['pdb'], - 'output_pdbqt_path': ['pdbqt'], - 'output_log_path': ['log'] + "input_ligand_path": ["pdb"], + "output_ligand_path": ["pdbqt"], + "input_receptor_path": ["pdb"], + "output_receptor_path": ["pdbqt"], + "input_ligand_pdbqt_path": ["pdbqt"], + "input_receptor_pdbqt_path": ["pdbqt"], + "input_box_path": ["pdb"], + "output_pdbqt_path": ["pdbqt"], + "output_log_path": ["log"], } return ext in formats[argument] def check_mgltools_path(mgltools_path, out_log, classname): - """ Checks the path of mgltools """ + """Checks the path of mgltools""" if not Path(mgltools_path).exists(): - fu.log(classname + ': Unexisting mgltools_path, exiting', out_log) - raise SystemExit(classname + ': Unexisting mgltools_path, exiting') + fu.log(classname + ": Unexisting mgltools_path, exiting", out_log) + raise SystemExit(classname + ": Unexisting mgltools_path, exiting") return mgltools_path diff --git a/setup.py b/setup.py index 2cb91b4..28c107d 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="biobb_vs", - version="4.2.0", + version="5.0.0", author="Biobb developers", author_email="genis.bayarri@irbbarcelona.org", description="Biobb_vs is the Biobb module collection to perform virtual screening studies.", @@ -15,12 +15,12 @@ url="https://github.com/bioexcel/biobb_vs", project_urls={ "Documentation": "http://biobb-vs.readthedocs.io/en/latest/", - "Bioexcel": "https://bioexcel.eu/" + "Bioexcel": "https://bioexcel.eu/", }, - packages=setuptools.find_packages(exclude=['docs', 'test']), - package_data={'biobb_vs': ['py.typed']}, - install_requires=['biobb_common==4.2.0'], - python_requires='>=3.8', + packages=setuptools.find_packages(exclude=["docs", "test"]), + package_data={"biobb_vs": ["py.typed"]}, + install_requires=["biobb_common==5.0.0"], + python_requires=">=3.9", entry_points={ "console_scripts": [ "fpocket_filter = biobb_vs.fpocket.fpocket_filter:main", @@ -30,16 +30,15 @@ "box_residues = biobb_vs.utils.box_residues:main", "box = biobb_vs.utils.box:main", "extract_model_pdbqt = biobb_vs.utils.extract_model_pdbqt:main", - "autodock_vina_run = biobb_vs.vina.autodock_vina_run:main" + "autodock_vina_run = biobb_vs.vina.autodock_vina_run:main", ] }, - classifiers=( - "Development Status :: 3 - Alpha", - "Programming Language :: Python :: 3.8", + classifiers=[ + "Development Status :: 5 - Production/Stable", "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", "License :: OSI Approved :: Apache Software License", "Operating System :: MacOS :: MacOS X", "Operating System :: POSIX", - ), + "Operating System :: Unix", + ], )