diff --git a/.github/workflows/test_dev.yml b/.github/workflows/test_dev.yml new file mode 100644 index 0000000..c9e51a6 --- /dev/null +++ b/.github/workflows/test_dev.yml @@ -0,0 +1,40 @@ +# This workflow will install Python dependencies, run tests and lint with a variety of Python versions +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python + +name: Tests (dev) + +on: + push: + branches: [ "dev" ] + pull_request: + branches: [ "dev" ] + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install flake8 pytest + python -m pip install -e . + - name: Lint with flake8 + run: | + # stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + - name: Test with pytest + run: | + pytest diff --git a/.github/workflows/test_master.yml b/.github/workflows/test_master.yml new file mode 100644 index 0000000..adc98b5 --- /dev/null +++ b/.github/workflows/test_master.yml @@ -0,0 +1,40 @@ +# This workflow will install Python dependencies, run tests and lint with a variety of Python versions +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python + +name: Tests (master) + +on: + push: + branches: [ "master"] + pull_request: + branches: [ "master"] + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install flake8 pytest + python -m pip install -e . + - name: Lint with flake8 + run: | + # stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + - name: Test with pytest + run: | + pytest diff --git a/README.md b/README.md index 65481fd..458cbde 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,13 @@ # Fréchet ChemNet Distance +![PyPI](https://img.shields.io/pypi/v/fcd) +![PyPI - Python Version](https://img.shields.io/pypi/pyversions/fcd) +![Tests (master)](https://github.com/bioinf-jku/fcd/actions/workflows/test_master.yml/badge.svg?branch=dev) +![Tests (dev)](https://github.com/bioinf-jku/fcd/actions/workflows/test_dev.yml/badge.svg?branch=dev) +![PyPI - Downloads](https://img.shields.io/pypi/dm/fcd) +![GitHub release (latest by date)](https://img.shields.io/github/v/release/bioinf-jku/fcd) +![GitHub release date](https://img.shields.io/github/release-date/bioinf-jku/fcd) +![GitHub](https://img.shields.io/github/license/bioinf-jku/fcd) + Code for the paper "Fréchet ChemNet Distance: A Metric for Generative Models for Molecules in Drug Discovery" [JCIM](https://pubs.acs.org/doi/10.1021/acs.jcim.8b00234) / diff --git a/fcd/__init__.py b/fcd/__init__.py index 1099eed..cee3edd 100644 --- a/fcd/__init__.py +++ b/fcd/__init__.py @@ -11,4 +11,4 @@ "canonical_smiles", ] -__version__ = "1.2" +__version__ = "1.2.1" diff --git a/fcd/fcd.py b/fcd/fcd.py index 47f2509..b0f14d7 100644 --- a/fcd/fcd.py +++ b/fcd/fcd.py @@ -50,7 +50,7 @@ def get_predictions( smiles_list: List[str], batch_size: int = 128, n_jobs: int = 1, - device: str | None = None, + device: Optional[str] = None, ) -> np.ndarray: """Calculate Chemnet activations @@ -81,7 +81,7 @@ def get_predictions( return np.row_stack(chemnet_activations) -def get_fcd(smiles1: List[str], smiles2: List[str], model: nn.Module | None = None, device=None) -> float: +def get_fcd(smiles1: List[str], smiles2: List[str], model: Optional[nn.Module] = None, device=None) -> float: """Calculate FCD between two sets of Smiles Args: diff --git a/fcd/utils.py b/fcd/utils.py index 4040188..ea780e6 100644 --- a/fcd/utils.py +++ b/fcd/utils.py @@ -2,7 +2,7 @@ import warnings from contextlib import contextmanager from multiprocessing import Pool -from typing import List +from typing import List, Optional import numpy as np import torch @@ -43,7 +43,7 @@ def tokenize(smiles: str) -> List[str]: return tok_smile -def get_one_hot(smiles: str, pad_len: int | None = None) -> np.ndarray: +def get_one_hot(smiles: str, pad_len: Optional[int] = None) -> np.ndarray: """Generate one-hot representation of a Smiles string. Args: diff --git a/test/test_fcd.py b/test/test_fcd.py index c1a3b27..81395da 100644 --- a/test/test_fcd.py +++ b/test/test_fcd.py @@ -1,9 +1,9 @@ -import pytest import numpy as np +import pytest +from pytest import approx from fcd import get_fcd -from fcd.utils import get_one_hot, SmilesDataset -from pytest import approx +from fcd.utils import SmilesDataset, get_one_hot class TestFCD: @@ -12,7 +12,7 @@ def test_random_smiles_cpu(self): smiles_list2 = ["ISi#()", "Si#()+", "#()+-", "()+-1"] target = 8.8086 fcd = get_fcd(smiles_list1, smiles_list2, device="cpu") - assert fcd == approx(target, abs=1e-3) + assert fcd == approx(target, abs=1e-2) def test_random_smiles_gpu(self): # Skip test if CUDA is not available