diff --git a/.github/workflows/dataviz.yaml b/.github/workflows/dataviz.yaml index 59bf892c..19a64cc8 100644 --- a/.github/workflows/dataviz.yaml +++ b/.github/workflows/dataviz.yaml @@ -72,7 +72,7 @@ jobs: micromamba install -n dataviz --file devtools/conda-envs/${{ matrix.os }}/simulation.yaml micromamba install -n dataviz --file devtools/conda-envs/${{ matrix.os }}/modeling.yaml micromamba install -n dataviz --file devtools/conda-envs/${{ matrix.os }}/spectrum.yaml - + python -m pip install -e ./drugforge-data --no-deps python -m pip install -e ./drugforge-modeling --no-deps python -m pip install -e ./drugforge-cli --no-deps @@ -81,7 +81,7 @@ jobs: python -m pip install -e ./drugforge-simulation --no-deps python -m pip install -e ./drugforge-spectrum --no-deps micromamba list - + - name: Test OE License & Write License to File env: OE_LICENSE_TEXT: ${{ secrets.OE_LICENSE }} diff --git a/README.md b/README.md index 4fc824ec..81f71c6b 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,9 @@ This fork is now developed and maintained independently by the [Chodera Lab](htt ## Intro -All pandemics are global health threats. Our best defense is a healthy global antiviral discovery community with a robust pipeline of open discovery tools. +All pandemics are global health threats. Our best defense is a healthy global antiviral discovery community with a robust pipeline of open discovery tools. -The toolkit in this repo is a batteries-included drug discovery pipeline being actively developed in a transparent open-source way, with a focus on computational chemistry and informatics support for medicinal chemistry. +The toolkit in this repo is a batteries-included drug discovery pipeline being actively developed in a transparent open-source way, with a focus on computational chemistry and informatics support for medicinal chemistry. ## Getting Started @@ -27,7 +27,7 @@ Install the `drugforge` subpackages and begin to explore! The drugforge [documen There are a range of workflows and tooling to use split into several namespace subpackages by theme. -**Warning:** The implementation of drugforge-ML is still in the works and will be available in the next release. If you want to use ML scoring please refer to the original version of this code under [asapdiscovery](https://github.com/asapdiscovery/asapdiscovery). +**Warning:** The implementation of drugforge-ML is still in the works and will be available in the next release. If you want to use ML scoring please refer to the original version of this code under [asapdiscovery](https://github.com/asapdiscovery/asapdiscovery). `drugforge-alchemy`: Free energy calculations using [OpenFE](https://openfree.energy/) and [Alchemiscale](https://docs.alchemiscale.org/en/latest/). See [tutorial](https://drugforge.readthedocs.io/en/latest/tutorials/running_alchemical_free_energy_calculations.html) and CLI [guide](https://asapdiscovery.readthedocs.io/en/latest/guides/using_asap_alchemy_cli.html) diff --git a/devtools/conda-envs/macos-latest/alchemy.yaml b/devtools/conda-envs/macos-latest/alchemy.yaml index b6abd5f5..f5fb5823 100644 --- a/devtools/conda-envs/macos-latest/alchemy.yaml +++ b/devtools/conda-envs/macos-latest/alchemy.yaml @@ -5,15 +5,16 @@ channels: dependencies: - alchemiscale-client - bokeh - - cinnabar + - cinnabar ~=0.5.0 - click - - gufe + - gufe ~=1.6.0 + - importlib_resources # manually added. More info at https://github.com/conda-forge/openmmforcefields-feedstock/pull/26 - kartograf - lomap2 - networkx - numpy - openeye-toolkits - - openfe ~=1.0 + - openfe ~=1.4 - openff-toolkit - openff-models - openff-qcsubmit diff --git a/devtools/conda-envs/macos-latest/cli.yaml b/devtools/conda-envs/macos-latest/cli.yaml index 9fdd66b7..403dbbd0 100644 --- a/devtools/conda-envs/macos-latest/cli.yaml +++ b/devtools/conda-envs/macos-latest/cli.yaml @@ -3,4 +3,4 @@ channels: - conda-forge dependencies: - click - - pytest \ No newline at end of file + - pytest diff --git a/devtools/conda-envs/ubuntu-latest/alchemy.yaml b/devtools/conda-envs/ubuntu-latest/alchemy.yaml index b6abd5f5..f5fb5823 100644 --- a/devtools/conda-envs/ubuntu-latest/alchemy.yaml +++ b/devtools/conda-envs/ubuntu-latest/alchemy.yaml @@ -5,15 +5,16 @@ channels: dependencies: - alchemiscale-client - bokeh - - cinnabar + - cinnabar ~=0.5.0 - click - - gufe + - gufe ~=1.6.0 + - importlib_resources # manually added. More info at https://github.com/conda-forge/openmmforcefields-feedstock/pull/26 - kartograf - lomap2 - networkx - numpy - openeye-toolkits - - openfe ~=1.0 + - openfe ~=1.4 - openff-toolkit - openff-models - openff-qcsubmit diff --git a/devtools/conda-envs/ubuntu-latest/cli.yaml b/devtools/conda-envs/ubuntu-latest/cli.yaml index 9fdd66b7..403dbbd0 100644 --- a/devtools/conda-envs/ubuntu-latest/cli.yaml +++ b/devtools/conda-envs/ubuntu-latest/cli.yaml @@ -3,4 +3,4 @@ channels: - conda-forge dependencies: - click - - pytest \ No newline at end of file + - pytest diff --git a/devtools/conda-envs/ubuntu-latest/simulation.yaml b/devtools/conda-envs/ubuntu-latest/simulation.yaml index d05c7874..36ea6fc4 100644 --- a/devtools/conda-envs/ubuntu-latest/simulation.yaml +++ b/devtools/conda-envs/ubuntu-latest/simulation.yaml @@ -71,4 +71,4 @@ dependencies: - multimethod # ML - - mtenn >=0.6.3 \ No newline at end of file + - mtenn >=0.6.3 diff --git a/devtools/conda-envs/ubuntu-latest/spectrum.yaml b/devtools/conda-envs/ubuntu-latest/spectrum.yaml index 880f5dac..b2155eb8 100644 --- a/devtools/conda-envs/ubuntu-latest/spectrum.yaml +++ b/devtools/conda-envs/ubuntu-latest/spectrum.yaml @@ -64,4 +64,3 @@ dependencies: - moto - boto3 - multimethod - diff --git a/devtools/conda-envs/ubuntu-latest/workflows.yaml b/devtools/conda-envs/ubuntu-latest/workflows.yaml index 7f1ed8dd..5aae6ff4 100644 --- a/devtools/conda-envs/ubuntu-latest/workflows.yaml +++ b/devtools/conda-envs/ubuntu-latest/workflows.yaml @@ -6,4 +6,4 @@ dependencies: # drugforge {all the other packages} click pydantic - unittest \ No newline at end of file + unittest diff --git a/devtools/detect_imports.py b/devtools/detect_imports.py index bc02fed6..f720d2d7 100644 --- a/devtools/detect_imports.py +++ b/devtools/detect_imports.py @@ -14,7 +14,7 @@ from pathlib import Path -def get_imports_from_file(file_path: str) -> Set[Tuple[str, str]]: +def get_imports_from_file(file_path: str) -> set[tuple[str, str]]: """ Extract import names and their submodules from a Python file. Returns set of tuples (package, submodule). @@ -22,7 +22,7 @@ def get_imports_from_file(file_path: str) -> Set[Tuple[str, str]]: imports = set() try: - with open(file_path, 'r', encoding='utf-8') as f: + with open(file_path, encoding='utf-8') as f: tree = ast.parse(f.read()) for node in ast.walk(tree): @@ -49,7 +49,7 @@ def get_imports_from_file(file_path: str) -> Set[Tuple[str, str]]: return imports -def find_all_imports_with_files(directory: str) -> Dict[str, Dict[str, Set[str]]]: +def find_all_imports_with_files(directory: str) -> dict[str, dict[str, set[str]]]: """ Find all unique imports and their submodules in Python files. @@ -132,4 +132,4 @@ def main(directory: str, output: str, packages_only: bool): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/docs/README.md b/docs/README.md index 5d74b138..321a06a5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,12 +1,12 @@ # Compiling drugforge's Documentation -For the docs to compile properly, you will need to have the full drugforge environment installed. +For the docs to compile properly, you will need to have the full drugforge environment installed. The docs for this project are built with [Sphinx](http://www.sphinx-doc.org/en/master/). To install the needed dependencies, you can run: ```bash - mamba env update -f docs/requirements.yaml -n YOUR_DRUGFORGE_ENVIRONMENT_NAME + mamba env update -f docs/requirements.yaml -n YOUR_DRUGFORGE_ENVIRONMENT_NAME ``` You can then build the docs with: diff --git a/docs/index.md b/docs/index.md index e669be12..fb565daf 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,7 +2,7 @@ Welcome to drugforge's documentation! ========================================= -All pandemics are global health threats. Our best defense is a healthy global antiviral discovery community with a robust pipeline of open discovery tools. +All pandemics are global health threats. Our best defense is a healthy global antiviral discovery community with a robust pipeline of open discovery tools. The toolkit in this repo is a batteries-included drug discovery pipeline being actively developed in a transparent open-source way, with a focus on computational chemistry and informatics support for medicinal chemistry. @@ -15,7 +15,7 @@ drugforge is not designed as a one size fits all solution for drug discovery, ra ``` ```{warning} -The implementation of drugforge-ML is still in the works and will be available in the next release. If you want to use ML scoring please refer to the original version of this code under [asapdiscovery](https://github.com/asapdiscovery/asapdiscovery). +The implementation of drugforge-ML is still in the works and will be available in the next release. If you want to use ML scoring please refer to the original version of this code under [asapdiscovery](https://github.com/asapdiscovery/asapdiscovery). ``` The `drugforge` toolkit is focused around the following core competencies, organised into submodules: diff --git a/docs/installation.md b/docs/installation.md index bc42d982..9847433a 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -53,7 +53,7 @@ Note that the Docker image assumes that your OpenEye license is located at `~/.O Developer installation from source ---------------------------------- -To install `drugforge` from source, you will need to clone the repository, create a compatible base environment with mamba (or conda), we recommend using only the dependencies for `drugforge` for this step. +To install `drugforge` from source, you will need to clone the repository, create a compatible base environment with mamba (or conda), we recommend using only the dependencies for `drugforge` for this step. Install the development dependencies/utils (such as openeye-toolkits, pytest, ipython, etc.). And finally, install all the subpackages with `pip` using an editable install (so changes get automatically updated). This needs a for loop and compatibility config mode. You can do this using the following commands: diff --git a/drugforge-alchemy/drugforge/alchemy/cli/prep.py b/drugforge-alchemy/drugforge/alchemy/cli/prep.py index d1339f7e..814af76e 100644 --- a/drugforge-alchemy/drugforge/alchemy/cli/prep.py +++ b/drugforge-alchemy/drugforge/alchemy/cli/prep.py @@ -301,11 +301,7 @@ def run( import pandas import rich - from drugforge.alchemy.cli.utils import ( - get_cpus, - print_header, - pull_from_postera, - ) + from drugforge.alchemy.cli.utils import get_cpus, print_header, pull_from_postera from drugforge.alchemy.schema.prep_workflow import AlchemyPrepWorkflow from drugforge.data.readers.molfile import MolFileFactory from drugforge.modeling.schema import PreppedComplex diff --git a/drugforge-alchemy/drugforge/alchemy/cli/utils.py b/drugforge-alchemy/drugforge/alchemy/cli/utils.py index dc753a2f..b532115e 100644 --- a/drugforge-alchemy/drugforge/alchemy/cli/utils.py +++ b/drugforge-alchemy/drugforge/alchemy/cli/utils.py @@ -5,9 +5,9 @@ import rich if TYPE_CHECKING: + from cinnabar import FEMap from drugforge.alchemy.schema.fec import FreeEnergyCalculationNetwork from drugforge.data.schema.ligand import Ligand - from cinnabar import FEMap def print_header(console: "rich.Console"): @@ -68,8 +68,8 @@ def upload_to_postera( from drugforge.data.services.postera.manifold_data_validation import ( rename_output_columns_for_manifold, ) - from drugforge.workflows.postera.postera_uploader import PosteraUploader from drugforge.data.services.services_config import PosteraSettings + from drugforge.workflows.postera.postera_uploader import PosteraUploader # mock an enum to specify which columns are allowed class AlchemyResults(str, Enum): diff --git a/drugforge-alchemy/drugforge/alchemy/predict.py b/drugforge-alchemy/drugforge/alchemy/predict.py index 016356ea..eaa7ecd3 100644 --- a/drugforge-alchemy/drugforge/alchemy/predict.py +++ b/drugforge-alchemy/drugforge/alchemy/predict.py @@ -10,9 +10,9 @@ import pandas as pd import panel import plotmol -from drugforge.data.schema.ligand import Ligand from bokeh.models import Band, ColumnDataSource, Range1d, Whisker from cinnabar import stats +from drugforge.data.schema.ligand import Ligand from openff.units import unit from rdkit import Chem from rdkit.Chem import Draw diff --git a/drugforge-alchemy/drugforge/alchemy/schema/_util.py b/drugforge-alchemy/drugforge/alchemy/schema/_util.py index b2a75c58..82fe0c03 100644 --- a/drugforge-alchemy/drugforge/alchemy/schema/_util.py +++ b/drugforge-alchemy/drugforge/alchemy/schema/_util.py @@ -1,7 +1,8 @@ from collections import Counter from typing import TYPE_CHECKING -from gufe.serialization.json import JSONCodec + from alchemiscale import ScopedKey +from gufe.serialization.json import JSONCodec if TYPE_CHECKING: from drugforge.data.schema.ligand import Ligand diff --git a/drugforge-alchemy/drugforge/alchemy/schema/base.py b/drugforge-alchemy/drugforge/alchemy/schema/base.py index bd6d0787..7f1e938a 100644 --- a/drugforge-alchemy/drugforge/alchemy/schema/base.py +++ b/drugforge-alchemy/drugforge/alchemy/schema/base.py @@ -17,6 +17,7 @@ def to_file(self, filename: str): Write the model to JSON file. """ from gufe.tokenization import JSON_HANDLER + from ._util import SCOPEDKEY_CODEC JSON_HANDLER.add_codec(SCOPEDKEY_CODEC) @@ -30,6 +31,7 @@ def from_file(cls, filename: str): Load the model from a JSON file """ from gufe.tokenization import JSON_HANDLER + from ._util import SCOPEDKEY_CODEC JSON_HANDLER.add_codec(SCOPEDKEY_CODEC) diff --git a/drugforge-alchemy/drugforge/alchemy/schema/fec.py b/drugforge-alchemy/drugforge/alchemy/schema/fec.py index e8c4b389..d4ebe08d 100644 --- a/drugforge-alchemy/drugforge/alchemy/schema/fec.py +++ b/drugforge-alchemy/drugforge/alchemy/schema/fec.py @@ -1,5 +1,5 @@ import warnings -from typing import TYPE_CHECKING, Any, Literal, Optional, Union, Dict +from typing import TYPE_CHECKING, Any, Dict, Literal, Optional, Union import gufe import openfe @@ -300,7 +300,7 @@ class AlchemiscaleResults(_BaseResults): ) @validator("network_key", pre=True) - def convert_to_scoped_key(cls, value: Union[Dict, ScopedKey]) -> ScopedKey: + def convert_to_scoped_key(cls, value: Union[dict, ScopedKey]) -> ScopedKey: # if we have a dict convert it to a ScopedKey if isinstance(value, dict): return ScopedKey(**value) diff --git a/drugforge-alchemy/drugforge/alchemy/schema/prep_workflow.py b/drugforge-alchemy/drugforge/alchemy/schema/prep_workflow.py index c249bf36..64bc9d7d 100644 --- a/drugforge-alchemy/drugforge/alchemy/schema/prep_workflow.py +++ b/drugforge-alchemy/drugforge/alchemy/schema/prep_workflow.py @@ -9,15 +9,13 @@ ProtomerExpander, ) from drugforge.data.operators.state_expanders.stereo_expander import StereoExpander -from drugforge.data.operators.state_expanders.tautomer_expander import ( - TautomerExpander, -) -from drugforge.modeling.schema import PreppedComplex +from drugforge.data.operators.state_expanders.tautomer_expander import TautomerExpander from drugforge.data.schema.ligand import Ligand from drugforge.docking.schema.pose_generation import ( OpenEyeConstrainedPoseGenerator, RDKitConstrainedPoseGenerator, ) +from drugforge.modeling.schema import PreppedComplex from pydantic.v1 import Field from rich import pretty from rich.padding import Padding diff --git a/drugforge-alchemy/drugforge/alchemy/tests/conftest.py b/drugforge-alchemy/drugforge/alchemy/tests/conftest.py index 05ef1f1e..6cec5c4b 100644 --- a/drugforge-alchemy/drugforge/alchemy/tests/conftest.py +++ b/drugforge-alchemy/drugforge/alchemy/tests/conftest.py @@ -7,10 +7,10 @@ from drugforge.alchemy.schema.prep_workflow import AlchemyPrepWorkflow from drugforge.alchemy.utils import AlchemiscaleHelper from drugforge.data.readers.molfile import MolFileFactory -from drugforge.modeling.schema import PreppedComplex from drugforge.data.schema.ligand import Ligand, write_ligands_to_multi_sdf from drugforge.data.testing.test_resources import fetch_test_file from drugforge.docking.schema.pose_generation import OpenEyeConstrainedPoseGenerator +from drugforge.modeling.schema import PreppedComplex from gufe.protocols import Context, ProtocolUnit, ProtocolUnitFailure diff --git a/drugforge-alchemy/drugforge/alchemy/tests/test_cli.py b/drugforge-alchemy/drugforge/alchemy/tests/test_cli.py index 804d2b00..3ca9761c 100644 --- a/drugforge-alchemy/drugforge/alchemy/tests/test_cli.py +++ b/drugforge-alchemy/drugforge/alchemy/tests/test_cli.py @@ -8,18 +8,15 @@ import rich from alchemiscale import AlchemiscaleClient from alchemiscale.models import ScopedKey +from click.testing import CliRunner from drugforge.alchemy.cli.cli import alchemy from drugforge.alchemy.schema.fec import ( FreeEnergyCalculationFactory, FreeEnergyCalculationNetwork, ) -from drugforge.alchemy.schema.prep_workflow import ( - AlchemyDataSet, - AlchemyPrepWorkflow, -) +from drugforge.alchemy.schema.prep_workflow import AlchemyDataSet, AlchemyPrepWorkflow from drugforge.data.services.cdd.cdd_api import CDDAPI from drugforge.data.testing.test_resources import fetch_test_file -from click.testing import CliRunner from openfe.setup import LigandNetwork from rdkit import Chem diff --git a/drugforge-alchemy/drugforge/alchemy/tests/test_utils.py b/drugforge-alchemy/drugforge/alchemy/tests/test_utils.py index 69265ead..3b4d21f2 100644 --- a/drugforge-alchemy/drugforge/alchemy/tests/test_utils.py +++ b/drugforge-alchemy/drugforge/alchemy/tests/test_utils.py @@ -378,9 +378,7 @@ def get_cdd_data(protocol_name: str): ] return pandas.DataFrame(data) - monkeypatch.setattr( - drugforge.alchemy.predict, "download_cdd_data", get_cdd_data - ) + monkeypatch.setattr(drugforge.alchemy.predict, "download_cdd_data", get_cdd_data) molecules = get_cdd_molecules( protocol_name="my-protocol", @@ -410,9 +408,7 @@ def get_cdd_data(protocol_name: str): ] return pandas.DataFrame(data) - monkeypatch.setattr( - drugforge.alchemy.predict, "download_cdd_data", get_cdd_data - ) + monkeypatch.setattr(drugforge.alchemy.predict, "download_cdd_data", get_cdd_data) molecules = get_cdd_molecules( protocol_name="my-protocol", diff --git a/drugforge-alchemy/drugforge/alchemy/utils.py b/drugforge-alchemy/drugforge/alchemy/utils.py index eb63c1b8..8d19a126 100644 --- a/drugforge-alchemy/drugforge/alchemy/utils.py +++ b/drugforge-alchemy/drugforge/alchemy/utils.py @@ -12,11 +12,10 @@ from drugforge.alchemy.schema.forcefield import ForceFieldParams from openmm.app import ForceField, Modeller, PDBFile - if TYPE_CHECKING: - from drugforge.modeling.schema import PreppedComplex, PreppedTarget from drugforge.data.schema.ligand import Ligand from drugforge.data.schema.target import PreppedTarget + from drugforge.modeling.schema import PreppedComplex, PreppedTarget def create_protein_only_system(input_pdb_path: str, ff_params: ForceFieldParams): diff --git a/drugforge-cli/drugforge/cli/cli.py b/drugforge-cli/drugforge/cli/cli.py index da89b9d8..10db9bf6 100644 --- a/drugforge-cli/drugforge/cli/cli.py +++ b/drugforge-cli/drugforge/cli/cli.py @@ -5,9 +5,7 @@ def cli(help="Command-line interface for drugforge"): ... -from drugforge.workflows.docking_workflows.cli import ( # noqa: F401, E402, F811 - docking, -) +from drugforge.workflows.docking_workflows.cli import docking # noqa: F401, E402, F811 cli.add_command(docking) diff --git a/drugforge-cli/drugforge/cli/tests/test_meta_cli.py b/drugforge-cli/drugforge/cli/tests/test_meta_cli.py index 4040ec32..854ab0cf 100644 --- a/drugforge-cli/drugforge/cli/tests/test_meta_cli.py +++ b/drugforge-cli/drugforge/cli/tests/test_meta_cli.py @@ -1,8 +1,8 @@ import traceback import pytest -from drugforge.cli.cli import cli from click.testing import CliRunner +from drugforge.cli.cli import cli def click_success(result): diff --git a/drugforge-data/drugforge/data/backend/openeye.py b/drugforge-data/drugforge/data/backend/openeye.py index 6f8feeca..e8b64cdf 100644 --- a/drugforge-data/drugforge/data/backend/openeye.py +++ b/drugforge-data/drugforge/data/backend/openeye.py @@ -4,6 +4,7 @@ from typing import Any, Dict, List, Optional, Union # noqa: F401 from warnings import warn +from drugforge.data.schema.schema_base import MoleculeFilter from openeye import ( # noqa: F401 oechem, oedepict, @@ -17,7 +18,6 @@ oespruce, oeszybki, ) -from drugforge.data.schema.schema_base import MoleculeFilter # exec on module import diff --git a/drugforge-data/drugforge/data/backend/rdkit.py b/drugforge-data/drugforge/data/backend/rdkit.py index 24f57588..94bde363 100644 --- a/drugforge-data/drugforge/data/backend/rdkit.py +++ b/drugforge-data/drugforge/data/backend/rdkit.py @@ -103,9 +103,7 @@ def get_SD_data(mol: Chem.Mol) -> dict[str, list]: return get_dict_of_lists_from_dict_of_str(_get_SD_data(mol)) - from drugforge.data.util.data_conversion import ( - get_dict_of_lists_from_list_of_dicts, - ) + from drugforge.data.util.data_conversion import get_dict_of_lists_from_list_of_dicts data_list = [_get_SD_data(conf) for conf in mol.GetConformers()] return get_dict_of_lists_from_list_of_dicts(data_list) diff --git a/drugforge-data/drugforge/data/operators/state_expanders/protomer_expander.py b/drugforge-data/drugforge/data/operators/state_expanders/protomer_expander.py index 2fc75f4b..108219b8 100644 --- a/drugforge-data/drugforge/data/operators/state_expanders/protomer_expander.py +++ b/drugforge-data/drugforge/data/operators/state_expanders/protomer_expander.py @@ -9,9 +9,7 @@ oequacpac, save_openeye_sdfs, ) -from drugforge.data.operators.state_expanders.state_expander import ( - StateExpanderBase, -) +from drugforge.data.operators.state_expanders.state_expander import StateExpanderBase from drugforge.data.schema.ligand import Ligand from pydantic.v1 import Field diff --git a/drugforge-data/drugforge/data/operators/state_expanders/stereo_expander.py b/drugforge-data/drugforge/data/operators/state_expanders/stereo_expander.py index b7fd4d1c..34e589bc 100644 --- a/drugforge-data/drugforge/data/operators/state_expanders/stereo_expander.py +++ b/drugforge-data/drugforge/data/operators/state_expanders/stereo_expander.py @@ -1,9 +1,7 @@ from typing import Literal from drugforge.data.backend.openeye import clear_SD_data, oechem, oeomega -from drugforge.data.operators.state_expanders.state_expander import ( - StateExpanderBase, -) +from drugforge.data.operators.state_expanders.state_expander import StateExpanderBase from drugforge.data.schema.ligand import Ligand from pydantic.v1 import Field diff --git a/drugforge-data/drugforge/data/operators/state_expanders/tautomer_expander.py b/drugforge-data/drugforge/data/operators/state_expanders/tautomer_expander.py index a4b0cb94..06682bad 100644 --- a/drugforge-data/drugforge/data/operators/state_expanders/tautomer_expander.py +++ b/drugforge-data/drugforge/data/operators/state_expanders/tautomer_expander.py @@ -1,9 +1,7 @@ from typing import Literal from drugforge.data.backend.openeye import clear_SD_data, oechem, oequacpac -from drugforge.data.operators.state_expanders.state_expander import ( - StateExpanderBase, -) +from drugforge.data.operators.state_expanders.state_expander import StateExpanderBase from drugforge.data.schema.ligand import Ligand from pydantic.v1 import Field diff --git a/drugforge-data/drugforge/data/readers/structure_dir.py b/drugforge-data/drugforge/data/readers/structure_dir.py index 36e31bae..7932bd1c 100644 --- a/drugforge-data/drugforge/data/readers/structure_dir.py +++ b/drugforge-data/drugforge/data/readers/structure_dir.py @@ -4,10 +4,7 @@ import dask from drugforge.data.schema.complex import Complex -from drugforge.data.util.dask_utils import ( - FailureMode, - actualise_dask_delayed_iterable, -) +from drugforge.data.util.dask_utils import FailureMode, actualise_dask_delayed_iterable from pydantic.v1 import BaseModel, Field, validator logger = logging.getLogger(__name__) diff --git a/drugforge-data/drugforge/data/schema/complex.py b/drugforge-data/drugforge/data/schema/complex.py index f2028961..a5fee442 100644 --- a/drugforge-data/drugforge/data/schema/complex.py +++ b/drugforge-data/drugforge/data/schema/complex.py @@ -9,12 +9,11 @@ load_openeye_pdb, oechem, save_openeye_pdb, - split_openeye_mol + split_openeye_mol, ) from drugforge.data.schema.ligand import Ligand -from drugforge.data.schema.schema_base import DataModelAbstractBase +from drugforge.data.schema.schema_base import DataModelAbstractBase, MoleculeFilter from drugforge.data.schema.target import Target -from drugforge.data.schema.schema_base import MoleculeFilter from pydantic.v1 import Field logger = logging.getLogger(__name__) @@ -115,5 +114,3 @@ def to_combined_oemol(self): @property def hash(self): return f"{self.target.hash}+{self.ligand.fixed_inchikey}" - - diff --git a/drugforge-data/drugforge/data/schema/ligand.py b/drugforge-data/drugforge/data/schema/ligand.py index 05c7e28c..b3901446 100644 --- a/drugforge-data/drugforge/data/schema/ligand.py +++ b/drugforge-data/drugforge/data/schema/ligand.py @@ -197,9 +197,7 @@ def from_oemol(cls, mol: oechem.OEMol, **kwargs) -> "Ligand": Create a Ligand from an OEMol extracting all SD tags into the internal model """ from drugforge.data.backend.openeye import get_SD_data - from drugforge.data.util.data_conversion import ( - get_first_value_of_dict_of_lists, - ) + from drugforge.data.util.data_conversion import get_first_value_of_dict_of_lists # work with a copy as we change the state of the molecule input_mol = oechem.OEMol(mol) @@ -395,7 +393,9 @@ def to_openfe(self) -> "gufe.components.SmallMoleculeComponent": return gufe.components.SmallMoleculeComponent.from_rdkit(self.to_rdkit()) @classmethod - def from_openfe(cls, mol: "gufe.components.SmallMoleculeComponent", **kwargs) -> "Ligand": + def from_openfe( + cls, mol: "gufe.components.SmallMoleculeComponent", **kwargs + ) -> "Ligand": """ Create a Ligand from an openfe SmallMoleculeComponent """ @@ -568,9 +568,7 @@ def set_SD_data(self, data: dict[str, Union[str, list]]) -> None: new_data[k] = v # update tags and conf_tags! - from drugforge.data.util.data_conversion import ( - get_first_value_of_dict_of_lists, - ) + from drugforge.data.util.data_conversion import get_first_value_of_dict_of_lists self.conf_tags.update(new_data) self.tags.update(get_first_value_of_dict_of_lists(new_data)) diff --git a/drugforge-data/drugforge/data/schema/target.py b/drugforge-data/drugforge/data/schema/target.py index b1b1cd0f..b74cf097 100644 --- a/drugforge-data/drugforge/data/schema/target.py +++ b/drugforge-data/drugforge/data/schema/target.py @@ -10,15 +10,15 @@ split_openeye_mol, ) from drugforge.data.schema.identifiers import TargetIdentifiers -from pydantic.v1 import Field, root_validator - from drugforge.data.schema.schema_base import ( DataModelAbstractBase, DataStorageType, + MoleculeFilter, check_strings_for_equality_with_exclusion, schema_dict_get_val_overload, - write_file_directly, MoleculeFilter, + write_file_directly, ) +from pydantic.v1 import Field, root_validator logger = logging.getLogger(__name__) @@ -125,5 +125,3 @@ def crystal_symmetry(self): Get the crystal symmetry of the target """ return oechem.OEGetCrystalSymmetry(self.to_oemol()) - - diff --git a/drugforge-data/drugforge/data/scripts/download_cdd_data.py b/drugforge-data/drugforge/data/scripts/download_cdd_data.py index b9be1e7d..d65c7e02 100644 --- a/drugforge-data/drugforge/data/scripts/download_cdd_data.py +++ b/drugforge-data/drugforge/data/scripts/download_cdd_data.py @@ -6,9 +6,7 @@ import logging import os -from drugforge.data.services.cdd.cdd_download import ( # noqa: E402 - download_molecules, -) +from drugforge.data.services.cdd.cdd_download import download_molecules # noqa: E402 ################################################################################ diff --git a/drugforge-data/drugforge/data/services/fragalysis/fragalysis_reader.py b/drugforge-data/drugforge/data/services/fragalysis/fragalysis_reader.py index 2d7f8eeb..f5ee0b45 100644 --- a/drugforge-data/drugforge/data/services/fragalysis/fragalysis_reader.py +++ b/drugforge-data/drugforge/data/services/fragalysis/fragalysis_reader.py @@ -8,10 +8,7 @@ import dask import pandas from drugforge.data.schema.complex import Complex -from drugforge.data.util.dask_utils import ( - FailureMode, - actualise_dask_delayed_iterable, -) +from drugforge.data.util.dask_utils import FailureMode, actualise_dask_delayed_iterable from pydantic.v1 import BaseModel, Field, root_validator, validator logger = logging.getLogger(__name__) diff --git a/drugforge-data/drugforge/data/services/postera/molecule_set.py b/drugforge-data/drugforge/data/services/postera/molecule_set.py index aab21c4c..f4956781 100644 --- a/drugforge-data/drugforge/data/services/postera/molecule_set.py +++ b/drugforge-data/drugforge/data/services/postera/molecule_set.py @@ -3,12 +3,11 @@ from typing import Dict, Optional, Tuple, Union # noqa: F401 import pandas as pd +from drugforge.data.services.postera.manifold_data_validation import ManifoldAllowedTags from drugforge.data.services.web_utils import _BaseWebAPI from drugforge.data.util.stringenum import StringEnum from typing_extensions import TypedDict -from drugforge.data.services.postera.manifold_data_validation import ManifoldAllowedTags - logger = logging.getLogger(__name__) diff --git a/drugforge-data/drugforge/data/testing/test_files.yaml b/drugforge-data/drugforge/data/testing/test_files.yaml index ea43e630..6e4f361f 100644 --- a/drugforge-data/drugforge/data/testing/test_files.yaml +++ b/drugforge-data/drugforge/data/testing/test_files.yaml @@ -379,7 +379,7 @@ files: - resource: spectrum_dir/YP_009944273_1_unrelaxed_rank_001_alphafold2_multimer_v3_model_1_seed_000.pdb sha256hash: 32b5758b7c12e02fd52177c3ebd323bbf5c8bd06dcbcd82ef89042df10ae346d - resource: spectrum_dir/YP_010229075_1_unrelaxed_rank_001_alphafold2_multimer_v3_model_1_seed_000.pdb - sha256hash: 5fb77395f9d65add9d52c4d8ba83195a771fd4ea5c6020b6f9b8d5eaf446f274 + sha256hash: 5fb77395f9d65add9d52c4d8ba83195a771fd4ea5c6020b6f9b8d5eaf446f274 - resource: spectrum_dir/YP_009725295_1_unrelaxed_rank_001_alphafold2_multimer_v3_model_1_seed_000.pdb sha256hash: 5eadcaa47f507281f80eb3cd8a84453dbd5012e549ef6151c808f56bad1dfc7b diff --git a/drugforge-data/drugforge/data/tests/aws/conftest.py b/drugforge-data/drugforge/data/tests/aws/conftest.py index 96e8d644..241552f6 100644 --- a/drugforge-data/drugforge/data/tests/aws/conftest.py +++ b/drugforge-data/drugforge/data/tests/aws/conftest.py @@ -1,8 +1,8 @@ import os import pytest -from drugforge.data.services.aws.s3 import S3 from boto3.session import Session +from drugforge.data.services.aws.s3 import S3 from moto.server import ThreadedMotoServer diff --git a/drugforge-data/drugforge/data/tests/test_complex_schema.py b/drugforge-data/drugforge/data/tests/test_complex_schema.py index 4838e506..5e066172 100644 --- a/drugforge-data/drugforge/data/tests/test_complex_schema.py +++ b/drugforge-data/drugforge/data/tests/test_complex_schema.py @@ -109,5 +109,3 @@ def test_complex_json_file_roundtrip(complex_pdb, tmp_path): c2 = Complex.from_json_file(path) assert c1 == c2 - - diff --git a/drugforge-data/drugforge/data/tests/test_dask_clusters.py b/drugforge-data/drugforge/data/tests/test_dask_clusters.py index a05be473..f7575c86 100644 --- a/drugforge-data/drugforge/data/tests/test_dask_clusters.py +++ b/drugforge-data/drugforge/data/tests/test_dask_clusters.py @@ -1,8 +1,8 @@ import time import pytest -from drugforge.data.util.dask_utils import DaskType, make_dask_client_meta from dask.distributed import Client +from drugforge.data.util.dask_utils import DaskType, make_dask_client_meta @pytest.mark.parametrize("loglevel", ["DEBUG", 10]) diff --git a/drugforge-data/drugforge/data/tests/test_data_cli.py b/drugforge-data/drugforge/data/tests/test_data_cli.py index 96452792..15e2cd6a 100644 --- a/drugforge-data/drugforge/data/tests/test_data_cli.py +++ b/drugforge-data/drugforge/data/tests/test_data_cli.py @@ -2,9 +2,9 @@ import pandas import pytest +from click.testing import CliRunner from drugforge.data.cli.cli import data as cli from drugforge.data.testing.test_resources import fetch_test_file -from click.testing import CliRunner @pytest.fixture(scope="session") diff --git a/drugforge-data/drugforge/data/tests/test_fragalysis.py b/drugforge-data/drugforge/data/tests/test_fragalysis.py index 5773d2f2..4c0cb132 100644 --- a/drugforge-data/drugforge/data/tests/test_fragalysis.py +++ b/drugforge-data/drugforge/data/tests/test_fragalysis.py @@ -6,6 +6,7 @@ import traceback import pytest +from click.testing import CliRunner from drugforge.data.cli.cli import data as cli from drugforge.data.schema.legacy import CrystalCompoundData from drugforge.data.services.fragalysis.fragalysis_download import ( @@ -16,7 +17,6 @@ parse_fragalysis, ) from drugforge.data.testing.test_resources import fetch_test_file -from click.testing import CliRunner def click_success(result): diff --git a/drugforge-data/drugforge/data/tests/test_ligand_schema.py b/drugforge-data/drugforge/data/tests/test_ligand_schema.py index 1e9a5d49..6146161e 100644 --- a/drugforge-data/drugforge/data/tests/test_ligand_schema.py +++ b/drugforge-data/drugforge/data/tests/test_ligand_schema.py @@ -1,11 +1,7 @@ from uuid import uuid4 import pytest -from drugforge.data.backend.openeye import ( - get_SD_data, - load_openeye_sdf, - set_SD_data, -) +from drugforge.data.backend.openeye import get_SD_data, load_openeye_sdf, set_SD_data from drugforge.data.schema.experimental import ExperimentalCompoundData from drugforge.data.schema.identifiers import LigandIdentifiers, LigandProvenance from drugforge.data.schema.ligand import Ligand diff --git a/drugforge-data/drugforge/data/tests/test_multi_expansion.py b/drugforge-data/drugforge/data/tests/test_multi_expansion.py index cb876e8d..f1290acb 100644 --- a/drugforge-data/drugforge/data/tests/test_multi_expansion.py +++ b/drugforge-data/drugforge/data/tests/test_multi_expansion.py @@ -1,11 +1,7 @@ import pytest from drugforge.data.backend.openeye import oe_smiles_roundtrip -from drugforge.data.operators.state_expanders.protomer_expander import ( - ProtomerExpander, -) -from drugforge.data.operators.state_expanders.state_expander import ( - StateExpansionSet, -) +from drugforge.data.operators.state_expanders.protomer_expander import ProtomerExpander +from drugforge.data.operators.state_expanders.state_expander import StateExpansionSet from drugforge.data.operators.state_expanders.stereo_expander import StereoExpander from drugforge.data.schema.ligand import Ligand diff --git a/drugforge-data/drugforge/data/tests/test_protomer_tautomer_expander.py b/drugforge-data/drugforge/data/tests/test_protomer_tautomer_expander.py index 9c48d344..dee4f236 100644 --- a/drugforge-data/drugforge/data/tests/test_protomer_tautomer_expander.py +++ b/drugforge-data/drugforge/data/tests/test_protomer_tautomer_expander.py @@ -1,11 +1,7 @@ import pytest from drugforge.data.backend.openeye import oe_smiles_roundtrip -from drugforge.data.operators.state_expanders.protomer_expander import ( - ProtomerExpander, -) -from drugforge.data.operators.state_expanders.tautomer_expander import ( - TautomerExpander, -) +from drugforge.data.operators.state_expanders.protomer_expander import ProtomerExpander +from drugforge.data.operators.state_expanders.tautomer_expander import TautomerExpander from drugforge.data.schema.ligand import Ligand diff --git a/drugforge-data/drugforge/data/tests/test_state_expanders.py b/drugforge-data/drugforge/data/tests/test_state_expanders.py index 535af6df..960afb14 100644 --- a/drugforge-data/drugforge/data/tests/test_state_expanders.py +++ b/drugforge-data/drugforge/data/tests/test_state_expanders.py @@ -7,9 +7,7 @@ ProtomerExpander, ) from drugforge.data.operators.state_expanders.stereo_expander import StereoExpander -from drugforge.data.operators.state_expanders.tautomer_expander import ( - TautomerExpander, -) +from drugforge.data.operators.state_expanders.tautomer_expander import TautomerExpander from drugforge.data.schema.ligand import Ligand from drugforge.data.testing.test_resources import fetch_test_file diff --git a/drugforge-data/drugforge/data/tests/test_structures_data.py b/drugforge-data/drugforge/data/tests/test_structures_data.py index 3cfd3bf2..6cf240e8 100644 --- a/drugforge-data/drugforge/data/tests/test_structures_data.py +++ b/drugforge-data/drugforge/data/tests/test_structures_data.py @@ -38,10 +38,7 @@ def test_download_cif_assembly(self, tmp_path): def test_load_save_openeye_pdb(self, tmp_path): """Test that a downloaded pdb file can be loaded with the openeye-specific functions""" - from drugforge.data.backend.openeye import ( - load_openeye_pdb, - save_openeye_pdb, - ) + from drugforge.data.backend.openeye import load_openeye_pdb, save_openeye_pdb pdb_id = "8DGY" file_path = download_pdb_structure(pdb_id, tmp_path, file_format="pdb") diff --git a/drugforge-data/drugforge/data/tests/test_target_schema.py b/drugforge-data/drugforge/data/tests/test_target_schema.py index 344fe80e..f3a04dd8 100644 --- a/drugforge-data/drugforge/data/tests/test_target_schema.py +++ b/drugforge-data/drugforge/data/tests/test_target_schema.py @@ -158,4 +158,4 @@ def test_target_moonshot_pdb_processed_no_ligand(moonshot_pdb): oechem.OESplitMolComplex(lig, prot, wat, other, mol, opts) assert lig.NumAtoms() == 0 assert prot.NumAtoms() != 0 - assert wat.NumAtoms() == 0 \ No newline at end of file + assert wat.NumAtoms() == 0 diff --git a/drugforge-data/drugforge/data/util/dask_utils.py b/drugforge-data/drugforge/data/util/dask_utils.py index 4cd8d0fb..8780c879 100644 --- a/drugforge-data/drugforge/data/util/dask_utils.py +++ b/drugforge-data/drugforge/data/util/dask_utils.py @@ -6,14 +6,11 @@ import dask import psutil -from drugforge.data.util.execution_utils import ( - get_platform, - hyperthreading_is_enabled, -) -from drugforge.data.util.stringenum import StringEnum from dask import config as cfg from dask.utils import parse_timedelta from distributed import Client, LocalCluster +from drugforge.data.util.execution_utils import get_platform, hyperthreading_is_enabled +from drugforge.data.util.stringenum import StringEnum logger = logging.getLogger(__name__) diff --git a/drugforge-dataviz/drugforge/dataviz/html_viz.py b/drugforge-dataviz/drugforge/dataviz/html_viz.py index 94502c77..73c2d248 100644 --- a/drugforge-dataviz/drugforge/dataviz/html_viz.py +++ b/drugforge-dataviz/drugforge/dataviz/html_viz.py @@ -19,11 +19,6 @@ oemol_to_sdf_string, openeye_perceive_residues, ) -from drugforge.dataviz.plip import ( - get_interactions_plip, - make_color_res_fitness, - make_color_res_subpockets, -) from drugforge.data.metadata.resources import active_site_chains, master_structures from drugforge.data.schema.complex import Complex from drugforge.data.schema.ligand import Ligand @@ -34,6 +29,11 @@ from drugforge.data.util.dask_utils import backend_wrapper, dask_vmap from drugforge.data.util.logging import HiddenPrint from drugforge.dataviz._html_blocks import HTMLBlockData +from drugforge.dataviz.plip import ( + get_interactions_plip, + make_color_res_fitness, + make_color_res_subpockets, +) from drugforge.dataviz.visualizer import VisualizerBase from drugforge.docking.docking import DockingResult from drugforge.docking.docking_data_validation import DockingResultCols diff --git a/drugforge-dataviz/drugforge/dataviz/plip.py b/drugforge-dataviz/drugforge/dataviz/plip.py index 7ca16b96..b1832c8d 100644 --- a/drugforge-dataviz/drugforge/dataviz/plip.py +++ b/drugforge-dataviz/drugforge/dataviz/plip.py @@ -236,7 +236,9 @@ def get_interactions_plip(protein, pose, color_method, target) -> dict: # load the XML produced by PLIP that contains all the interaction data. intn_dict_xml = xmltodict.parse( - ET.tostring(ET.parse(os.path.join(tmpdirname, "tmp_complex_report.xml")).getroot()) + ET.tostring( + ET.parse(os.path.join(tmpdirname, "tmp_complex_report.xml")).getroot() + ) ) intn_dict = {} diff --git a/drugforge-dataviz/drugforge/dataviz/tests/test_dataviz_cli.py b/drugforge-dataviz/drugforge/dataviz/tests/test_dataviz_cli.py index 8214f009..71dd1c43 100644 --- a/drugforge-dataviz/drugforge/dataviz/tests/test_dataviz_cli.py +++ b/drugforge-dataviz/drugforge/dataviz/tests/test_dataviz_cli.py @@ -1,8 +1,8 @@ import traceback import pytest -from drugforge.dataviz.cli import visualization from click.testing import CliRunner +from drugforge.dataviz.cli import visualization def click_success(result): diff --git a/drugforge-dataviz/drugforge/dataviz/tests/test_fintscore.py b/drugforge-dataviz/drugforge/dataviz/tests/test_fintscore.py index e2db9f8e..d1626188 100644 --- a/drugforge-dataviz/drugforge/dataviz/tests/test_fintscore.py +++ b/drugforge-dataviz/drugforge/dataviz/tests/test_fintscore.py @@ -1,9 +1,9 @@ from pathlib import Path from drugforge.data.backend.openeye import load_openeye_pdb -from drugforge.dataviz.plip import compute_fint_score from drugforge.data.readers.molfile import MolFileFactory from drugforge.data.testing.test_resources import fetch_test_file +from drugforge.dataviz.plip import compute_fint_score def test_fint_score(): diff --git a/drugforge-docking/drugforge/docking/docking.py b/drugforge-docking/drugforge/docking/docking.py index 5631803f..ab3c8012 100644 --- a/drugforge-docking/drugforge/docking/docking.py +++ b/drugforge-docking/drugforge/docking/docking.py @@ -13,15 +13,15 @@ combine_protein_ligand, oechem, save_openeye_pdb, - split_openeye_design_unit + split_openeye_design_unit, ) from drugforge.data.schema.complex import Complex -from drugforge.modeling.schema import PreppedComplex from drugforge.data.schema.ligand import Ligand from drugforge.data.schema.pairs import CompoundStructurePair from drugforge.data.schema.sets import MultiStructureBase from drugforge.data.schema.target import Target from drugforge.data.util.dask_utils import BackendType, FailureMode +from drugforge.modeling.schema import PreppedComplex from pydantic.v1 import BaseModel, Field, PositiveFloat logger = logging.getLogger(__name__) diff --git a/drugforge-docking/drugforge/docking/fint_scorer.py b/drugforge-docking/drugforge/docking/fint_scorer.py index 344887ae..1249a2c6 100644 --- a/drugforge-docking/drugforge/docking/fint_scorer.py +++ b/drugforge-docking/drugforge/docking/fint_scorer.py @@ -1,22 +1,21 @@ from pathlib import Path from typing import ClassVar, Union -from multimethod import multimethod -from pydantic.v1 import Field, validator - +from drugforge.data.schema.complex import Complex +from drugforge.data.services.postera.manifold_data_validation import TargetTags +from drugforge.data.util.dask_utils import backend_wrapper, dask_vmap from drugforge.dataviz.plip import compute_fint_score from drugforge.docking.docking import DockingResult from drugforge.docking.scorer import ( + Score, ScorerBase, ScoreType, ScoreUnits, - Score, _get_disk_path_from_docking_result, ) from drugforge.spectrum.fitness import target_has_fitness_data -from drugforge.data.schema.complex import Complex -from drugforge.data.services.postera.manifold_data_validation import TargetTags -from drugforge.data.util.dask_utils import dask_vmap, backend_wrapper +from multimethod import multimethod +from pydantic.v1 import Field, validator class FINTScorer(ScorerBase): diff --git a/drugforge-docking/drugforge/docking/meta_scorer.py b/drugforge-docking/drugforge/docking/meta_scorer.py index 71de2e9a..24e76bb5 100644 --- a/drugforge-docking/drugforge/docking/meta_scorer.py +++ b/drugforge-docking/drugforge/docking/meta_scorer.py @@ -1,9 +1,8 @@ import numpy as np -from pydantic.v1 import BaseModel, Field - +from drugforge.data.util.dask_utils import BackendType, FailureMode from drugforge.docking.docking import DockingResult -from drugforge.docking.scorer import ScorerBase, Score -from drugforge.data.util.dask_utils import FailureMode, BackendType +from drugforge.docking.scorer import Score, ScorerBase +from pydantic.v1 import BaseModel, Field class MetaScorer(BaseModel): diff --git a/drugforge-docking/drugforge/docking/ml_scorer.py b/drugforge-docking/drugforge/docking/ml_scorer.py index 8043d954..d9d0febe 100644 --- a/drugforge-docking/drugforge/docking/ml_scorer.py +++ b/drugforge-docking/drugforge/docking/ml_scorer.py @@ -1,25 +1,24 @@ from pathlib import Path -from typing import ClassVar, Optional, Any, Union - -from mtenn.config import ModelType -from multimethod import multimethod -from pydantic.v1 import Field +from typing import Any, ClassVar, Optional, Union +from drugforge.data.schema.complex import Complex +from drugforge.data.schema.ligand import Ligand +from drugforge.data.services.postera.manifold_data_validation import TargetTags +from drugforge.data.util.dask_utils import backend_wrapper, dask_vmap from drugforge.docking.docking import DockingResult from drugforge.docking.scorer import ( - ScoreType, + Score, ScorerBase, + ScoreType, ScoreUnits, - logger, - Score, _get_disk_path_from_docking_result, + logger, ) from drugforge.ml.inference import InferenceBase, get_inference_cls_from_model_type from drugforge.ml.models import MLModelSpecBase -from drugforge.data.schema.complex import Complex -from drugforge.data.schema.ligand import Ligand -from drugforge.data.services.postera.manifold_data_validation import TargetTags -from drugforge.data.util.dask_utils import dask_vmap, backend_wrapper +from mtenn.config import ModelType +from multimethod import multimethod +from pydantic.v1 import Field def endpoint_and_model_type_to_score_type(endpoint: str, model_type: str) -> ScoreType: diff --git a/drugforge-docking/drugforge/docking/schema/pose_generation.py b/drugforge-docking/drugforge/docking/schema/pose_generation.py index b8400dab..4d8d677d 100644 --- a/drugforge-docking/drugforge/docking/schema/pose_generation.py +++ b/drugforge-docking/drugforge/docking/schema/pose_generation.py @@ -12,8 +12,8 @@ set_SD_data, smiles_to_oemol, ) -from drugforge.modeling.schema import PreppedComplex from drugforge.data.schema.ligand import Ligand +from drugforge.modeling.schema import PreppedComplex from pydantic.v1 import BaseModel, Field, PositiveFloat, PositiveInt from rdkit import Chem, RDLogger diff --git a/drugforge-docking/drugforge/docking/selectors/mcs_selector.py b/drugforge-docking/drugforge/docking/selectors/mcs_selector.py index 35783bd2..e59f23ed 100644 --- a/drugforge-docking/drugforge/docking/selectors/mcs_selector.py +++ b/drugforge-docking/drugforge/docking/selectors/mcs_selector.py @@ -3,18 +3,15 @@ from typing import ClassVar, Union import numpy as np +from dask import delayed from drugforge.data.backend.openeye import oechem -from drugforge.docking.selectors.selector import SelectorBase from drugforge.data.schema.complex import Complex, ComplexBase -from drugforge.modeling.schema import PreppedComplex from drugforge.data.schema.ligand import Ligand from drugforge.data.schema.pairs import CompoundStructurePair -from drugforge.data.util.dask_utils import ( - FailureMode, - actualise_dask_delayed_iterable, -) +from drugforge.data.util.dask_utils import FailureMode, actualise_dask_delayed_iterable from drugforge.docking.docking import DockingInputPair # TODO: move to backend -from dask import delayed +from drugforge.docking.selectors.selector import SelectorBase +from drugforge.modeling.schema import PreppedComplex from pydantic.v1 import Field from rdkit import Chem, rdBase from rdkit.Chem import rdRascalMCES diff --git a/drugforge-docking/drugforge/docking/selectors/pairwise_selector.py b/drugforge-docking/drugforge/docking/selectors/pairwise_selector.py index 571f8bf8..40aba76c 100644 --- a/drugforge-docking/drugforge/docking/selectors/pairwise_selector.py +++ b/drugforge-docking/drugforge/docking/selectors/pairwise_selector.py @@ -2,11 +2,11 @@ from itertools import product from typing import ClassVar, Union -from drugforge.docking.selectors.selector import SelectorBase from drugforge.data.schema.complex import Complex, ComplexBase -from drugforge.modeling.schema import PreppedComplex from drugforge.data.schema.ligand import ChemicalRelationship, Ligand from drugforge.data.schema.pairs import CompoundStructurePair +from drugforge.docking.selectors.selector import SelectorBase +from drugforge.modeling.schema import PreppedComplex logger = logging.getLogger(__name__) diff --git a/drugforge-docking/drugforge/docking/selectors/selector.py b/drugforge-docking/drugforge/docking/selectors/selector.py index 4806249e..bab9affe 100644 --- a/drugforge-docking/drugforge/docking/selectors/selector.py +++ b/drugforge-docking/drugforge/docking/selectors/selector.py @@ -3,14 +3,11 @@ import dask from drugforge.data.schema.complex import Complex -from drugforge.modeling.schema import PreppedComplex from drugforge.data.schema.ligand import Ligand from drugforge.data.schema.pairs import CompoundStructurePair -from drugforge.data.util.dask_utils import ( - FailureMode, - actualise_dask_delayed_iterable, -) +from drugforge.data.util.dask_utils import FailureMode, actualise_dask_delayed_iterable from drugforge.docking.docking import DockingInputPair # TODO: move to backend +from drugforge.modeling.schema import PreppedComplex from pydantic.v1 import BaseModel diff --git a/drugforge-docking/drugforge/docking/tests/conftest.py b/drugforge-docking/drugforge/docking/tests/conftest.py index 59ffeb6f..42f494c5 100644 --- a/drugforge-docking/drugforge/docking/tests/conftest.py +++ b/drugforge-docking/drugforge/docking/tests/conftest.py @@ -1,11 +1,11 @@ import pytest from drugforge.data.backend.openeye import oechem from drugforge.data.schema.complex import Complex -from drugforge.modeling.schema import PreppedComplex from drugforge.data.schema.ligand import Ligand from drugforge.data.testing.test_resources import fetch_test_file from drugforge.docking.docking import DockingInputMultiStructure, DockingInputPair from drugforge.docking.openeye import POSITDockingResults +from drugforge.modeling.schema import PreppedComplex @pytest.fixture() diff --git a/drugforge-docking/drugforge/docking/tests/test_pairs.py b/drugforge-docking/drugforge/docking/tests/test_pairs.py index 89099d72..ee71a463 100644 --- a/drugforge-docking/drugforge/docking/tests/test_pairs.py +++ b/drugforge-docking/drugforge/docking/tests/test_pairs.py @@ -1,10 +1,10 @@ import pytest from drugforge.data.schema.complex import Complex -from drugforge.modeling.schema import PreppedComplex from drugforge.data.schema.ligand import Ligand from drugforge.data.schema.pairs import CompoundStructurePair from drugforge.data.testing.test_resources import fetch_test_file from drugforge.docking.docking import DockingInputPair # TODO: move to data +from drugforge.modeling.schema import PreppedComplex @pytest.fixture(scope="session") diff --git a/drugforge-docking/drugforge/docking/tests/test_scorers.py b/drugforge-docking/drugforge/docking/tests/test_scorers.py index 1ed22a7b..ca9d7439 100644 --- a/drugforge-docking/drugforge/docking/tests/test_scorers.py +++ b/drugforge-docking/drugforge/docking/tests/test_scorers.py @@ -1,12 +1,10 @@ import pytest -from drugforge.docking.scorer import ( - ChemGauss4Scorer, -) from drugforge.docking.fint_scorer import FINTScorer # TODO: undo this comment when xfail is removed # from drugforge.docking.ml_scorer import GATScorer, SchnetScorer, E3NNScorer from drugforge.docking.meta_scorer import MetaScorer +from drugforge.docking.scorer import ChemGauss4Scorer # parametrize over fixtures diff --git a/drugforge-docking/drugforge/docking/tests/test_selectors.py b/drugforge-docking/drugforge/docking/tests/test_selectors.py index c306d1c0..088d0be3 100644 --- a/drugforge-docking/drugforge/docking/tests/test_selectors.py +++ b/drugforge-docking/drugforge/docking/tests/test_selectors.py @@ -1,23 +1,21 @@ import pytest -from drugforge.docking.selectors.mcs_selector import ( - MCSSelector, - RascalMCESSelector, -) +from drugforge.data.schema.complex import Complex +from drugforge.data.schema.ligand import Ligand +from drugforge.data.schema.pairs import CompoundStructurePair +from drugforge.data.services.cdd.cdd_api import CDDAPI +from drugforge.data.services.services_config import CDDSettings +from drugforge.data.testing.test_resources import fetch_test_file +from drugforge.docking.docking import DockingInputPair # TODO: move to data +from drugforge.docking.selectors.mcs_selector import MCSSelector, RascalMCESSelector from drugforge.docking.selectors.pairwise_selector import ( LeaveOneOutSelector, LeaveSimilarOutSelector, PairwiseSelector, SelfDockingSelector, ) -from drugforge.data.schema.pairs import CompoundStructurePair -from drugforge.docking.docking import DockingInputPair # TODO: move to data -from drugforge.data.schema.complex import Complex -from drugforge.data.schema.ligand import Ligand -from drugforge.data.services.cdd.cdd_api import CDDAPI -from drugforge.data.services.services_config import CDDSettings -from drugforge.data.testing.test_resources import fetch_test_file from drugforge.modeling.schema import PreppedComplex + @pytest.fixture(scope="session") def all_mpro_fns(): return [ @@ -46,6 +44,7 @@ def complexes(all_mpro_fns): for struct in all_pdbs ] + @pytest.fixture(scope="session") def prepped_complexes(complexes): # kinda expensive to make, so let's just do the first 2 diff --git a/drugforge-ml/drugforge/ml/cli_args.py b/drugforge-ml/drugforge/ml/cli_args.py index 1156eda5..5cf49669 100644 --- a/drugforge-ml/drugforge/ml/cli_args.py +++ b/drugforge-ml/drugforge/ml/cli_args.py @@ -3,11 +3,7 @@ import click import torch from drugforge.data.util.utils import MOONSHOT_CDD_ID_REGEX, MPRO_ID_REGEX -from drugforge.ml.config import ( - DatasetSplitterType, - EarlyStoppingType, - OptimizerType, -) +from drugforge.ml.config import DatasetSplitterType, EarlyStoppingType, OptimizerType from mtenn.config import CombinationConfig, ReadoutConfig, StrategyConfig diff --git a/drugforge-ml/drugforge/ml/cli_sweep.py b/drugforge-ml/drugforge/ml/cli_sweep.py index 83eb2baa..350262b1 100644 --- a/drugforge-ml/drugforge/ml/cli_sweep.py +++ b/drugforge-ml/drugforge/ml/cli_sweep.py @@ -32,11 +32,7 @@ wandb_args, weights_path, ) -from drugforge.ml.config import ( - DatasetSplitterType, - EarlyStoppingType, - OptimizerType, -) +from drugforge.ml.config import DatasetSplitterType, EarlyStoppingType, OptimizerType from drugforge.ml.sweep import Sweeper from drugforge.ml.trainer import Trainer from mtenn.config import CombinationConfig, ModelType, ReadoutConfig, StrategyConfig diff --git a/drugforge-ml/drugforge/ml/inference.py b/drugforge-ml/drugforge/ml/inference.py index df54cb6c..f05580a8 100644 --- a/drugforge-ml/drugforge/ml/inference.py +++ b/drugforge-ml/drugforge/ml/inference.py @@ -6,6 +6,9 @@ import mtenn import numpy as np import torch + +# static import of models from base yaml here +from dgllife.utils import CanonicalAtomFeaturizer from drugforge.data.backend.openeye import oechem from drugforge.data.schema.complex import Complex from drugforge.data.schema.ligand import Ligand @@ -19,9 +22,6 @@ MLModelSpec, MLModelSpecBase, ) - -# static import of models from base yaml here -from dgllife.utils import CanonicalAtomFeaturizer from mtenn.config import E3NNModelConfig, GATModelConfig, ModelType, SchNetModelConfig from pydantic.v1 import BaseModel, Field diff --git a/drugforge-ml/drugforge/ml/tests/conftest.py b/drugforge-ml/drugforge/ml/tests/conftest.py index c3c61a51..15dca97a 100644 --- a/drugforge-ml/drugforge/ml/tests/conftest.py +++ b/drugforge-ml/drugforge/ml/tests/conftest.py @@ -1,9 +1,9 @@ import os import pytest +from dgllife.utils import CanonicalAtomFeaturizer from drugforge.data.schema.experimental import ExperimentalCompoundData from drugforge.ml.dataset import GraphDataset -from dgllife.utils import CanonicalAtomFeaturizer from rdkit import Chem @@ -110,4 +110,6 @@ def test_data(graph_dataset): @pytest.fixture() def remote_ensemble_manifest_url(): - return "https://d1ibwnbvfa7iey.cloudfront.net/test_manifest/asap_ensemble_models.yaml" + return ( + "https://d1ibwnbvfa7iey.cloudfront.net/test_manifest/asap_ensemble_models.yaml" + ) diff --git a/drugforge-ml/drugforge/ml/tests/test_ml_cli.py b/drugforge-ml/drugforge/ml/tests/test_ml_cli.py index 5ac46007..addd6395 100644 --- a/drugforge-ml/drugforge/ml/tests/test_ml_cli.py +++ b/drugforge-ml/drugforge/ml/tests/test_ml_cli.py @@ -2,12 +2,12 @@ import pickle as pkl import pytest +from click.testing import CliRunner from drugforge.data.testing.test_resources import fetch_test_file from drugforge.ml.cli import ml as cli from drugforge.ml.config import DatasetConfig from drugforge.ml.schema import TrainingPredictionTracker from drugforge.ml.trainer import Trainer -from click.testing import CliRunner @pytest.fixture(scope="session") diff --git a/drugforge-ml/drugforge/ml/tests/test_mlops_cli.py b/drugforge-ml/drugforge/ml/tests/test_mlops_cli.py index 1ea6300a..80c44d4c 100644 --- a/drugforge-ml/drugforge/ml/tests/test_mlops_cli.py +++ b/drugforge-ml/drugforge/ml/tests/test_mlops_cli.py @@ -3,9 +3,9 @@ from unittest.mock import Mock, patch import pandas as pd +from click.testing import CliRunner from drugforge.data.testing.test_resources import fetch_test_file from drugforge.ml.cli_mlops import mlops as cli -from click.testing import CliRunner def click_success(result): diff --git a/drugforge-modeling/drugforge/modeling/modeling.py b/drugforge-modeling/drugforge/modeling/modeling.py index 317a9cd1..b3f25f4c 100644 --- a/drugforge-modeling/drugforge/modeling/modeling.py +++ b/drugforge-modeling/drugforge/modeling/modeling.py @@ -471,5 +471,3 @@ def du_to_complex(du, include_solvent=False): complex_mol = openeye_perceive_residues(complex_mol) return complex_mol - - diff --git a/drugforge-modeling/drugforge/modeling/protein_prep.py b/drugforge-modeling/drugforge/modeling/protein_prep.py index a3a1173d..ab04cd97 100644 --- a/drugforge-modeling/drugforge/modeling/protein_prep.py +++ b/drugforge-modeling/drugforge/modeling/protein_prep.py @@ -6,14 +6,10 @@ import dask import yaml -from drugforge.data.backend.openeye import oechem +from drugforge.data.backend.openeye import oechem, split_openeye_design_unit from drugforge.data.schema.complex import Complex -from drugforge.modeling.schema import PreppedComplex, PreppedTarget from drugforge.data.schema.ligand import Ligand -from drugforge.data.util.dask_utils import ( - FailureMode, - actualise_dask_delayed_iterable, -) +from drugforge.data.util.dask_utils import FailureMode, actualise_dask_delayed_iterable from drugforge.data.util.stringenum import StringEnum from drugforge.data.util.utils import seqres_to_res_list from drugforge.modeling.modeling import ( @@ -22,7 +18,7 @@ spruce_protein, superpose_molecule, ) -from drugforge.data.backend.openeye import split_openeye_design_unit +from drugforge.modeling.schema import PreppedComplex, PreppedTarget from pydantic.v1 import BaseModel, Field if TYPE_CHECKING: diff --git a/drugforge-modeling/drugforge/modeling/schema.py b/drugforge-modeling/drugforge/modeling/schema.py index 06b8d2d9..bef29bc5 100644 --- a/drugforge-modeling/drugforge/modeling/schema.py +++ b/drugforge-modeling/drugforge/modeling/schema.py @@ -1,23 +1,28 @@ from __future__ import annotations from pathlib import Path -from typing import Optional, Any, Union - +from typing import Any, Optional, Union + +from drugforge.data.backend.openeye import ( + bytes64_to_oedu, + load_openeye_design_unit, + oedu_to_bytes64, + openeye_perceive_residues, + save_openeye_design_unit, + save_openeye_pdb, + split_openeye_design_unit, +) +from drugforge.data.schema.complex import Complex, ComplexBase +from drugforge.data.schema.identifiers import TargetIdentifiers +from drugforge.data.schema.ligand import Ligand +from drugforge.data.schema.schema_base import ( + DataModelAbstractBase, + DataStorageType, + schema_dict_get_val_overload, +) from openeye import oechem from pydantic.v1 import Field, root_validator -from drugforge.data.schema.complex import ComplexBase, Complex -from drugforge.data.schema.ligand import Ligand -from drugforge.data.backend.openeye import (oedu_to_bytes64, - bytes64_to_oedu, - load_openeye_design_unit, - save_openeye_design_unit, - split_openeye_design_unit, - openeye_perceive_residues, - save_openeye_pdb) -from drugforge.data.schema.identifiers import TargetIdentifiers -from drugforge.data.schema.schema_base import DataModelAbstractBase, DataStorageType, schema_dict_get_val_overload - class PreppedTarget(DataModelAbstractBase): """ @@ -26,7 +31,7 @@ class PreppedTarget(DataModelAbstractBase): target_name: str = Field(None, description="The name of the target") - ids: Optional[TargetIdentifiers] = Field( + ids: TargetIdentifiers | None = Field( None, description="TargetIdentifiers Schema for identifiers associated with this target", ) @@ -47,7 +52,7 @@ class PreppedTarget(DataModelAbstractBase): allow_mutation=False, ) - crystal_symmetry: Optional[Any] = Field( + crystal_symmetry: Any | None = Field( None, description="bounding box of the target, lost in oedu conversion so can be saved as attribute.", ) @@ -67,7 +72,7 @@ def _validate_at_least_one_id(cls, v): return v @classmethod - def from_oedu(cls, oedu: oechem.OEDesignUnit, **kwargs) -> "PreppedTarget": + def from_oedu(cls, oedu: oechem.OEDesignUnit, **kwargs) -> PreppedTarget: kwargs.pop("data", None) oedu_bytes = oedu_to_bytes64(oedu) return cls(data=oedu_bytes, **kwargs) @@ -76,12 +81,12 @@ def to_oedu(self) -> oechem.OEDesignUnit: return bytes64_to_oedu(self.data) @classmethod - def from_oedu_file(cls, oedu_file: Union[str, Path], **kwargs) -> "PreppedTarget": + def from_oedu_file(cls, oedu_file: str | Path, **kwargs) -> PreppedTarget: kwargs.pop("data", None) oedu = load_openeye_design_unit(oedu_file) return cls.from_oedu(oedu=oedu, **kwargs) - def to_oedu_file(self, filename: Union[str, Path]) -> None: + def to_oedu_file(self, filename: str | Path) -> None: oedu = self.to_oedu() save_openeye_design_unit(oedu, filename) @@ -105,6 +110,7 @@ def hash(self): return hashlib.sha256(self.data).hexdigest() + class PreppedComplex(ComplexBase): """ Schema for a Complex, containing both a PreppedTarget and Ligand @@ -168,4 +174,3 @@ def from_complex(cls, complex: Complex, prep_kwargs={}) -> PreppedComplex: def hash(self): # Using the target_hash instead hashing the OEDU bytes because prepping is stochastic return f"{self.target.target_hash}+{self.ligand.fixed_inchikey}" - diff --git a/drugforge-modeling/drugforge/modeling/tests/conftest.py b/drugforge-modeling/drugforge/modeling/tests/conftest.py index 5e0a94cb..31faa285 100644 --- a/drugforge-modeling/drugforge/modeling/tests/conftest.py +++ b/drugforge-modeling/drugforge/modeling/tests/conftest.py @@ -1,7 +1,8 @@ import pytest from drugforge.modeling.schema import PreppedComplex + @pytest.fixture(scope="session") def prepped_complexes(complexes): # kinda expensive to make, so let's just do the first 2 - return [PreppedComplex.from_complex(c) for c in complexes[:2]] \ No newline at end of file + return [PreppedComplex.from_complex(c) for c in complexes[:2]] diff --git a/drugforge-modeling/drugforge/modeling/tests/test_modeling.py b/drugforge-modeling/drugforge/modeling/tests/test_modeling.py index e94cf783..1cecfbd4 100644 --- a/drugforge-modeling/drugforge/modeling/tests/test_modeling.py +++ b/drugforge-modeling/drugforge/modeling/tests/test_modeling.py @@ -1,7 +1,7 @@ import pytest from drugforge.data.backend.openeye import load_openeye_pdb, oechem, split_openeye_mol -from drugforge.data.testing.test_resources import fetch_test_file from drugforge.data.schema.schema_base import MoleculeFilter +from drugforge.data.testing.test_resources import fetch_test_file @pytest.fixture() diff --git a/drugforge-modeling/drugforge/modeling/tests/test_protein_prep.py b/drugforge-modeling/drugforge/modeling/tests/test_protein_prep.py index d744e5b1..ddab8ab4 100644 --- a/drugforge-modeling/drugforge/modeling/tests/test_protein_prep.py +++ b/drugforge-modeling/drugforge/modeling/tests/test_protein_prep.py @@ -1,27 +1,28 @@ import os import pytest -from pydantic.v1 import ValidationError - +from drugforge.data.backend.openeye import load_openeye_design_unit from drugforge.data.schema.complex import Complex +from drugforge.data.schema.identifiers import TargetIdentifiers from drugforge.data.sequence import seqres_by_target from drugforge.data.services.postera.manifold_data_validation import TargetTags from drugforge.data.testing.test_resources import fetch_test_file from drugforge.modeling.protein_prep import ProteinPrepper from drugforge.modeling.schema import PreppedComplex, PreppedTarget -from drugforge.data.backend.openeye import load_openeye_design_unit -from drugforge.data.schema.identifiers import TargetIdentifiers +from pydantic.v1 import ValidationError @pytest.fixture def loop_db(): return fetch_test_file("fragalysis-mpro_spruce.loop_db") + @pytest.fixture(scope="session") def complex_pdb(): pdb = fetch_test_file("Mpro-P2660_0A_bound.pdb") return pdb + @pytest.fixture(scope="session") def cmplx(): return Complex.from_pdb( @@ -39,6 +40,7 @@ def prep_complex(): ligand_kwargs={"compound_name": "test2"}, ) + @pytest.fixture(scope="session") def complex_oedu(): oedu = fetch_test_file("Mpro-P2660_0A_bound-prepped_receptor.oedu") @@ -58,11 +60,13 @@ def structure_dir(all_structure_dir_fns): all_paths = [fetch_test_file(f) for f in all_structure_dir_fns] return all_paths[0].parent, all_paths + @pytest.fixture(scope="session") def oedu_file(): oedu = fetch_test_file("Mpro-P0008_0A_ERI-UCB-ce40166b-17_prepped_receptor_0.oedu") return oedu + @pytest.fixture(scope="session") def du_cache_files(): return ["du_cache/Mpro-x0354_0A_bound.oedu", "du_cache/Mpro-x1002_0A_bound.oedu"] diff --git a/drugforge-simulation/drugforge/simulation/tests/test_simulate.py b/drugforge-simulation/drugforge/simulation/tests/test_simulate.py index d70ef5f0..c1b4994f 100644 --- a/drugforge-simulation/drugforge/simulation/tests/test_simulate.py +++ b/drugforge-simulation/drugforge/simulation/tests/test_simulate.py @@ -3,11 +3,11 @@ from unittest import mock import pytest +from click.testing import CliRunner from drugforge.docking.docking import DockingResult from drugforge.docking.openeye import POSITDockingResults from drugforge.simulation.cli import simulation as cli from drugforge.simulation.simulate import SimulationResult, VanillaMDSimulator -from click.testing import CliRunner from openmm import unit diff --git a/drugforge-spectrum/drugforge/spectrum/align_seq_match.py b/drugforge-spectrum/drugforge/spectrum/align_seq_match.py index 9a02afae..39eecd6c 100644 --- a/drugforge-spectrum/drugforge/spectrum/align_seq_match.py +++ b/drugforge-spectrum/drugforge/spectrum/align_seq_match.py @@ -4,9 +4,9 @@ import numpy as np import pymol2 +from Bio import Align, AlignIO, pairwise2 from drugforge.spectrum.blast import pdb_to_seq from drugforge.spectrum.seq_alignment import get_colors_by_aa_group -from Bio import Align, AlignIO, pairwise2 def pairwise_alignment(pdb_file, pdb_align, start_idxA, start_idxB): diff --git a/drugforge-spectrum/drugforge/spectrum/calculate_rmsd.py b/drugforge-spectrum/drugforge/spectrum/calculate_rmsd.py index 4ae0712f..2269b2d4 100644 --- a/drugforge-spectrum/drugforge/spectrum/calculate_rmsd.py +++ b/drugforge-spectrum/drugforge/spectrum/calculate_rmsd.py @@ -1,16 +1,15 @@ +import logging from pathlib import Path +from typing import Union +import MDAnalysis as mda import numpy as np import pymol2 -import MDAnalysis as mda from Bio import pairwise2 from drugforge.data.backend.openeye import load_openeye_pdb, save_openeye_pdb from drugforge.modeling.modeling import superpose_molecule from drugforge.spectrum.blast import pdb_to_seq -from typing import Union -import logging - def rmsd_alignment( target_pdb: str, @@ -106,7 +105,9 @@ def select_best_colabfold( logging.info(f"RMSD for seed {seed} is {rmsd} A") if len(rmsds) == 0: - logging.warning(f"No ColabFold entry for {seq_name} and model {fold_model} found.") + logging.warning( + f"No ColabFold entry for {seq_name} and model {fold_model} found." + ) return 0, "" min_rmsd = np.argmin(rmsds) min_rmsd_file = file_seed[min_rmsd] @@ -206,6 +207,7 @@ def hide_chain(p, chain, obj): p.cmd.save(session_save) return + def convert_chain_id(chain: str) -> str: """Convert a chain identifier between letter and number representations. The ASCII values for lowercase letters start from a=97, so we subtract/add 96 to convert. @@ -228,6 +230,7 @@ def convert_chain_id(chain: str) -> str: logging.warning(f"Chain identifier {chain} is not valid.") return chain + def colorbyrmsd( p: pymol2.PyMOL, target_sel: str, @@ -300,7 +303,8 @@ def colorbyrmsd( return -def get_residue_mapping(seq_ref: str, seq_mob:str) -> tuple[int, int]: + +def get_residue_mapping(seq_ref: str, seq_mob: str) -> tuple[int, int]: """Aligns two sequences and returns the correct start and end residue indices, ignoring gaps @@ -342,14 +346,15 @@ def get_residue_mapping(seq_ref: str, seq_mob:str) -> tuple[int, int]: return start_idx + 1, end_idx + 1 # 1-based indexing + def find_bsite_resids( - pdb:str, - pdb_ref:str, - aligned_temp:str, - ligres:str = "UNK", - chain_m:str ="A", - chain_r:str ="A", - bsite_dist:float = 4.5, + pdb: str, + pdb_ref: str, + aligned_temp: str, + ligres: str = "UNK", + chain_m: str = "A", + chain_r: str = "A", + bsite_dist: float = 4.5, res_threshold: int = 5, ): """Find binding site residues in a protein-ligand complex based on ligand proximity. @@ -384,6 +389,7 @@ def find_bsite_resids( No binding site residues have an idx above res_threshold """ from scipy.spatial.distance import cdist + rmsd, pdb_aln = rmsd_alignment(pdb, pdb_ref, aligned_temp, chain_m, chain_r) u = mda.Universe(pdb_aln) u_ref = mda.Universe(pdb_ref) @@ -434,17 +440,18 @@ def find_bsite_resids( return np.sort(bs_mob[:n_res]), bs_ref + def get_binding_site_rmsd( file_mob: Union[Path, str], file_ref: Union[Path, str], - bsite_dist:float = 4.5, - rmsd_mode:str = "CA", - chain_mob:str = "A", - chain_ref:str = "A", - ligres:str = "LIG", - lig_ref_pdb:str = None, - chain_ref2:str = "A", - aligned_temp:str = None, + bsite_dist: float = 4.5, + rmsd_mode: str = "CA", + chain_mob: str = "A", + chain_ref: str = "A", + ligres: str = "LIG", + lig_ref_pdb: str = None, + chain_ref2: str = "A", + aligned_temp: str = None, ) -> float: """Calculate RMSD for the Binding Site residues between file_mob and file_ref The binding site is defined as all residues protein within bsite_dist Angs of the ligand in the reference protein. @@ -541,7 +548,9 @@ def get_binding_site_rmsd( binding_site_m.append(res.resid) binding_site_r.append(r) else: - logging.warning(f"Missmatch in residue with index {i} {binding_site_n[i]} != {res.resname}") + logging.warning( + f"Missmatch in residue with index {i} {binding_site_n[i]} != {res.resname}" + ) sel_bs = " or ".join(f"resid {r}" for r in binding_site_r) sel_bs_m = " or ".join(f"resid {r}" for r in binding_site_m) @@ -579,4 +588,4 @@ def get_binding_site_rmsd( logging.error(f"Error: Mismatched lengths ({len(m_pos)} vs {len(ref_pos)})") rmsd = -1 - return rmsd \ No newline at end of file + return rmsd diff --git a/drugforge-spectrum/drugforge/spectrum/score.py b/drugforge-spectrum/drugforge/spectrum/score.py index 9e156434..4281b84d 100644 --- a/drugforge-spectrum/drugforge/spectrum/score.py +++ b/drugforge-spectrum/drugforge/spectrum/score.py @@ -1,35 +1,33 @@ -from drugforge.data.schema.complex import Complex -from drugforge.modeling.schema import PreppedComplex -from drugforge.docking.docking import DockingInputPair -from drugforge.docking.meta_scorer import MetaScorer -from drugforge.docking.analysis import calculate_rmsd_openeye - -from drugforge.docking.openeye import POSITDocker +import logging +import os +import shutil +import subprocess +from pathlib import Path +from typing import Optional, Union +import pandas as pd from drugforge.data.backend.openeye import ( load_openeye_pdb, + oechem, save_openeye_sdf, + split_openeye_mol, ) -from drugforge.data.backend.openeye import oechem, split_openeye_mol -from drugforge.spectrum.calculate_rmsd import rmsd_alignment -from drugforge.simulation.simulate import VanillaMDSimulator -from drugforge.data.services.postera.manifold_data_validation import TargetTags from drugforge.data.metadata.resources import active_site_chains - -import os -import shutil -from rdkit import Chem -from typing import Union -import pandas as pd -from pathlib import Path -import subprocess - -import logging -from typing import Optional +from drugforge.data.schema.complex import Complex +from drugforge.data.services.postera.manifold_data_validation import TargetTags +from drugforge.docking.analysis import calculate_rmsd_openeye +from drugforge.docking.docking import DockingInputPair +from drugforge.docking.meta_scorer import MetaScorer +from drugforge.docking.openeye import POSITDocker +from drugforge.modeling.schema import PreppedComplex +from drugforge.simulation.simulate import VanillaMDSimulator +from drugforge.spectrum.calculate_rmsd import rmsd_alignment from pydantic.v1 import BaseModel, Field, root_validator +from rdkit import Chem logger = logging.getLogger(__name__) + class ScoreSpectrumInputsBase(BaseModel): """Inputs for scoring workflow @@ -43,21 +41,21 @@ class ScoreSpectrumInputsBase(BaseModel): The target to dock against. logname : str Name of the log file. - loglevel : Union[int, str] + loglevel : Union[int, str] Logging level output_dir : Path Output directory where results will be stored. - overwrite : bool + overwrite : bool Whether to overwrite existing output. ref_chain : Optional[str] Chain ID to align to in reference structure containing the active site dock_chain : Optional[str] Active site chain ID to align to ref_chain in reference structure - lig_resname : Optional[str] + lig_resname : Optional[str] Name of residue with Ligand run_vina : bool Whether to run vina scoring. - vina_box_x : Optional[float] + vina_box_x : Optional[float] Coordinate x of vina box vina_box_y : Optional[float] Coordinate y of vina box @@ -71,8 +69,8 @@ class ScoreSpectrumInputsBase(BaseModel): Whether to run gnina scoring. gnina_script : Optional[Path] Path to bash script that runs Gnina CLI. - gnina_out_dir : Optional[Path] - Path to directory to process gnina files. + gnina_out_dir : Optional[Path] + Path to directory to process gnina files. Gnina has problems with remote directories so location in $HOME is recommended when running in a remote cluster. Returns @@ -86,6 +84,7 @@ class ScoreSpectrumInputsBase(BaseModel): ValueError If Gnina scoring is requested, a gnina_script to run the CLI, and a directory to save intermediate files must be provided """ + docking_dir: Path = Field( None, description="Path to directory where docked structures are stored." ) @@ -104,9 +103,7 @@ class ScoreSpectrumInputsBase(BaseModel): output_dir: Path = Field(Path("score_output"), description="Output directory") - overwrite: bool = Field( - False, description="Whether to overwrite existing output." - ) + overwrite: bool = Field(False, description="Whether to overwrite existing output.") ref_chain: Optional[str] = Field( None, description="Chain ID to align to in reference structure containing the active site", @@ -121,44 +118,29 @@ class ScoreSpectrumInputsBase(BaseModel): ) # Running Vina - run_vina: bool = Field( - False, - description="Whether to run vina scoring." - ) - vina_box_x: Optional[float] = Field( - None, - description="Coordinate x of vina box" - ) - vina_box_y: Optional[float] = Field( - None, - description="Coordinate y of vina box" - ) - vina_box_z: Optional[float] = Field( - None, - description="Coordinate z of vina box" - ) + run_vina: bool = Field(False, description="Whether to run vina scoring.") + vina_box_x: Optional[float] = Field(None, description="Coordinate x of vina box") + vina_box_y: Optional[float] = Field(None, description="Coordinate y of vina box") + vina_box_z: Optional[float] = Field(None, description="Coordinate z of vina box") path_to_grid_prep: Optional[Path] = Field( None, description="Path to file for grid prepping" ) dock_vina: bool = Field( - False, - description="Optionally run extra docking step with autodock vina " + False, description="Optionally run extra docking step with autodock vina " ) - + # Running Gnina - gnina_score: bool = Field( - False, description="Whether to run gnina scoring." - ) + gnina_score: bool = Field(False, description="Whether to run gnina scoring.") gnina_script: Optional[Path] = Field( None, description="Path to bash script that runs Gnina CLI." ) - + gnina_out_dir: Optional[Path] = Field( - None, description="Path to directory to process gnina files. Gnina has problems with remote directories so location in $HOME is recommended when running in a remote cluster." + None, + description="Path to directory to process gnina files. Gnina has problems with remote directories so location in $HOME is recommended when running in a remote cluster.", ) - class Config: arbitrary_types_allowed = True @@ -181,12 +163,15 @@ def check_inputs_vina(cls, values): vina_box_z = values.get("vina_box_z") path_to_grid_prep = values.get("path_to_grid_prep") - if (not vina_box_x or not vina_box_y or not vina_box_z) and not path_to_grid_prep: - raise ValueError("Either especify ALL coordinates of the box, ot the path to grid prepper function") - + if ( + not vina_box_x or not vina_box_y or not vina_box_z + ) and not path_to_grid_prep: + raise ValueError( + "Either especify ALL coordinates of the box, ot the path to grid prepper function" + ) return values - + @root_validator @classmethod def check_inputs_gnina(cls, values): @@ -196,9 +181,11 @@ def check_inputs_gnina(cls, values): gnina_score = values.get("gnina_score") gnina_script = values.get("gnina_script") gnina_out_dir = values.get("gnina_out_dir") - + if gnina_score and (not gnina_script or not gnina_out_dir): - raise ValueError("If Gnina scoring is requested, a gnina_script to run the CLI, and a directory to save intermediate files must be provided") + raise ValueError( + "If Gnina scoring is requested, a gnina_script to run the CLI, and a directory to save intermediate files must be provided" + ) return values @@ -217,6 +204,7 @@ def check_and_set_chains(cls, values): values["lig_resname"] = "LIG" return values + def dock_and_score( pdb_complex: Union[Path, str], comp_name: str, @@ -229,7 +217,7 @@ def dock_and_score( align_chain: str = "A", align_chain_ref: str = "A", ): - """Re-dock ligand in a complex and return pose scores, using the POSITDocker and given 'scorers'. + """Re-dock ligand in a complex and return pose scores, using the POSITDocker and given 'scorers'. Optionally aligns complex to a reference structure before docking. Parameters @@ -269,7 +257,7 @@ def dock_and_score( align_chain, align_chain_ref, ) - else: + else: logging.warning( f"A folder to store aligned PDB must be provided if target is to be aligned to ref_pdb. Alignment won't be made." ) @@ -387,7 +375,7 @@ def get_ligand_rmsd( "for rdkit mode. a path to save/load sdf mols must be provided" ) - rmsd_oechem = calculate_rmsd_openeye(ref_lig, target_lig) + rmsd_oechem = calculate_rmsd_openeye(ref_lig, target_lig) if rmsd_mode == "oechem": return rmsd_oechem elif rmsd_mode == "rdkit": @@ -403,14 +391,14 @@ def get_ligand_rmsd( def score_autodock_vina( receptor_pdb: Union[str, Path], ligand_sdf: Path, - box_center = None, - box_size = [20, 20, 20], - dock = False, - path_to_prepare_file = "./", + box_center=None, + box_size=[20, 20, 20], + dock=False, + path_to_prepare_file="./", ): - """ Score ligand pose with AutoDock Vina. + """Score ligand pose with AutoDock Vina. This function will take a receptor PDB and a ligand SDF, and prepare them to pdbqt files with the MGLTools, which are needed for Vina. - If the receptor and/or ligand is already in pdbqt format, it will be used as is. + If the receptor and/or ligand is already in pdbqt format, it will be used as is. The dimensions of the grid box for Vina can be specified or calculated, provided a path to a grid file (which can be downloaded from Vina). A dataframe with the scores will be returned, including the scores before and after minimization, as well as the path to a Vina docked pose if dock=True. @@ -478,10 +466,7 @@ def score_autodock_vina( v = Vina(sf_name="vina") # First check if prep was successful - if ( - not receptor_pdbqt.is_file() - or not ligand_pdbqt.is_file() - ): + if not receptor_pdbqt.is_file() or not ligand_pdbqt.is_file(): df_scores["Vina-score-premin"] = None df_scores["Vina-score-min"] = None if dock: @@ -522,7 +507,8 @@ def score_autodock_vina( break # Check if box_center was set sucessfully if box_center is None: - logger.warning(f"Could not generate grid box for Vina calculation because .gpf file was incorrect." + logger.warning( + f"Could not generate grid box for Vina calculation because .gpf file was incorrect." ) df_scores["Vina-score-premin"] = None df_scores["Vina-score-min"] = None @@ -536,16 +522,12 @@ def score_autodock_vina( # Score the current pose energy = v.score() - logger.info( - f"Score before minimization: {energy[0]} (kcal/mol)" - ) + logger.info(f"Score before minimization: {energy[0]} (kcal/mol)") df_scores["Vina-score-premin"] = energy[0] # Minimized locally the current pose energy_minimized = v.optimize() - logger.info( - f"Score after minimization: {energy_minimized[0]} (kcal/mol)" - ) + logger.info(f"Score after minimization: {energy_minimized[0]} (kcal/mol)") df_scores["Vina-score-min"] = energy_minimized[0] parent_dir = receptor_pdb.resolve().parents[0] v.write_pose(f"{parent_dir/receptor_pdb.stem}_minimized.pdbqt", overwrite=True) @@ -554,9 +536,7 @@ def score_autodock_vina( if dock: # Dock the ligand v.dock(exhaustiveness=32, n_poses=20) - v.write_poses( - f"{receptor_pdb.stem}_vina_out.pdbqt", n_poses=1, overwrite=True - ) + v.write_poses(f"{receptor_pdb.stem}_vina_out.pdbqt", n_poses=1, overwrite=True) df_scores["Vina-dock-score"] = v.score()[0] # Convert pose in pdbqt to calculate rmsd out_pose = f"{parent_dir/receptor_pdb.stem}_vina_out.pdb" @@ -567,11 +547,12 @@ def score_autodock_vina( return df_scores, out_pose -def score_gnina(pdb_target:str, - sdf_ligand:str, - pdb_dir:str, - home_dir:str, - gnina_script:str, +def score_gnina( + pdb_target: str, + sdf_ligand: str, + pdb_dir: str, + home_dir: str, + gnina_script: str, ) -> pd.DataFrame: """Score a ligand pose with Gnina CNN scoring function. @@ -586,7 +567,7 @@ def score_gnina(pdb_target:str, home_dir : str Directory where gnina will be run. This directory should be in $HOME, as gnina has problems with remote directories. gnina_script : str - Path to bash script that runs Gnina CLI. + Path to bash script that runs Gnina CLI. Returns ------- @@ -598,7 +579,7 @@ def score_gnina(pdb_target:str, - CNNscore: Gnina CNN score. - CNNaffinity: Gnina CNN affinity score. - CNNvariance: Gnina CNN affinity score variance. - + """ logfile = f"out_{pdb_target[:-4]}.log" env = os.environ.copy() @@ -654,7 +635,7 @@ def minimize_structure( comp_name: str, target_name: str, ) -> Union[Path, str]: - """MD energy minimization a protein ligand complex. + """MD energy minimization a protein ligand complex. Energy minimization is performed with OpenMM (no equilibration or production MD is performed). Parameters diff --git a/drugforge-spectrum/drugforge/spectrum/seq_alignment.py b/drugforge-spectrum/drugforge/spectrum/seq_alignment.py index 6ac9acf6..bcfb9644 100644 --- a/drugforge-spectrum/drugforge/spectrum/seq_alignment.py +++ b/drugforge-spectrum/drugforge/spectrum/seq_alignment.py @@ -1,6 +1,6 @@ +import logging import subprocess from pathlib import Path -import logging import numpy as np import pandas as pd @@ -464,7 +464,9 @@ def do_MSA( select_file = alignment.select_checkbox() elif "host" in select_mode or "organism" in select_mode: if alignment.hosts[0] is None: - raise NameError("The csv input file provided does not have host information, you have to use the 'keyword' mode.") + raise NameError( + "The csv input file provided does not have host information, you have to use the 'keyword' mode." + ) else: select_file = alignment.select_taxonomy(select_mode, f"{save_file}.fasta") else: @@ -486,7 +488,9 @@ def do_MSA( clean_csv = alignment.csv_align_data( alignment.select_file, f"{save_file}.csv", n_chains ) - logging.info(f"A csv file {clean_csv} have been generated with the selected sequences") + logging.info( + f"A csv file {clean_csv} have been generated with the selected sequences" + ) p, align_html = alignment.view_alignment( plot_width=plot_width, @@ -496,7 +500,9 @@ def do_MSA( max_mismatch=max_mismatch, reorder=custom_order.split(","), ) - logging.info(f"A html file {align_html} have been generated with the aligned sequences") + logging.info( + f"A html file {align_html} have been generated with the aligned sequences" + ) alignment.sucess = True return alignment diff --git a/drugforge-spectrum/drugforge/spectrum/tests/conftest.py b/drugforge-spectrum/drugforge/spectrum/tests/conftest.py index ce444663..dec6903d 100644 --- a/drugforge-spectrum/drugforge/spectrum/tests/conftest.py +++ b/drugforge-spectrum/drugforge/spectrum/tests/conftest.py @@ -6,14 +6,17 @@ def protein_path(): return fetch_test_file("Mpro-P2660_0A_bound.pdb") + @pytest.fixture(scope="session") def prepped_target_path(): return fetch_test_file("Mpro-P2660_0A_bound-prepped_protein.pdb") + @pytest.fixture(scope="session") def prepped_ligand_path(): return fetch_test_file("Mpro-P2660_0A_bound-prepped_ligand.sdf") + @pytest.fixture(scope="session") def blast_xml_path(): return fetch_test_file("SARS_blast_results.xml") @@ -33,18 +36,22 @@ def fasta_alignment_path(): def pdb_file(): return fetch_test_file("Mpro-P2660_0A_bound_oe_processed.pdb") + @pytest.fixture(scope="session") def docking_results_csv_path(): return fetch_test_file("lt_docking_scores.csv") + @pytest.fixture(scope="session") def ligand_prepped_vina(): return fetch_test_file("SARS_model_ligand_prepped.pdbqt") + @pytest.fixture(scope="session") def target_prepped_vina(): return fetch_test_file("SARS_model_target_prepped.pdbqt") + @pytest.fixture() def protein_apo_path(): return fetch_test_file("Mpro-YP_009725301_AFold_processed.pdb") diff --git a/drugforge-spectrum/drugforge/spectrum/tests/test_score.py b/drugforge-spectrum/drugforge/spectrum/tests/test_score.py index 4138b7c3..6b8adb83 100644 --- a/drugforge-spectrum/drugforge/spectrum/tests/test_score.py +++ b/drugforge-spectrum/drugforge/spectrum/tests/test_score.py @@ -3,15 +3,15 @@ from pathlib import Path import pytest +from drugforge.data.schema.ligand import Ligand +from drugforge.docking.scorer import ChemGauss4Scorer +from drugforge.spectrum.calculate_rmsd import get_binding_site_rmsd from drugforge.spectrum.score import ( dock_and_score, get_ligand_rmsd, + minimize_structure, score_autodock_vina, - minimize_structure ) -from drugforge.spectrum.calculate_rmsd import get_binding_site_rmsd -from drugforge.docking.scorer import ChemGauss4Scorer -from drugforge.data.schema.ligand import Ligand def click_success(result): @@ -23,10 +23,9 @@ def click_success(result): def test_bsite_rmsd_CA(protein_apo_path, protein_path): - """Test binding site RMSD calculation based on C-alpha atoms. - """ + """Test binding site RMSD calculation based on C-alpha atoms.""" rmsd = get_binding_site_rmsd( - file_ref=protein_path, + file_ref=protein_path, file_mob=protein_apo_path, bsite_dist=4.5, rmsd_mode="CA", @@ -40,7 +39,7 @@ def test_bsite_rmsd_CA(protein_apo_path, protein_path): def test_bsite_rmsd_heavy(protein_apo_path, protein_path): """Test binding site RMSD calculation based on heavy atoms.""" rmsd = get_binding_site_rmsd( - file_ref=protein_path, + file_ref=protein_path, file_mob=protein_apo_path, bsite_dist=4.5, rmsd_mode="heavy", @@ -69,15 +68,15 @@ def test_dock_score(protein_path): assert scores_df["docking-score-POSIT"].values[0] assert type(ligand_pose) == Ligand assert Path(aligned).exists() - -def test_lig_rmsd_oechem(protein_path): + +def test_lig_rmsd_oechem(protein_path): """Test ligand RMSD calculation using OpenEye toolkit method.""" lig_rmsd = get_ligand_rmsd( - ref_pdb=str(protein_path), - target_pdb=str(protein_path), - addHs=True, - rmsd_mode="oechem", + ref_pdb=str(protein_path), + target_pdb=str(protein_path), + addHs=True, + rmsd_mode="oechem", ) assert lig_rmsd == 0 @@ -85,12 +84,12 @@ def test_lig_rmsd_oechem(protein_path): def test_lig_rmsd_rdkit(protein_path, tmp_path): """Test ligand RMSD calculation using RDKit toolkit method.""" lig_rmsd = get_ligand_rmsd( - ref_pdb=str(protein_path), - target_pdb=str(protein_path), - addHs=True, - rmsd_mode="rdkit", - pathT=str(tmp_path/"target.sdf"), - pathR=str(tmp_path/"ref.sdf"), + ref_pdb=str(protein_path), + target_pdb=str(protein_path), + addHs=True, + rmsd_mode="rdkit", + pathT=str(tmp_path / "target.sdf"), + pathR=str(tmp_path / "ref.sdf"), ) assert lig_rmsd == 0 @@ -100,7 +99,7 @@ def test_vina_score(target_prepped_vina, ligand_prepped_vina): df_vina, out_pose = score_autodock_vina( receptor_pdb=target_prepped_vina, ligand_sdf=ligand_prepped_vina, - box_center=[-22,5,25], + box_center=[-22, 5, 25], box_size=[20, 20, 20], dock=False, ) @@ -115,8 +114,9 @@ def test_minimize(protein_path, tmp_path): pdb_complex=protein_path, min_out=min_out, out_dir=tmp_path, - md_platform='CPU', - comp_name='Mol', - target_name='SARS-CoV-2',) + md_platform="CPU", + comp_name="Mol", + target_name="SARS-CoV-2", + ) - assert Path(min_out).exists() \ No newline at end of file + assert Path(min_out).exists() diff --git a/drugforge-spectrum/drugforge/spectrum/tests/test_seq_align.py b/drugforge-spectrum/drugforge/spectrum/tests/test_seq_align.py index 471559aa..834db182 100644 --- a/drugforge-spectrum/drugforge/spectrum/tests/test_seq_align.py +++ b/drugforge-spectrum/drugforge/spectrum/tests/test_seq_align.py @@ -88,4 +88,4 @@ def test_MSA_color_match(blast_csv_path, tmp_path): max_mismatch=2, custom_order="", ) - assert aln_out.sucess \ No newline at end of file + assert aln_out.sucess diff --git a/drugforge-spectrum/drugforge/spectrum/tests/test_struct_align.py b/drugforge-spectrum/drugforge/spectrum/tests/test_struct_align.py index 1f087f59..541540d6 100644 --- a/drugforge-spectrum/drugforge/spectrum/tests/test_struct_align.py +++ b/drugforge-spectrum/drugforge/spectrum/tests/test_struct_align.py @@ -2,10 +2,7 @@ import traceback import pytest -from drugforge.spectrum.align_seq_match import ( - pairwise_alignment, - save_pymol_seq_align, -) +from drugforge.spectrum.align_seq_match import pairwise_alignment, save_pymol_seq_align from drugforge.spectrum.calculate_rmsd import rmsd_alignment, save_alignment_pymol @@ -72,4 +69,4 @@ def test_pymol_seq_align(protein_path, tmp_path): color_dict=[colorsA, colorsA], session_save=pse_out, ) - assert pse_out.exists() \ No newline at end of file + assert pse_out.exists() diff --git a/drugforge-workflows/drugforge/workflows/docking_workflows/cli.py b/drugforge-workflows/drugforge/workflows/docking_workflows/cli.py index 86516be1..4a70f627 100644 --- a/drugforge-workflows/drugforge/workflows/docking_workflows/cli.py +++ b/drugforge-workflows/drugforge/workflows/docking_workflows/cli.py @@ -22,10 +22,10 @@ target, use_only_cache, ) -from drugforge.docking.selectors.selector_list import StructureSelector from drugforge.data.services.postera.manifold_data_validation import TargetTags from drugforge.data.util.dask_utils import DaskType, FailureMode from drugforge.docking.openeye import POSIT_METHOD, POSIT_RELAX_MODE +from drugforge.docking.selectors.selector_list import StructureSelector from drugforge.simulation.simulate import OpenMMPlatform from drugforge.workflows.docking_workflows.cross_docking import ( CrossDockingWorkflowInputs, diff --git a/drugforge-workflows/drugforge/workflows/docking_workflows/cross_docking.py b/drugforge-workflows/drugforge/workflows/docking_workflows/cross_docking.py index b47a0bf6..7133340e 100644 --- a/drugforge-workflows/drugforge/workflows/docking_workflows/cross_docking.py +++ b/drugforge-workflows/drugforge/workflows/docking_workflows/cross_docking.py @@ -6,7 +6,6 @@ from pathlib import Path from shutil import rmtree -from drugforge.docking.selectors.selector_list import StructureSelector from drugforge.data.readers.meta_structure_factory import MetaStructureFactory from drugforge.data.readers.molfile import MolFileFactory from drugforge.data.services.postera.manifold_data_validation import ( @@ -19,13 +18,12 @@ write_results_to_multi_sdf, ) from drugforge.docking.docking_data_validation import DockingResultCols +from drugforge.docking.meta_scorer import MetaScorer from drugforge.docking.openeye import POSIT_METHOD, POSIT_RELAX_MODE, POSITDocker from drugforge.docking.scorer import ChemGauss4Scorer -from drugforge.docking.meta_scorer import MetaScorer +from drugforge.docking.selectors.selector_list import StructureSelector from drugforge.modeling.protein_prep import ProteinPrepper -from drugforge.workflows.docking_workflows.workflows import ( - DockingWorkflowInputsBase, -) +from drugforge.workflows.docking_workflows.workflows import DockingWorkflowInputsBase from pydantic.v1 import Field, PositiveInt diff --git a/drugforge-workflows/drugforge/workflows/docking_workflows/large_scale_docking.py b/drugforge-workflows/drugforge/workflows/docking_workflows/large_scale_docking.py index f3b5174a..00a96d5a 100644 --- a/drugforge-workflows/drugforge/workflows/docking_workflows/large_scale_docking.py +++ b/drugforge-workflows/drugforge/workflows/docking_workflows/large_scale_docking.py @@ -3,22 +3,16 @@ from drugforge.data.metadata.resources import master_structures from drugforge.data.operators.deduplicator import LigandDeDuplicator -from drugforge.docking.selectors.mcs_selector import RascalMCESSelector from drugforge.data.readers.meta_ligand_factory import MetaLigandFactory from drugforge.data.readers.meta_structure_factory import MetaStructureFactory from drugforge.data.schema.complex import Complex from drugforge.data.services.aws.cloudfront import CloudFront from drugforge.data.services.aws.s3 import S3 -from drugforge.workflows.postera.manifold_artifacts import ( - ArtifactType, - ManifoldArtifactUploader, -) from drugforge.data.services.postera.manifold_data_validation import ( map_output_col_to_manifold_tag, rename_output_columns_for_manifold, ) from drugforge.data.services.postera.molecule_set import MoleculeSetAPI -from drugforge.workflows.postera.postera_uploader import PosteraUploader from drugforge.data.services.services_config import ( CloudfrontSettings, PosteraSettings, @@ -30,17 +24,19 @@ from drugforge.dataviz.html_viz import ColorMethod, HTMLVisualizer from drugforge.docking.docking import write_results_to_multi_sdf from drugforge.docking.docking_data_validation import DockingResultCols -from drugforge.docking.openeye import POSITDocker -from drugforge.docking.scorer import ( - ChemGauss4Scorer, -) from drugforge.docking.fint_scorer import FINTScorer from drugforge.docking.meta_scorer import MetaScorer +from drugforge.docking.openeye import POSITDocker +from drugforge.docking.scorer import ChemGauss4Scorer +from drugforge.docking.selectors.mcs_selector import RascalMCESSelector from drugforge.modeling.protein_prep import ProteinPrepper from drugforge.spectrum.fitness import target_has_fitness_data -from drugforge.workflows.docking_workflows.workflows import ( - PosteraDockingWorkflowInputs, +from drugforge.workflows.docking_workflows.workflows import PosteraDockingWorkflowInputs +from drugforge.workflows.postera.manifold_artifacts import ( + ArtifactType, + ManifoldArtifactUploader, ) +from drugforge.workflows.postera.postera_uploader import PosteraUploader from pydantic.v1 import Field, PositiveInt @@ -292,6 +288,7 @@ def large_scale_docking_workflow(inputs: LargeScaleDockingInputs): logger.warning("Using ML scorer is still experimental. Fails are expected.") from drugforge.docking.ml_scorer import MLModelScorer # Lazy import from drugforge.ml.models import ASAPMLModelRegistry + # check which endpoints are availabe for the target models = ASAPMLModelRegistry.reccomend_models_for_target(inputs.target) for model in models: diff --git a/drugforge-workflows/drugforge/workflows/docking_workflows/ligand_transfer_docking.py b/drugforge-workflows/drugforge/workflows/docking_workflows/ligand_transfer_docking.py index ee89c444..3bd9412a 100644 --- a/drugforge-workflows/drugforge/workflows/docking_workflows/ligand_transfer_docking.py +++ b/drugforge-workflows/drugforge/workflows/docking_workflows/ligand_transfer_docking.py @@ -14,27 +14,21 @@ from shutil import rmtree from typing import Optional -from drugforge.docking.selectors.selector_list import StructureSelector from drugforge.data.readers.meta_structure_factory import MetaStructureFactory -from drugforge.data.util.dask_utils import ( - BackendType, - DaskType, - make_dask_client_meta, -) +from drugforge.data.util.dask_utils import BackendType, DaskType, make_dask_client_meta from drugforge.data.util.logging import FileLogger from drugforge.data.util.utils import check_empty_dataframe from drugforge.dataviz.gif_viz import GIFVisualizer from drugforge.dataviz.html_viz import ColorMethod, HTMLVisualizer from drugforge.docking.docking import write_results_to_multi_sdf from drugforge.docking.docking_data_validation import DockingResultCols +from drugforge.docking.meta_scorer import MetaScorer from drugforge.docking.openeye import POSIT_METHOD, POSIT_RELAX_MODE, POSITDocker from drugforge.docking.scorer import ChemGauss4Scorer -from drugforge.docking.meta_scorer import MetaScorer +from drugforge.docking.selectors.selector_list import StructureSelector from drugforge.modeling.protein_prep import LigandTransferProteinPrepper from drugforge.simulation.simulate import OpenMMPlatform, VanillaMDSimulator -from drugforge.workflows.docking_workflows.workflows import ( - DockingWorkflowInputsBase, -) +from drugforge.workflows.docking_workflows.workflows import DockingWorkflowInputsBase from pydantic.v1 import Field, PositiveInt, root_validator @@ -342,6 +336,7 @@ def get_unique_ligands(complex_list): logger.warning("Using ML scorer is still experimental. Fails are expected.") from drugforge.docking.ml_scorer import MLModelScorer # Lazy import from drugforge.ml.models import ASAPMLModelRegistry + # check which endpoints are availabe for the target models = ASAPMLModelRegistry.reccomend_models_for_target(inputs.target) ml_scorers = MLModelScorer.load_model_specs(models=models) diff --git a/drugforge-workflows/drugforge/workflows/docking_workflows/small_scale_docking.py b/drugforge-workflows/drugforge/workflows/docking_workflows/small_scale_docking.py index 1aaadf2b..59c1b311 100644 --- a/drugforge-workflows/drugforge/workflows/docking_workflows/small_scale_docking.py +++ b/drugforge-workflows/drugforge/workflows/docking_workflows/small_scale_docking.py @@ -3,51 +3,43 @@ from drugforge.data.metadata.resources import master_structures from drugforge.data.operators.deduplicator import LigandDeDuplicator -from drugforge.docking.selectors.mcs_selector import RascalMCESSelector from drugforge.data.readers.meta_ligand_factory import MetaLigandFactory from drugforge.data.readers.meta_structure_factory import MetaStructureFactory from drugforge.data.schema.complex import Complex from drugforge.data.services.aws.cloudfront import CloudFront from drugforge.data.services.aws.s3 import S3 -from drugforge.workflows.postera.manifold_artifacts import ( - ArtifactType, - ManifoldArtifactUploader, -) from drugforge.data.services.postera.manifold_data_validation import ( TargetProteinMap, map_output_col_to_manifold_tag, rename_output_columns_for_manifold, ) from drugforge.data.services.postera.molecule_set import MoleculeSetAPI -from drugforge.workflows.postera.postera_uploader import PosteraUploader from drugforge.data.services.services_config import ( CloudfrontSettings, PosteraSettings, S3Settings, ) -from drugforge.data.util.dask_utils import ( - BackendType, - DaskType, - make_dask_client_meta, -) +from drugforge.data.util.dask_utils import BackendType, DaskType, make_dask_client_meta from drugforge.data.util.logging import FileLogger from drugforge.data.util.utils import check_empty_dataframe from drugforge.dataviz.gif_viz import GIFVisualizer from drugforge.dataviz.html_viz import ColorMethod, HTMLVisualizer from drugforge.docking.docking import write_results_to_multi_sdf from drugforge.docking.docking_data_validation import DockingResultCols -from drugforge.docking.openeye import POSITDocker -from drugforge.docking.scorer import ( - ChemGauss4Scorer, -) from drugforge.docking.fint_scorer import FINTScorer from drugforge.docking.meta_scorer import MetaScorer +from drugforge.docking.openeye import POSITDocker +from drugforge.docking.scorer import ChemGauss4Scorer +from drugforge.docking.selectors.mcs_selector import RascalMCESSelector from drugforge.modeling.protein_prep import ProteinPrepper from drugforge.simulation.simulate import OpenMMPlatform, VanillaMDSimulator from drugforge.spectrum.fitness import target_has_fitness_data -from drugforge.workflows.docking_workflows.workflows import ( - PosteraDockingWorkflowInputs, +from drugforge.workflows.docking_workflows.workflows import PosteraDockingWorkflowInputs +from drugforge.workflows.postera.manifold_artifacts import ( + ArtifactType, + ManifoldArtifactUploader, ) +from drugforge.workflows.postera.postera_uploader import PosteraUploader from pydantic.v1 import Field, PositiveInt @@ -302,6 +294,7 @@ def small_scale_docking_workflow(inputs: SmallScaleDockingInputs): logger.warning("Using ML scorer is still experimental. Fails are expected.") from drugforge.docking.ml_scorer import MLModelScorer # Lazy import from drugforge.ml.models import ASAPMLModelRegistry + # check which endpoints are availabe for the target models = ASAPMLModelRegistry.reccomend_models_for_target(inputs.target) for model in models: diff --git a/drugforge-workflows/drugforge/workflows/docking_workflows/symexp_crystal_packing.py b/drugforge-workflows/drugforge/workflows/docking_workflows/symexp_crystal_packing.py index 4cd6242b..40936784 100644 --- a/drugforge-workflows/drugforge/workflows/docking_workflows/symexp_crystal_packing.py +++ b/drugforge-workflows/drugforge/workflows/docking_workflows/symexp_crystal_packing.py @@ -2,22 +2,16 @@ from shutil import rmtree from drugforge.data.operators.deduplicator import LigandDeDuplicator -from drugforge.docking.selectors.mcs_selector import RascalMCESSelector from drugforge.data.operators.symmetry_expander import SymmetryExpander from drugforge.data.readers.meta_ligand_factory import MetaLigandFactory from drugforge.data.readers.meta_structure_factory import MetaStructureFactory from drugforge.data.services.aws.cloudfront import CloudFront from drugforge.data.services.aws.s3 import S3 -from drugforge.workflows.postera.manifold_artifacts import ( - ArtifactType, - ManifoldArtifactUploader, -) from drugforge.data.services.postera.manifold_data_validation import ( map_output_col_to_manifold_tag, rename_output_columns_for_manifold, ) from drugforge.data.services.postera.molecule_set import MoleculeSetAPI -from drugforge.workflows.postera.postera_uploader import PosteraUploader from drugforge.data.services.services_config import ( CloudfrontSettings, PosteraSettings, @@ -30,10 +24,14 @@ from drugforge.docking.docking_data_validation import DockingResultCols from drugforge.docking.openeye import POSITDocker from drugforge.docking.scorer import ChemGauss4Scorer, SymClashScorer +from drugforge.docking.selectors.mcs_selector import RascalMCESSelector from drugforge.modeling.protein_prep import ProteinPrepper -from drugforge.workflows.docking_workflows.workflows import ( - PosteraDockingWorkflowInputs, +from drugforge.workflows.docking_workflows.workflows import PosteraDockingWorkflowInputs +from drugforge.workflows.postera.manifold_artifacts import ( + ArtifactType, + ManifoldArtifactUploader, ) +from drugforge.workflows.postera.postera_uploader import PosteraUploader from pydantic.v1 import Field diff --git a/drugforge-workflows/drugforge/workflows/postera/postera_uploader.py b/drugforge-workflows/drugforge/workflows/postera/postera_uploader.py index 36d1957e..29073fb0 100644 --- a/drugforge-workflows/drugforge/workflows/postera/postera_uploader.py +++ b/drugforge-workflows/drugforge/workflows/postera/postera_uploader.py @@ -4,10 +4,7 @@ import numpy as np import pandas as pd from drugforge.data.backend.rdkit import rdkit_smiles_roundtrip -from drugforge.data.services.postera.molecule_set import ( - MoleculeSetAPI, - MoleculeSetKeys, -) +from drugforge.data.services.postera.molecule_set import MoleculeSetAPI, MoleculeSetKeys from drugforge.data.services.services_config import PosteraSettings from drugforge.docking.docking_data_validation import DockingResultCols from pydantic.v1 import BaseModel, Field diff --git a/drugforge-workflows/drugforge/workflows/spectrum_workflows/cli.py b/drugforge-workflows/drugforge/workflows/spectrum_workflows/cli.py index 89bba4a9..543b164a 100644 --- a/drugforge-workflows/drugforge/workflows/spectrum_workflows/cli.py +++ b/drugforge-workflows/drugforge/workflows/spectrum_workflows/cli.py @@ -1,8 +1,25 @@ +import logging from pathlib import Path from typing import Optional import click import pandas as pd +from drugforge.cli.cli_args import ( + blast_json, + email, + gen_ref_pdb, + input_json, + loglevel, + max_mismatches, + multimer, + n_chains, + output_dir, + pdb_file, + pymol_save, + seq_file, + seq_type, + target, +) from drugforge.data.util.logging import FileLogger from drugforge.simulation.simulate import OpenMMPlatform from drugforge.spectrum.align_seq_match import ( @@ -15,27 +32,11 @@ save_alignment_pymol, select_best_colabfold, ) -from drugforge.cli.cli_args import ( - output_dir, - pdb_file, - target, - input_json, - blast_json, - email, - gen_ref_pdb, - max_mismatches, - multimer, - n_chains, - pymol_save, - seq_file, - seq_type, - loglevel, -) from drugforge.spectrum.seq_alignment import Alignment, do_MSA - -from drugforge.workflows.spectrum_workflows.score_complex import ScoreInputs, score_complex_workflow - -import logging +from drugforge.workflows.spectrum_workflows.score_complex import ( + ScoreInputs, + score_complex_workflow, +) @click.group() @@ -205,7 +206,9 @@ def seq_alignment( ) record = pdb_file_record[0] - logger.info(f"A PDB template for {record.label} was saved as {record.pdb_file}") + logger.info( + f"A PDB template for {record.label} was saved as {record.pdb_file}" + ) @spectrum.command() @@ -479,10 +482,10 @@ def fitness_alignment( @spectrum.command() @click.option( - "-d", - "--docking-dir", - type=click.Path(exists=True), - help="Path to directory where docked structures are stored." + "-d", + "--docking-dir", + type=click.Path(exists=True), + help="Path to directory where docked structures are stored.", ) @click.option( "-f", @@ -498,10 +501,10 @@ def fitness_alignment( help="Path to directory where scoring results will be stored.", ) @click.option( - "--docking-csv", - type=click.Path(), - default="", - help="Path to csv files with docking results." + "--docking-csv", + type=click.Path(), + default="", + help="Path to csv files with docking results.", ) @target @click.option( @@ -526,10 +529,11 @@ def fitness_alignment( help="coordinate z of vina box.", ) @click.option( - "--path-to-grid-prep", - type=click.Path(), - default="./", - help="Path to .py file that calculates grid for Vina.") + "--path-to-grid-prep", + type=click.Path(), + default="./", + help="Path to .py file that calculates grid for Vina.", +) @click.option( "--docking-vina", is_flag=True, @@ -558,7 +562,7 @@ def fitness_alignment( "--md-openmm-platform", type=str, default="Fastest", - help="The OpenMM platform to use for MD minimization. [CPU|CUDA|OpenCL|Reference|Fastest]", + help="The OpenMM platform to use for MD minimization. [CPU|CUDA|OpenCL|Reference|Fastest]", ) @click.option( "--ml-score", @@ -604,23 +608,17 @@ def fitness_alignment( ) @click.option( "--gnina-out-dir", - type=click.Path(), - default="./", - help="Directory for gnina output." -) -@click.option( - "--log-level", - type=str, - default="INFO", - help="Logging level." + type=click.Path(), + default="./", + help="Directory for gnina output.", ) +@click.option("--log-level", type=str, default="INFO", help="Logging level.") @input_json - def score( docking_dir: str, pdb_ref: str, docking_csv: str, - out_dir:str, + out_dir: str, target: str, ligand_regex: str, protein_regex: str, @@ -634,7 +632,7 @@ def score( docking_vina: bool = False, path_to_grid_prep: str = "./", minimize: bool = False, - md_openmm_platform:OpenMMPlatform = OpenMMPlatform.Fastest, + md_openmm_platform: OpenMMPlatform = OpenMMPlatform.Fastest, ml_score: bool = False, bsite_rmsd: bool = False, gnina_score: bool = False, @@ -642,7 +640,7 @@ def score( gnina_out_dir: Optional[str] = None, log_level: str = "info", input_json: Optional[str] = None, -) ->None: +) -> None: """Run scoring workflow on docked and minimized poses""" loglevel = getattr(logging, log_level.upper(), logging.INFO) @@ -680,5 +678,6 @@ def score( score_complex_workflow(inputs) + if __name__ == "__main__": spectrum() diff --git a/drugforge-workflows/drugforge/workflows/spectrum_workflows/score_complex.py b/drugforge-workflows/drugforge/workflows/spectrum_workflows/score_complex.py index 8b85b68e..56a718d7 100644 --- a/drugforge-workflows/drugforge/workflows/spectrum_workflows/score_complex.py +++ b/drugforge-workflows/drugforge/workflows/spectrum_workflows/score_complex.py @@ -1,25 +1,25 @@ +import os +import re +from pathlib import Path +from shutil import rmtree + +import pandas as pd from drugforge.data.schema.complex import Complex from drugforge.data.util.logging import FileLogger -from drugforge.simulation.simulate import OpenMMPlatform from drugforge.docking.scorer import ChemGauss4Scorer +from drugforge.simulation.simulate import OpenMMPlatform +from drugforge.spectrum.calculate_rmsd import get_binding_site_rmsd from drugforge.spectrum.score import ( ScoreSpectrumInputsBase, dock_and_score, get_ligand_rmsd, - score_autodock_vina, minimize_structure, + score_autodock_vina, score_gnina, ) -from drugforge.spectrum.calculate_rmsd import get_binding_site_rmsd - -import pandas as pd -from pathlib import Path -import re - -from shutil import rmtree -import os from pydantic.v1 import Field + class ScoreInputs(ScoreSpectrumInputsBase): """Schema for inputs for scoring complexes @@ -29,7 +29,7 @@ class ScoreInputs(ScoreSpectrumInputsBase): Path to docking output csv file, from previous drugforge-docking step. ligand_regex : str Pattern for extracting ligand ID from file string. - protein_regex : str + protein_regex : str Pattern for extracting protein ID from file string. bsite_rmsd : bool Whether to calculate binding site RMSD. @@ -57,16 +57,15 @@ class ScoreInputs(ScoreSpectrumInputsBase): Path to directory to save gnina output. """ - docking_csv: Path = Field( - None, description="Path to docking output csv file." - ) + docking_csv: Path = Field(None, description="Path to docking output csv file.") ligand_regex: str = Field( "ASAP-[0-9]+", description="Pattern for extracting ligand ID from file string." ) protein_regex: str = Field( - "YP_[0-9]+_[0-9]+|NP_[0-9]+_[0-9]+", description="Pattern for extracting protein ID from file string." + "YP_[0-9]+_[0-9]+|NP_[0-9]+_[0-9]+", + description="Pattern for extracting protein ID from file string.", ) bsite_rmsd: bool = Field( @@ -86,6 +85,7 @@ class ScoreInputs(ScoreSpectrumInputsBase): OpenMMPlatform.Fastest, description="OpenMM platform to use for MD minimization" ) + def score_complex_workflow(inputs: ScoreInputs): """Run scoring workflow for a set of docked complexes according to spectrum. Prepares a csv file with different types of scores, including: @@ -115,8 +115,8 @@ def score_complex_workflow(inputs: ScoreInputs): new_directory = False output_dir.mkdir(exist_ok=True, parents=True) - output_csv = output_dir/"scores.csv" - if output_csv.exists(): # Delete existing csv file because we are appending to it + output_csv = output_dir / "scores.csv" + if output_csv.exists(): # Delete existing csv file because we are appending to it os.remove(output_csv) logger = FileLogger( @@ -141,7 +141,7 @@ def score_complex_workflow(inputs: ScoreInputs): if inputs.docking_csv.exists(): df_dock = pd.read_csv(inputs.docking_csv) - + if "input" in df_dock.columns: # Match the protein and ligand regex on docking output file logger.info("Reading docking CSV file: %s", inputs.docking_csv) @@ -258,7 +258,9 @@ def score_complex_workflow(inputs: ScoreInputs): ) chain_dock = "1" # Standard in OpenMM output file except FileNotFoundError as error: - logger.error(f"File not found during minimization of {file_min}: {error}") + logger.error( + f"File not found during minimization of {file_min}: {error}" + ) continue except ValueError as error: logger.error(f"Value error during minimization of {file_min}: {error}") @@ -275,8 +277,9 @@ def score_complex_workflow(inputs: ScoreInputs): scorers = [ChemGauss4Scorer()] # load addtional ml scorers if inputs.ml_score: - from drugforge.ml.models import ASAPMLModelRegistry from drugforge.docking.scorer import MLModelScorer + from drugforge.ml.models import ASAPMLModelRegistry + logger.info("Loading additional ML scorers") # check which endpoints are availabe for the target models = ASAPMLModelRegistry.reccomend_models_for_target(inputs.target) @@ -297,12 +300,10 @@ def score_complex_workflow(inputs: ScoreInputs): align_chain=inputs.dock_chain, align_chain_ref=inputs.ref_chain, ) - logger.debug( - "Columns of scoring dataset from drugforge: %s", scores_df.columns - ) + logger.debug("Columns of scoring dataset from drugforge: %s", scores_df.columns) scores_df["premin-score-POSIT"] = pre_min_score df_save = scores_df[["premin-score-POSIT", "docking-score-POSIT"]] - if inputs.ml_score: # Add ML scores + if inputs.ml_score: # Add ML scores if scores_df["docking-score-POSIT"].values: df_save = scores_df[ [ @@ -351,7 +352,10 @@ def score_complex_workflow(inputs: ScoreInputs): logger.debug("The aligned file was saved in %s", aligned) logger.info("Calculating RMSD of the ligand") lig_rmsd = get_ligand_rmsd( - str(aligned), str(file_ref), True, rmsd_mode="oechem", + str(aligned), + str(file_ref), + True, + rmsd_mode="oechem", ) df_save.insert(loc=len(df_save.columns), column="Lig-RMSD", value=lig_rmsd) pout = f"Calculated RMSD of POSIT ligand pose = {lig_rmsd} with ref {file_ref.stem}" @@ -379,7 +383,7 @@ def score_complex_workflow(inputs: ScoreInputs): bsite_rmsd = get_binding_site_rmsd( aligned, file_ref, - bsite_dist=5.0, + bsite_dist=5.0, ligres=inputs.lig_resname, chain_mob=inputs.dock_chain, chain_ref=inputs.ref_chain, @@ -387,13 +391,17 @@ def score_complex_workflow(inputs: ScoreInputs): aligned_temp=aligned, ) except FileNotFoundError as e: - logger.error(f"Reference or aligned file not found for RMSD calculation: {e}") + logger.error( + f"Reference or aligned file not found for RMSD calculation: {e}" + ) bsite_rmsd = -1 except ValueError as e: logger.error(f"Value error during binding site RMSD calculation: {e}") bsite_rmsd = -1 except Exception as e: - logger.exception(f"Unexpected error while computing binding site RMSD: {e}") + logger.exception( + f"Unexpected error while computing binding site RMSD: {e}" + ) bsite_rmsd = -1 df_save.insert( @@ -428,16 +436,22 @@ def score_complex_workflow(inputs: ScoreInputs): rmsd_mode="oechem", overlay=False, ) - logger.info(f"The RMSD of the vina pose was: {lig_rmsd}",) + logger.info( + f"The RMSD of the vina pose was: {lig_rmsd}", + ) except FileNotFoundError as e: - logger.error(f"Reference or pose file not found for RMSD calculation: {e}") + logger.error( + f"Reference or pose file not found for RMSD calculation: {e}" + ) lig_rmsd = -1 except ValueError as e: logger.error(f"Value error during ligand RMSD calculation: {e}") lig_rmsd = -1 except Exception as e: - logger.exception(f"Unexpected error while computing Vina ligand RMSD: {e}") - lig_rmsd = -1 + logger.exception( + f"Unexpected error while computing Vina ligand RMSD: {e}" + ) + lig_rmsd = -1 df_vina["Vina-pose-RMSD"] = lig_rmsd df_save = pd.concat([df_save, df_vina], axis=1, join="inner") @@ -461,5 +475,5 @@ def score_complex_workflow(inputs: ScoreInputs): logger.error( "A gnina bash script must be provided to calculate gnina scores. Won't calculate." ) - df_save.to_csv(output_csv, mode='a', index=False, header=first_write) - first_write = False \ No newline at end of file + df_save.to_csv(output_csv, mode="a", index=False, header=first_write) + first_write = False diff --git a/drugforge-workflows/drugforge/workflows/tests/conftest.py b/drugforge-workflows/drugforge/workflows/tests/conftest.py index 93d2937a..ae3d0f0d 100644 --- a/drugforge-workflows/drugforge/workflows/tests/conftest.py +++ b/drugforge-workflows/drugforge/workflows/tests/conftest.py @@ -1,10 +1,10 @@ import pytest from drugforge.data.backend.openeye import oechem -from drugforge.modeling.schema import PreppedComplex from drugforge.data.schema.ligand import Ligand from drugforge.data.testing.test_resources import fetch_test_file from drugforge.docking.docking import DockingInputMultiStructure, DockingInputPair from drugforge.docking.openeye import POSITDockingResults +from drugforge.modeling.schema import PreppedComplex @pytest.fixture() diff --git a/drugforge-workflows/drugforge/workflows/tests/docking_cli/test_docking_cli.py b/drugforge-workflows/drugforge/workflows/tests/docking_cli/test_docking_cli.py index 4359a4a5..ec9a99a5 100644 --- a/drugforge-workflows/drugforge/workflows/tests/docking_cli/test_docking_cli.py +++ b/drugforge-workflows/drugforge/workflows/tests/docking_cli/test_docking_cli.py @@ -3,10 +3,10 @@ from unittest import mock import pytest +from click.testing import CliRunner from drugforge.docking.docking import DockingResult from drugforge.simulation.simulate import SimulationResult, VanillaMDSimulator from drugforge.workflows.docking_workflows.cli import docking as cli -from click.testing import CliRunner def click_success(result): diff --git a/drugforge-workflows/drugforge/workflows/tests/prep_cli/test_prep_cli.py b/drugforge-workflows/drugforge/workflows/tests/prep_cli/test_prep_cli.py index d7af3ecf..7245da42 100644 --- a/drugforge-workflows/drugforge/workflows/tests/prep_cli/test_prep_cli.py +++ b/drugforge-workflows/drugforge/workflows/tests/prep_cli/test_prep_cli.py @@ -2,10 +2,10 @@ import traceback import pytest +from click.testing import CliRunner from drugforge.data.metadata.resources import master_structures from drugforge.data.testing.test_resources import fetch_test_file from drugforge.workflows.prep_workflows.cli import protein_prep as cli -from click.testing import CliRunner def click_success(result): diff --git a/drugforge-workflows/drugforge/workflows/tests/spectrum_cli/conftest.py b/drugforge-workflows/drugforge/workflows/tests/spectrum_cli/conftest.py index 7ab0a04c..d5b707c2 100644 --- a/drugforge-workflows/drugforge/workflows/tests/spectrum_cli/conftest.py +++ b/drugforge-workflows/drugforge/workflows/tests/spectrum_cli/conftest.py @@ -6,6 +6,7 @@ def blast_xml_path(): return fetch_test_file("SARS_blast_results.xml") + @pytest.fixture(scope="session") def blast_csv_path(): return fetch_test_file("SARS_blast_results.csv") @@ -66,4 +67,4 @@ def fasta_alignment_path(): @pytest.fixture(scope="session") def docking_results_csv_path(): - return fetch_test_file("lt_docking_scores.csv") \ No newline at end of file + return fetch_test_file("lt_docking_scores.csv") diff --git a/drugforge-workflows/drugforge/workflows/tests/spectrum_cli/test_spectrum_cli.py b/drugforge-workflows/drugforge/workflows/tests/spectrum_cli/test_spectrum_cli.py index 6ba2a527..990e3130 100644 --- a/drugforge-workflows/drugforge/workflows/tests/spectrum_cli/test_spectrum_cli.py +++ b/drugforge-workflows/drugforge/workflows/tests/spectrum_cli/test_spectrum_cli.py @@ -2,8 +2,8 @@ import traceback import pytest -from drugforge.workflows.spectrum_workflows.cli import spectrum as cli from click.testing import CliRunner +from drugforge.workflows.spectrum_workflows.cli import spectrum as cli def click_success(result): @@ -49,13 +49,14 @@ def test_seq_alignment_multimer(blast_xml_path, tmp_path): "", "--multimer", "--n-chains", - '2', + "2", "--output-dir", tmp_path, ], ) assert click_success(result) + @pytest.mark.skipif(os.getenv("SKIP_EXPENSIVE_TESTS"), reason="Expensive tests skipped") def test_struct_alignment_single_pdb(blast_csv_path, protein_path, tmp_path): runner = CliRunner() @@ -215,7 +216,9 @@ def test_fitness_alignment_fasta( @pytest.mark.skipif(os.getenv("SKIP_EXPENSIVE_TESTS"), reason="Expensive tests skipped") -def test_score_docking_only(structure_dir, pdb_file, tmp_path, docking_results_csv_path): +def test_score_docking_only( + structure_dir, pdb_file, tmp_path, docking_results_csv_path +): runner = CliRunner() struct_dir, _ = structure_dir csv_save = tmp_path / "scores.csv" @@ -224,7 +227,7 @@ def test_score_docking_only(structure_dir, pdb_file, tmp_path, docking_results_c [ "score", "-d", - struct_dir, + struct_dir, "-f", pdb_file, "-o", @@ -236,8 +239,8 @@ def test_score_docking_only(structure_dir, pdb_file, tmp_path, docking_results_c "--dock-chain", "A", "--ref-chain", - "A" + "A", ], ) assert csv_save.exists() - assert click_success(result) \ No newline at end of file + assert click_success(result) diff --git a/drugforge-workflows/drugforge/workflows/tests/test_postera_live.py b/drugforge-workflows/drugforge/workflows/tests/test_postera_live.py index 5c66a07d..cfe19877 100644 --- a/drugforge-workflows/drugforge/workflows/tests/test_postera_live.py +++ b/drugforge-workflows/drugforge/workflows/tests/test_postera_live.py @@ -7,9 +7,7 @@ import numpy as np import pandas as pd import pytest -from drugforge.data.services.postera.manifold_data_validation import ( - ManifoldAllowedTags, -) +from drugforge.data.services.postera.manifold_data_validation import ManifoldAllowedTags from drugforge.data.services.postera.molecule_set import ( MoleculeList, MoleculeSetAPI, @@ -17,8 +15,8 @@ MoleculeUpdateList, ) from drugforge.data.services.postera.postera_factory import PosteraFactory -from drugforge.workflows.postera.postera_uploader import PosteraUploader from drugforge.data.services.services_config import PosteraSettings +from drugforge.workflows.postera.postera_uploader import PosteraUploader from requests.exceptions import HTTPError # WARNING IMPORTANT: - this is a live test and will make real requests to the POSTERA API