Skip to content

Commit

Permalink
linting, add offline setting
Browse files Browse the repository at this point in the history
  • Loading branch information
SeonghwanSeo committed Dec 25, 2024
1 parent b8926f2 commit e7a7e9a
Show file tree
Hide file tree
Showing 34 changed files with 512 additions and 271 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# USER
.DS_Store
weights
weights/
run.sh
result/
examples/library/
nogit/
maintain_test/
uv.lock


# Byte-compiled / optimized / DLL files
Expand Down
26 changes: 18 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@

# PharmacoNet: Open-source Protein-based Pharmacophore Modeling
[![DOI](https://zenodo.org/badge/699273873.svg)](https://zenodo.org/doi/10.5281/zenodo.12168474)

[![DOI](https://zenodo.org/badge/699273873.svg)](https://zenodo.org/doi/10.5281/zenodo.12168474)

**Before using PharmacoNet, consider using OpenPharmaco - GUI powered by PharmacoNet.**

Expand Down Expand Up @@ -32,7 +31,6 @@ If you have any problems or need help with the code, please add an github issue
- [Pre-trained Docking Proxy](#pretrained-docking-proxy)
- [Citation](#citation)


## Quick Start

```bash
Expand All @@ -50,6 +48,7 @@ python feature_extraction.py --protein <PROTEIN_PATH> --center <X> <Y> <Z> --out
```

## Installation

- Using `environment.yml`
For various environment including Linux, MacOS and Window, the script installs **cpu-only version of PyTorch** by default. You can install a cuda-available version by modifying `environment.yml` or installing PyTorch manually.

Expand All @@ -61,8 +60,9 @@ python feature_extraction.py --protein <PROTEIN_PATH> --center <X> <Y> <Z> --out
```

- Manual Installation

```bash
# Required python>=3.9, Best Performance at higher version. (3.9, 3.10, 3.11, 3.12 - best)
# Required python>=3.9, Best Performance at higher version. (3.9, 3.10, 3.11, 3.12(best))
conda create --name openph python=3.10 openbabel=3.1.1 pymol-open-source=3.0.0 numpy=1.26.4
conda activate pmnet

Expand Down Expand Up @@ -140,6 +140,15 @@ INFO:root:Save Pharmacophore Model to result/6OIM/6OIM_2.0_-8.0_-1.0_model.pm
INFO:root:Save Pymol Visualization Session to result/6OIM/6OIM_2.0_-8.0_-1.0_model.pse
```

#### Example with custom model weight file (offline)

PharmacoNet's weight file is automatically downloaded during `modeling.py`.
If your environment is offline, you can download the weight files from [Google Drive](https://drive.google.com/uc?id=1gzjdM7bD3jPm23LBcDXtkSk18nETL04p).

```bash
> python modeling.py --pdb 6oim --weight_path <WEIGHT_PATH>
```

## Virtual Screening

We provide the simple script for screening.
Expand Down Expand Up @@ -175,7 +184,7 @@ score = model.scoring_smiles(<SMILES>, <NUM_CONFORMERS>)

## Pharmacophore Feature Extraction

***See: [`./developer/`](/developer/), [`./src/pmnet_appl/`](/src/pmnet_appl/).***
**_See: [`./developer/`](/developer/), [`./src/pmnet_appl/`](/src/pmnet_appl/)._**

For deep learning researcher who want to use PharmacoNet as pre-trained model for feature extraction, we provide the python API.

Expand Down Expand Up @@ -225,19 +234,21 @@ pmnet_attr = (multi_scale_features, hotspot_infos)
```

## Pretrained Docking Proxy
***See: [`./src/pmnet_appl/`](/src/pmnet_appl/).***

**_See: [`./src/pmnet_appl/`](/src/pmnet_appl/)._**

We provide pre-trained docking proxy models which predict docking score against arbitrary protein using PharmacoNet.
We hope this implementation prompts the molecule optimization.

If you use this implementation, please cite PharmacoNet with original papers.

Implementation List:

- TacoGFN: Target-conditioned GFlowNet for Structure-based Drug Design [[paper](https://arxiv.org/abs/2310.03223)]

Related Works:
- RxnFlow: Generative Flows on Synthetic Pathway for Drug Design [paper]

- RxnFlow: Generative Flows on Synthetic Pathway for Drug Design [paper]

## Citation

Expand All @@ -252,4 +263,3 @@ Paper on [arxiv](https://arxiv.org/abs/2310.00681)
url = {https://arxiv.org/abs/2310.00681},
}
```

60 changes: 44 additions & 16 deletions modeling.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,13 @@ def __init__(self):
cfg_args = self.add_argument_group("config")
cfg_args.add_argument("--pdb", type=str, help="RCSB PDB code")
cfg_args.add_argument("-l", "--ligand_id", type=str, help="RCSB ligand code")
cfg_args.add_argument("-p", "--protein", type=str, help="custom path of protein pdb file (.pdb)")
cfg_args.add_argument(
"-p", "--protein", type=str, help="custom path of protein pdb file (.pdb)"
)
cfg_args.add_argument("-c", "--chain", type=str, help="Chain")
cfg_args.add_argument("-a", "--all", action="store_true", help="use all binding sites")
cfg_args.add_argument(
"-a", "--all", action="store_true", help="use all binding sites"
)
cfg_args.add_argument(
"--out_dir",
type=str,
Expand All @@ -43,8 +47,15 @@ def __init__(self):

# system config
env_args = self.add_argument_group("environment")
env_args.add_argument("--cuda", action="store_true", help="use gpu acceleration with CUDA")
env_args.add_argument("--force", action="store_true", help="force to save the pharmacophore model")
env_args.add_argument(
"--weight_path", type=str, help="(Optional) custom pharmaconet weight path"
)
env_args.add_argument(
"--cuda", action="store_true", help="use gpu acceleration with CUDA"
)
env_args.add_argument(
"--force", action="store_true", help="force to save the pharmacophore model"
)
env_args.add_argument("-v", "--verbose", action="store_true", help="verbose")

# config
Expand All @@ -54,12 +65,16 @@ def __init__(self):
type=str,
help="path of ligand to define the center of box (.sdf, .pdb, .mol2)",
)
adv_args.add_argument("--center", nargs="+", type=float, help="coordinate of the center")
adv_args.add_argument(
"--center", nargs="+", type=float, help="coordinate of the center"
)


def main(args):
logging.info(pmnet.__description__)
assert args.prefix is not None or args.pdb is not None, "MISSING PREFIX: `--prefix` or `--pdb`"
assert (
args.prefix is not None or args.pdb is not None
), "MISSING PREFIX: `--prefix` or `--pdb`"
PREFIX = args.prefix if args.prefix else args.pdb

# NOTE: Setting
Expand All @@ -70,19 +85,20 @@ def main(args):
SAVE_DIR.mkdir(exist_ok=True, parents=True)

# NOTE: Load PharmacoNet
module = PharmacoNet("cuda" if args.cuda else "cpu")
logging.info(f"Load PharmacoNet finish")
module = PharmacoNet("cuda" if args.cuda else "cpu", weight_path=args.weight_path)
logging.info("Load PharmacoNet finish")

# NOTE: Set Protein
protein_path: str
if isinstance(args.pdb, str):
protein_path: str = str(SAVE_DIR / f"{PREFIX}.pdb")
protein_path = str(SAVE_DIR / f"{PREFIX}.pdb")
if not os.path.exists(protein_path):
logging.info(f"Download {args.pdb} to {protein_path}")
download_pdb(args.pdb, protein_path)
else:
logging.info(f"Load {protein_path}")
elif isinstance(args.protein, str):
protein_path: str = args.protein
protein_path = args.protein
assert os.path.exists(protein_path)
logging.info(f"Load {protein_path}")
else:
Expand All @@ -96,13 +112,17 @@ def run_pmnet(filename, ligand_path=None, center=None) -> PharmacophoreModel:
logging.warning(f"Modeling Pass - {model_path} exists")
pharmacophore_model = PharmacophoreModel.load(str(model_path))
else:
pharmacophore_model = module.run(protein_path, ref_ligand_path=ligand_path, center=center)
pharmacophore_model = module.run(
protein_path, ref_ligand_path=ligand_path, center=center
)
pharmacophore_model.save(str(model_path))
logging.info(f"Save Pharmacophore Model to {model_path}")
if (not args.force) and os.path.exists(pymol_path):
logging.warning(f"Visualizing Pass - {pymol_path} exists\n")
else:
visualize.visualize_single(pharmacophore_model, protein_path, ligand_path, PREFIX, str(pymol_path))
visualize.visualize_single(
pharmacophore_model, protein_path, ligand_path, PREFIX, str(pymol_path)
)
logging.info(f"Save Pymol Visualization Session to {pymol_path}\n")
return pharmacophore_model

Expand Down Expand Up @@ -173,16 +193,22 @@ def run_pmnet_manual_center():
if (not args.force) and os.path.exists(pymol_path):
logging.warning(f"Visualizing Pass - {pymol_path} exists\n")
else:
visualize.visualize_multiple(model_dict, protein_path, PREFIX, str(pymol_path))
visualize.visualize_multiple(
model_dict, protein_path, PREFIX, str(pymol_path)
)
logging.info(f"Save Pymol Visualization Session to {pymol_path}\n")
return

inform_list_text = "\n\n".join(str(inform) for inform in inform_list)
logging.info(f"A total of {len(inform_list)} ligand(s) are detected!\n{inform_list_text}\n")
logging.info(
f"A total of {len(inform_list)} ligand(s) are detected!\n{inform_list_text}\n"
)

# NOTE: Case 3-3: pattern matching
if args.ligand_id is not None or args.chain is not None:
logging.info(f"Filtering with matching pattern - ligand id: {args.ligand_id}, chain: {args.chain}")
logging.info(
f"Filtering with matching pattern - ligand id: {args.ligand_id}, chain: {args.chain}"
)
filtered_inform_list = []
for inform in inform_list:
if args.ligand_id is not None and args.ligand_id.upper() != inform.id:
Expand All @@ -201,7 +227,9 @@ def run_pmnet_manual_center():
return FAIL
if len(inform_list) > 1:
inform_list_text = "\n\n".join(str(inform) for inform in inform_list)
logging.info(f"A total of {len(inform_list)} ligands are selected!\n{inform_list_text}\n")
logging.info(
f"A total of {len(inform_list)} ligands are selected!\n{inform_list_text}\n"
)

if len(inform_list) == 1:
run_pmnet_inform(inform_list[0])
Expand Down
14 changes: 9 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "pharmaconet"
version = "2.1.0"
version = "2.1.1"
description = "PharmacoNet: Open-Source Software for Protein-based Pharmacophore Modeling and Virtual Screening"
license = { text = "MIT" }
authors = [{ name = "Seonghwan Seo", email = "shwan0106@kaist.ac.kr" }]
Expand All @@ -31,7 +31,8 @@ dependencies = [
"omegaconf>=2.3.0",
"molvoxel>=0.1.3",
"gdown>=5.1.0",
"biopython>=1.83"
"biopython>=1.83",
"ruff>=0.8.4",
]

[project.optional-dependencies]
Expand Down Expand Up @@ -68,19 +69,22 @@ line-length = 120
select = ["E", "F", "B", "UP", "T203",]
ignore = ["E501"]

[tool.ruff.per-file-ignores]
[tool.ruff.lint.per-file-ignores]
"__init__.py" = [
"F401", # imported but unused
"E402", # Module level import not at top of file
]

[tool.pyright]
[tool.basedpyright]
pythonVersion = "3.10"
typeCheckingMode = "standard"
diagnosticMode = "openFilesOnly"
reportImplicitStringConcatenation = false
useLibraryCodeForTypes = true
reportGeneralTypeIssues = "warning"
reportDeprecated = "warning"
reportUnusedVariable = false
reportUnusedImport = false

venvPath = '.'
venv = '.venv'
exclude = [".venv/"]
8 changes: 2 additions & 6 deletions src/pmnet/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
from .pharmacophore_model import PharmacophoreModel

__version__ = "2.1.0"
__citation_information__ = (
"Seo, S., & Kim, W. Y. (2023, December). "
"PharmacoNet: Accelerating Large-Scale Virtual Screening by Deep Pharmacophore Modeling. "
"In NeurIPS 2023 Workshop on New Frontiers of AI for Drug Discovery and Development."
)
__version__ = "2.1.1"
__citation_information__ = "Seo, S., & Kim, W. Y. (2024). PharmacoNet: deep learning-guided pharmacophore modeling for ultra-large-scale virtual screening. Chemical Science, 15(46), 19473-19487."
__maintainer__ = "https://github.com/SeonghwanSeo/PharmacoNet"

__description__ = (
Expand Down
6 changes: 3 additions & 3 deletions src/pmnet/data/constant.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Sequence, Set
from collections.abc import Sequence

INTERACTION_LIST: Sequence[str] = (
"Hydrophobic",
Expand Down Expand Up @@ -40,7 +40,7 @@
XBOND: 4.5, # 4.0 + 0.5
}

LONG_INTERACTION: Set[int] = {
LONG_INTERACTION: set[int] = {
PISTACKING_P,
PISTACKING_T,
PICATION_PRING,
Expand All @@ -49,7 +49,7 @@
SALTBRIDGE_PNEG,
}

SHORT_INTERACTION: Set[int] = {
SHORT_INTERACTION: set[int] = {
HYDROPHOBIC,
HBOND_LDON,
HBOND_PDON,
Expand Down
3 changes: 1 addition & 2 deletions src/pmnet/data/extract_pocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from Bio.PDB import PDBParser, PDBIO
from Bio.PDB.PDBIO import Select

from typing import Union
from numpy.typing import ArrayLike
from pathlib import Path

Expand Down Expand Up @@ -87,7 +86,7 @@ def accept_residue(self, residue):


def extract_pocket(
protein_pdb_path: Union[str, Path], out_pocket_pdb_path: str, center: ArrayLike, cutoff: float = DEFAULT_CUTOFF
protein_pdb_path: str | Path, out_pocket_pdb_path: str, center: ArrayLike, cutoff: float = DEFAULT_CUTOFF
):
parser = PDBParser()
structure = parser.get_structure("protein", str(protein_pdb_path))
Expand Down
Loading

0 comments on commit e7a7e9a

Please sign in to comment.