Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions devtools/conda-envs/macos-latest/spectrum.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ dependencies:
- biopython
- mdanalysis
- openeye-toolkits
- openfe ~=1.0
- openmm
- gufe >=1.0.0
- pymol-open-source
- rdkit
- plip
Expand Down
2 changes: 1 addition & 1 deletion drugforge-alchemy/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ dependencies = []
"Bug Tracker" = "https://github.com/choderalab/drugforge/issues"

[project.scripts]
asap-alchemy = "drugforge.alchemy.cli.cli:alchemy"
drugforge-alchemy = "drugforge.alchemy.cli.cli:alchemy"

[tool.setuptools.packages.find]
where = ["."]
Expand Down
2 changes: 1 addition & 1 deletion drugforge-cli/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ dependencies = []
"Bug Tracker" = "https://github.com/choderalab/drugforge/issues"

[project.scripts]
asap-cli = "drugforge.cli.cli:cli"
drugforge-cli = "drugforge.cli.cli:cli"

[tool.setuptools.packages.find]
where = ["."]
Expand Down
10 changes: 5 additions & 5 deletions drugforge-data/drugforge/data/schema/ligand.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
)

if TYPE_CHECKING:
import openfe
import gufe
from rdkit import Chem

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -386,16 +386,16 @@ def to_rdkit(self) -> "Chem.Mol":
set_SD_data(rdkit_mol, data)
return rdkit_mol

def to_openfe(self) -> "openfe.SmallMoleculeComponent":
def to_openfe(self) -> "gufe.components.SmallMoleculeComponent":
"""
Convert to an openfe SmallMoleculeComponent via the rdkit interface.
"""
import openfe
import gufe

return openfe.SmallMoleculeComponent.from_rdkit(self.to_rdkit())
return gufe.components.SmallMoleculeComponent.from_rdkit(self.to_rdkit())

@classmethod
def from_openfe(cls, mol: "openfe.SmallMoleculeComponent", **kwargs) -> "Ligand":
def from_openfe(cls, mol: "gufe.components.SmallMoleculeComponent", **kwargs) -> "Ligand":
"""
Create a Ligand from an openfe SmallMoleculeComponent
"""
Expand Down
2 changes: 1 addition & 1 deletion drugforge-data/drugforge/data/testing/test_files.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ files:
- resource: Mpro-YP_009725301_AFold_processed.pdb
sha256hash: 3cdc93de0186243d790e7abd61d77eacde649f547f3d0cd0aaa58243631431f8

# asap-spectrum testing
# spectrum testing
- resource: SARS_blast_results.xml
sha256hash: d6e59d1f6b2eeee5162cca4dbeee7ffcd56eeeabdb733a505ff86ee1588cf8f6

Expand Down
2 changes: 1 addition & 1 deletion drugforge-ml/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ dependencies = []
"Bug Tracker" = "https://github.com/choderalab/drugforge/issues"

[project.scripts]
asap-ml = "drugforge.ml.cli:ml"
drugforge-ml = "drugforge.ml.cli:ml"
convert-ds = "drugforge.ml.scripts.convert_dataset:convert"

[tool.setuptools.packages.find]
Expand Down
42 changes: 42 additions & 0 deletions drugforge-simulation/drugforge/simulation/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
output_dir,
pdb_file,
use_dask,
target
)
from drugforge.data.readers.molfile import MolFileFactory
from drugforge.data.schema.complex import Complex
from drugforge.data.util.dask_utils import DaskType, make_dask_client_meta
from drugforge.data.util.logging import FileLogger
from drugforge.simulation.simulate import OpenMMPlatform, VanillaMDSimulator
from drugforge.simulation.simulate import minimize_from_pdb
from openmm import unit


Expand Down Expand Up @@ -144,3 +146,43 @@ def vanilla_md(
@pdb_file
def szybki():
raise NotImplementedError("Szybki simulation not yet implemented")

@simulation.command()
@pdb_file
@click.option(
"--min-out",
type=str,
default="minimized.pdb",
help="Optional file name for saving result of BLAST search",
)
@output_dir
@md_openmm_platform
@target
@loglevel
def minimize(
pdb_file: Union[Path, str],
min_out: Union[Path, str],
output_dir: Union[Path, str],
md_openmm_platform: str,
target: str,
loglevel: Union[int, str] = logging.INFO,
):
logger = FileLogger(
"", # default root logger so that dask logging is forwarded
path=output_dir,
logfile="vanilla_md.log",
stdout=True,
level=loglevel,
).getLogger()

logger.info("Running minimization")

minimize_from_pdb(
pdb_file=pdb_file,
min_out=min_out,
output_dir=output_dir,
md_openmm_platform=md_openmm_platform,
target=target,
)
logger.info(f"Minimized structure saved to {min_out}")

70 changes: 70 additions & 0 deletions drugforge-simulation/drugforge/simulation/simulate.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import abc
import logging
import os
import shutil
import warnings
from pathlib import Path
Expand Down Expand Up @@ -653,3 +654,72 @@ def run_production_simulation(

def provenance(self) -> dict[str, str]:
return {}

def minimize_from_pdb(
pdb_file: Union[Path, str],
min_out: Union[Path, str],
output_dir: Union[Path, str],
md_openmm_platform: str,
target: str,
) -> Union[Path, str]:
"""MD energy minimization a protein ligand complex.
Energy minimization is performed with OpenMM (no equilibration or production MD is performed).

Parameters
----------
pdb_complex : Union[Path, str]
Path to protein ligand complex pdb
min_out : Union[Path, str]
Output file with minimized pdb
out_dir : Union[Path, str]
Directory to save output minimized complex
md_platform : str
MD OpenMM platform [CPU, CUDA, OpenCL, Reference, Fastest]
target : str
Name of reference target (see drugforge documentation).

Returns
-------
str
Path to minimized file
"""
from drugforge.data.schema.complex import Complex
from drugforge.modeling.schema import PreppedComplex

if Path(min_out).is_file():
logger.warning(
f"The file {min_out} already exists. The minimization will be skipped"
)
return min_out
comp_name = "MOL"
cmp = Complex.from_pdb(
pdb_file,
ligand_kwargs={"compound_name": comp_name},
target_kwargs={"target_name": target},
)
out_dir = Path(output_dir)
prepped_cmp = PreppedComplex.from_complex(cmp)
prepped_cmp.target.to_pdb_file(out_dir / "target.pdb")
cmp.ligand.to_sdf(out_dir / "ligand.sdf")

md_simulator = VanillaMDSimulator(
output_dir=out_dir,
openmm_platform=md_openmm_platform,
minimize_only=True,
num_steps=1,
)
simulation_results = md_simulator.simulate(
[(out_dir / "target.pdb", out_dir / "ligand.sdf")],
outpaths=[out_dir],
failure_mode="skip",
)
min_path = simulation_results[0].minimized_pdb_path
shutil.move(min_path, min_out)
shutil.rmtree(f"{out_dir}/target_ligand", ignore_errors=True)
for file_path in [f"{out_dir}/target.pdb", f"{out_dir}/ligand.sdf"]:
try:
os.remove(file_path)
except FileNotFoundError:
pass

return min_out
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def ligand_path():

@pytest.fixture(scope="session")
def protein_path():
return fetch_test_file("Mpro-x0071_0A_ERI-UCB-8c6b7d0d-1.pdb")
return fetch_test_file("Mpro-P2660_0A_bound.pdb")


@pytest.fixture(scope="session")
Expand Down
25 changes: 25 additions & 0 deletions drugforge-simulation/drugforge/simulation/tests/test_simulate.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from unittest import mock

import pytest
from pathlib import Path
from drugforge.docking.docking import DockingResult
from drugforge.docking.openeye import POSITDockingResults
from drugforge.simulation.cli import simulation as cli
Expand Down Expand Up @@ -201,3 +202,27 @@ def _simulate_patch(
]
result = runner.invoke(cli, args)
assert click_success(result)



@pytest.mark.skipif(os.getenv("SKIP_EXPENSIVE_TESTS"), reason="Expensive tests skipped")
def test_minimize_cli(protein_path, tmp_path):
"""Test minimization of protein PDB using OpenMM."""
runner = CliRunner()
min_out = f"{tmp_path}/min_out.pdb"
args = [
"minimize",
"--pdb-file",
protein_path,
"--min-out",
min_out,
"--output-dir",
tmp_path,
"--md-openmm-platform",
"CPU",
"--target",
"SARS-CoV-2-Mpro",
]
result = runner.invoke(cli, args)
assert click_success(result)
assert Path(min_out).exists()
71 changes: 0 additions & 71 deletions drugforge-spectrum/drugforge/spectrum/score.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
)
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

Expand Down Expand Up @@ -641,73 +640,3 @@ def score_gnina(pdb_target:str,
]
)
return df


def minimize_structure(
pdb_complex: Union[Path, str],
min_out: Union[Path, str],
out_dir: Union[Path, str],
md_platform: str,
comp_name: str,
target_name: str,
) -> Union[Path, str]:
"""MD energy minimization a protein ligand complex.
Energy minimization is performed with OpenMM (no equilibration or production MD is performed).

Parameters
----------
pdb_complex : Union[Path, str]
Path to protein ligand complex pdb
min_out : Union[Path, str]
Output file with minimized pdb
out_dir : Union[Path, str]
Directory to save output minimized complex
md_platform : str
MD OpenMM platform [CPU, CUDA, OpenCL, Reference, Fastest]
comp_name : str
Name of to give to complex. Can be arbitrary.
target_name : str
Name of reference target (see drugforge documentation).

Returns
-------
str
Path to minimized file
"""

if Path(min_out).is_file():
logger.warning(
f"The file {min_out} already exists. The minimization will be skipped"
)
return min_out
cmp = Complex.from_pdb(
pdb_complex,
ligand_kwargs={"compound_name": comp_name},
target_kwargs={"target_name": target_name},
)
out_dir = Path(out_dir)
prepped_cmp = PreppedComplex.from_complex(cmp)
prepped_cmp.target.to_pdb_file(out_dir / "target.pdb")
cmp.ligand.to_sdf(out_dir / "ligand.sdf")

md_simulator = VanillaMDSimulator(
output_dir=out_dir,
openmm_platform=md_platform,
minimize_only=True,
num_steps=1,
)
simulation_results = md_simulator.simulate(
[(out_dir / "target.pdb", out_dir / "ligand.sdf")],
outpaths=[out_dir],
failure_mode="skip",
)
min_path = simulation_results[0].minimized_pdb_path
shutil.move(min_path, min_out)
shutil.rmtree(f"{out_dir}/target_ligand", ignore_errors=True)
for file_path in [f"{out_dir}/target.pdb", f"{out_dir}/ligand.sdf"]:
try:
os.remove(file_path)
except FileNotFoundError:
pass

return min_out
16 changes: 0 additions & 16 deletions drugforge-spectrum/drugforge/spectrum/tests/test_score.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
dock_and_score,
get_ligand_rmsd,
score_autodock_vina,
minimize_structure
)
from drugforge.spectrum.calculate_rmsd import get_binding_site_rmsd
from drugforge.docking.scorer import ChemGauss4Scorer
Expand Down Expand Up @@ -105,18 +104,3 @@ def test_vina_score(target_prepped_vina, ligand_prepped_vina):
dock=False,
)
assert df_vina["Vina-score-premin"].values[0] < 0


@pytest.mark.skipif(os.getenv("SKIP_EXPENSIVE_TESTS"), reason="Expensive tests skipped")
def test_minimize(protein_path, tmp_path):
"""Test minimization of protein PDB using OpenMM."""
min_out = f"{tmp_path}/min_out.pdb"
minimize_structure(
pdb_complex = protein_path,
min_out = min_out,
out_dir = tmp_path,
md_platform = 'CPU',
comp_name = 'Mol',
target_name = 'SARS-CoV-2',)

assert Path(min_out).exists()
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ def fitness_alignment(
"--ml-score",
is_flag=True,
default=False,
help="Whether to employ asap-implemented ML models to score poses.",
help="Whether to employ implemented ML models to score poses.",
)
@click.option(
"--bsite-rmsd",
Expand Down
Loading
Loading