pautodock 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pautodock-1.0.0/PKG-INFO +83 -0
- pautodock-1.0.0/Readme.md +57 -0
- pautodock-1.0.0/pyproject.toml +41 -0
- pautodock-1.0.0/src/pautodock/__init__.py +1 -0
- pautodock-1.0.0/src/pautodock/__main__.py +82 -0
- pautodock-1.0.0/src/pautodock/__recover_output__.py +61 -0
- pautodock-1.0.0/src/pautodock/adparallel.py +429 -0
- pautodock-1.0.0/src/pautodock/fileutils.py +66 -0
- pautodock-1.0.0/src/pautodock/mgltoolsinstall.py +67 -0
- pautodock-1.0.0/src/pautodock/molop.py +145 -0
- pautodock-1.0.0/src/pautodock/multimol2op.py +81 -0
pautodock-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: pautodock
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A simple tool to parallelize AutoDock JOBs
|
|
5
|
+
Home-page: https://github.com/gmrandazzo/PAutoDock
|
|
6
|
+
License: lglpv3
|
|
7
|
+
Author: Giuseppe Marco Randazzo
|
|
8
|
+
Author-email: gmrandazzo@gmail.com
|
|
9
|
+
Requires-Python: >=3.8,<4.0
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
|
|
12
|
+
Classifier: License :: Other/Proprietary License
|
|
13
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
14
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
22
|
+
Requires-Dist: requests (>=2.32.3,<3.0.0)
|
|
23
|
+
Project-URL: Repository, https://github.com/gmrandazzo/PAutoDock
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# PAutodock - Parallelize AutoDock JOBs
|
|
27
|
+
|
|
28
|
+
PAutodock is a powerful set of scripts designed to parallelize AutoDock jobs, enabling fast screening across multiple CPUs. This tool is particularly useful for researchers and scientists working in computational biology and drug discovery, allowing them to efficiently manage and execute docking simulations.
|
|
29
|
+
|
|
30
|
+
## Table of Contents
|
|
31
|
+
|
|
32
|
+
- [License](#license)
|
|
33
|
+
- [Dependencies](#dependencies)
|
|
34
|
+
- [Changelog](#changelog)
|
|
35
|
+
- [Usage](#usage)
|
|
36
|
+
- [Contributing](#contributing)
|
|
37
|
+
- [Contact](#contact)
|
|
38
|
+
|
|
39
|
+
## License
|
|
40
|
+
|
|
41
|
+
PAutodock is distributed under the GPLv3 license. For detailed information on how the license works, please refer to the file "LICENSE" or visit [GNU GPLv3 License](http://www.gnu.org/licenses/gpl-3.0.en.html).
|
|
42
|
+
|
|
43
|
+
Copyright © Giuseppe Marco Randazzo <gmrandazzo@gmail.com>
|
|
44
|
+
|
|
45
|
+
## Dependencies
|
|
46
|
+
|
|
47
|
+
To run PAutodock, you will need the following software installed:
|
|
48
|
+
|
|
49
|
+
- [AutoDock](http://autodock.scripps.edu/)
|
|
50
|
+
- [AutoGrid](http://autodock.scripps.edu/resources/autogrid)
|
|
51
|
+
- [AutoDock Vina](http://vina.scripps.edu/)
|
|
52
|
+
- [OpenBabel](http://openbabel.org/index.html)
|
|
53
|
+
|
|
54
|
+
Ensure that these dependencies are properly installed and accessible from your command line.
|
|
55
|
+
|
|
56
|
+
## Changelog
|
|
57
|
+
|
|
58
|
+
- **2024**: Revamp in a more organized form
|
|
59
|
+
- **2022**: First time online
|
|
60
|
+
- **2017**: Initial release
|
|
61
|
+
|
|
62
|
+
## Usage
|
|
63
|
+
|
|
64
|
+
To use PAutodock for parallelizing AutoDock jobs, follow these steps:
|
|
65
|
+
|
|
66
|
+
1. **Prepare the Receptor and Ligand**:
|
|
67
|
+
- Ensure you have a receptor file (in PDB format) that represents the target protein or enzyme.
|
|
68
|
+
- Prepare a ligand file (also in PDB format) that contains the molecule you want to dock with the receptor.
|
|
69
|
+
|
|
70
|
+
2. **Create a Multimol2 File**:
|
|
71
|
+
- Prepare a multimol2 file that includes all the ligands you wish to screen.
|
|
72
|
+
- Each ligand in the file must have:
|
|
73
|
+
- **Partial Charges**: Ensure that the ligands have Gasteiger partial charges assigned.
|
|
74
|
+
- **3D Coordinates**: The ligands should be represented in 3D space.
|
|
75
|
+
- **Unique Names**: Each molecule must have a unique name to avoid conflicts during the screening process.
|
|
76
|
+
|
|
77
|
+
3. **Execute the Command**:
|
|
78
|
+
- Once your receptor and multimol2 file are ready, execute the following command in your terminal:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
cd data/3EML
|
|
82
|
+
pautodock --receptor rec.pdb --cx -9.06364 --cy -7.1446 --cz 55.8626 --db dataset.mol2 --wdir example_calculation --out screening_results.csv --vina ON --atd OFF
|
|
83
|
+
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# PAutodock - Parallelize AutoDock JOBs
|
|
2
|
+
|
|
3
|
+
PAutodock is a powerful set of scripts designed to parallelize AutoDock jobs, enabling fast screening across multiple CPUs. This tool is particularly useful for researchers and scientists working in computational biology and drug discovery, allowing them to efficiently manage and execute docking simulations.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [License](#license)
|
|
8
|
+
- [Dependencies](#dependencies)
|
|
9
|
+
- [Changelog](#changelog)
|
|
10
|
+
- [Usage](#usage)
|
|
11
|
+
- [Contributing](#contributing)
|
|
12
|
+
- [Contact](#contact)
|
|
13
|
+
|
|
14
|
+
## License
|
|
15
|
+
|
|
16
|
+
PAutodock is distributed under the GPLv3 license. For detailed information on how the license works, please refer to the file "LICENSE" or visit [GNU GPLv3 License](http://www.gnu.org/licenses/gpl-3.0.en.html).
|
|
17
|
+
|
|
18
|
+
Copyright © Giuseppe Marco Randazzo <gmrandazzo@gmail.com>
|
|
19
|
+
|
|
20
|
+
## Dependencies
|
|
21
|
+
|
|
22
|
+
To run PAutodock, you will need the following software installed:
|
|
23
|
+
|
|
24
|
+
- [AutoDock](http://autodock.scripps.edu/)
|
|
25
|
+
- [AutoGrid](http://autodock.scripps.edu/resources/autogrid)
|
|
26
|
+
- [AutoDock Vina](http://vina.scripps.edu/)
|
|
27
|
+
- [OpenBabel](http://openbabel.org/index.html)
|
|
28
|
+
|
|
29
|
+
Ensure that these dependencies are properly installed and accessible from your command line.
|
|
30
|
+
|
|
31
|
+
## Changelog
|
|
32
|
+
|
|
33
|
+
- **2024**: Revamp in a more organized form
|
|
34
|
+
- **2022**: First time online
|
|
35
|
+
- **2017**: Initial release
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
To use PAutodock for parallelizing AutoDock jobs, follow these steps:
|
|
40
|
+
|
|
41
|
+
1. **Prepare the Receptor and Ligand**:
|
|
42
|
+
- Ensure you have a receptor file (in PDB format) that represents the target protein or enzyme.
|
|
43
|
+
- Prepare a ligand file (also in PDB format) that contains the molecule you want to dock with the receptor.
|
|
44
|
+
|
|
45
|
+
2. **Create a Multimol2 File**:
|
|
46
|
+
- Prepare a multimol2 file that includes all the ligands you wish to screen.
|
|
47
|
+
- Each ligand in the file must have:
|
|
48
|
+
- **Partial Charges**: Ensure that the ligands have Gasteiger partial charges assigned.
|
|
49
|
+
- **3D Coordinates**: The ligands should be represented in 3D space.
|
|
50
|
+
- **Unique Names**: Each molecule must have a unique name to avoid conflicts during the screening process.
|
|
51
|
+
|
|
52
|
+
3. **Execute the Command**:
|
|
53
|
+
- Once your receptor and multimol2 file are ready, execute the following command in your terminal:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
cd data/3EML
|
|
57
|
+
pautodock --receptor rec.pdb --cx -9.06364 --cy -7.1446 --cz 55.8626 --db dataset.mol2 --wdir example_calculation --out screening_results.csv --vina ON --atd OFF
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
[tool.black]
|
|
2
|
+
line-length = 88
|
|
3
|
+
target-version = ["py311"]
|
|
4
|
+
|
|
5
|
+
[tool.isort]
|
|
6
|
+
profile = "black"
|
|
7
|
+
|
|
8
|
+
[tool.poetry]
|
|
9
|
+
name = "pautodock"
|
|
10
|
+
version = "1.0.0"
|
|
11
|
+
description = "A simple tool to parallelize AutoDock JOBs"
|
|
12
|
+
authors = ["Giuseppe Marco Randazzo <gmrandazzo@gmail.com>"]
|
|
13
|
+
readme = "Readme.md"
|
|
14
|
+
license = "lglpv3"
|
|
15
|
+
repository = "https://github.com/gmrandazzo/PAutoDock"
|
|
16
|
+
packages = [{include = "pautodock", from = "src"}]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 3 - Alpha",
|
|
19
|
+
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
|
|
20
|
+
"Operating System :: POSIX :: Linux",
|
|
21
|
+
"Operating System :: MacOS :: MacOS X",
|
|
22
|
+
"Topic :: Scientific/Engineering :: Bio-Informatics"
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[tool.poetry.dependencies]
|
|
26
|
+
python = "^3.8"
|
|
27
|
+
requests = "^2.32.3"
|
|
28
|
+
|
|
29
|
+
[tool.poetry.dev-dependencies]
|
|
30
|
+
pytest = "^7.4.0"
|
|
31
|
+
pytest-cov = "^4.1.0"
|
|
32
|
+
pre-commit = "^3.3.3"
|
|
33
|
+
tox = "^4.2.3"
|
|
34
|
+
|
|
35
|
+
[tool.poetry.scripts]
|
|
36
|
+
pautodock = "pautodock.__main__:main"
|
|
37
|
+
pautodock-recover-output = "pautodock.__recover_output__:main"
|
|
38
|
+
|
|
39
|
+
[build-system]
|
|
40
|
+
requires = ["poetry-core"]
|
|
41
|
+
build-backend = "poetry.core.masonry.api"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.0.0"
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""main.py
|
|
4
|
+
|
|
5
|
+
This file is part of PAutoDock.
|
|
6
|
+
Copyright (C) 2020 Giuseppe Marco Randazzo <gmrandazzo@gmail.com>
|
|
7
|
+
PAutoDock is distributed under GPLv3 license.
|
|
8
|
+
To know more in detail how the license work,
|
|
9
|
+
please read the file "LICENSE" or
|
|
10
|
+
go to "http://www.gnu.org/licenses/gpl-3.0.en.html"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
Provides the basic main function to run autodock screening
|
|
14
|
+
in parallel.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import argparse
|
|
18
|
+
import sys
|
|
19
|
+
|
|
20
|
+
from pautodock.adparallel import ADParallel
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def main():
|
|
24
|
+
"""
|
|
25
|
+
main.py: with that you run the program.
|
|
26
|
+
"""
|
|
27
|
+
p = argparse.ArgumentParser()
|
|
28
|
+
p.add_argument("--receptor", default=None, type=str, help="receptor")
|
|
29
|
+
p.add_argument("--ligand", default=None, type=str, help="ligand PDB")
|
|
30
|
+
p.add_argument("--cx", default=None, type=float, help="center x")
|
|
31
|
+
p.add_argument("--cy", default=None, type=float, help="center y")
|
|
32
|
+
p.add_argument("--cz", default=None, type=float, help="center z")
|
|
33
|
+
p.add_argument("--gx", default=30, type=int, help="grid x size")
|
|
34
|
+
p.add_argument("--gy", default=30, type=int, help="grid y size")
|
|
35
|
+
p.add_argument("--gz", default=30, type=int, help="grid z size")
|
|
36
|
+
p.add_argument("--db", default=None, type=str, help="multimol2 database")
|
|
37
|
+
p.add_argument("--wdir", default=None, type=str, help="work directory")
|
|
38
|
+
p.add_argument("--smode", default="fast", type=str, help="screening mode")
|
|
39
|
+
p.add_argument("--out", default=None, type=str, help="screening output")
|
|
40
|
+
p.add_argument("--atd", default="OFF", type=str, help="Autodock ON")
|
|
41
|
+
p.add_argument("--vina", default="ON", type=str, help="Vina ON")
|
|
42
|
+
args = p.parse_args(sys.argv[1:])
|
|
43
|
+
|
|
44
|
+
if args.receptor is None or args.ligand is None and args.cx is None:
|
|
45
|
+
print("\nUsage: %s --receptor [input pdb]" % sys.argv[0])
|
|
46
|
+
print(" --ligand [input pdb/mol2]")
|
|
47
|
+
print(" --cx [center x]")
|
|
48
|
+
print(" --cy [center y]")
|
|
49
|
+
print(" --cz [center z]")
|
|
50
|
+
print(" --db [multi mol2]")
|
|
51
|
+
print(" --wdir [work path]")
|
|
52
|
+
print(" --smode=[slow,medium,fast]")
|
|
53
|
+
print(" --gx=[grid x size]")
|
|
54
|
+
print(" --gy=[grid y size]")
|
|
55
|
+
print(" --gz=[grid z size]")
|
|
56
|
+
print(" --out [screening output]")
|
|
57
|
+
print(" --atd [ON;OFF]")
|
|
58
|
+
print(" --vina [ON;OFF]")
|
|
59
|
+
else:
|
|
60
|
+
# Load import pdb; pdb.set_trace()#
|
|
61
|
+
dock = ADParallel(args.receptor, args.ligand, args.db, args.wdir)
|
|
62
|
+
if args.ligand is None:
|
|
63
|
+
dock.cx = args.cx
|
|
64
|
+
dock.cy = args.cy
|
|
65
|
+
dock.cz = args.cz
|
|
66
|
+
|
|
67
|
+
if args.atd == "OFF":
|
|
68
|
+
dock.atd = False
|
|
69
|
+
|
|
70
|
+
if args.vina == "ON":
|
|
71
|
+
dock.vina = True
|
|
72
|
+
|
|
73
|
+
dock.speed = args.smode
|
|
74
|
+
dock.gsize_x = args.gx
|
|
75
|
+
dock.gsize_y = args.gy
|
|
76
|
+
dock.gsize_z = args.gz
|
|
77
|
+
dock.virtual_screening(args.out)
|
|
78
|
+
return 0
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
if __name__ == "__main__":
|
|
82
|
+
main()
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""recover_output.py
|
|
4
|
+
|
|
5
|
+
This file is part of PAutoDock.
|
|
6
|
+
Copyright (C) 2020 Giuseppe Marco Randazzo <gmrandazzo@gmail.com>
|
|
7
|
+
PAutoDock is distributed under GPLv3 license.
|
|
8
|
+
To know more in detail how the license work,
|
|
9
|
+
please read the file "LICENSE" or
|
|
10
|
+
go to "http://www.gnu.org/licenses/gpl-3.0.en.html"
|
|
11
|
+
|
|
12
|
+
Provides a commandline script to recover the output result of a virtualscreening.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import argparse
|
|
16
|
+
import os
|
|
17
|
+
import sys
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
from pautodock.adparallel import ADParallel
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def main():
|
|
24
|
+
"""
|
|
25
|
+
main.py
|
|
26
|
+
"""
|
|
27
|
+
p = argparse.ArgumentParser()
|
|
28
|
+
p.add_argument("--wdir", default=None, type=str, help="work directory")
|
|
29
|
+
p.add_argument("--out", default=None, type=str, help="screening output")
|
|
30
|
+
p.add_argument("--ligand", default=None, type=str, help="ligand")
|
|
31
|
+
args = p.parse_args(sys.argv[1:])
|
|
32
|
+
|
|
33
|
+
if args.wdir is None or args.out is None:
|
|
34
|
+
print("\nUsage: %s --receptor [input pdb]" % sys.argv[0])
|
|
35
|
+
print(" --wdir [work path]")
|
|
36
|
+
print(" --ligand [ligand PDB]")
|
|
37
|
+
print(" --out [screening output]")
|
|
38
|
+
else:
|
|
39
|
+
dock = ADParallel("", None, None, args.ligand, None, args.wdir)
|
|
40
|
+
vinalogout = []
|
|
41
|
+
dpfout = []
|
|
42
|
+
mnames = []
|
|
43
|
+
for root, directories, filenames in os.walk(str(Path(args.wdir).absolute())):
|
|
44
|
+
for filename in filenames:
|
|
45
|
+
if "vina_log.txt" in filename:
|
|
46
|
+
vinalogout.append(os.path.join(root, filename))
|
|
47
|
+
mname = str(Path(vinalogout[-1]).parents[0].name)
|
|
48
|
+
if mname not in mnames:
|
|
49
|
+
mnames.append(mname)
|
|
50
|
+
elif "ind.dlg" in filename:
|
|
51
|
+
dpfout.append(os.path.join(root, filename))
|
|
52
|
+
mname = str(Path(dpfout[-1]).parents[0].name)
|
|
53
|
+
if mname not in mnames:
|
|
54
|
+
mnames.append(mname)
|
|
55
|
+
else:
|
|
56
|
+
continue
|
|
57
|
+
dock.gen_vs_output(vinalogout, dpfout, mnames, args.out)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
if __name__ == "__main__":
|
|
61
|
+
main()
|
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""adparallel.py
|
|
4
|
+
|
|
5
|
+
This file is part of PAutoDock.
|
|
6
|
+
Copyright (C) 2020 Giuseppe Marco Randazzo <gmrandazzo@gmail.com>
|
|
7
|
+
PAutoDock is distributed under GPLv3 license.
|
|
8
|
+
To know more in detail how the license work,
|
|
9
|
+
please read the file "LICENSE" or
|
|
10
|
+
go to "http://www.gnu.org/licenses/gpl-3.0.en.html"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
Provides the basic code to run autodock in parallel on a machine.
|
|
14
|
+
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import logging
|
|
18
|
+
import math
|
|
19
|
+
import multiprocessing
|
|
20
|
+
import os
|
|
21
|
+
import shutil
|
|
22
|
+
import tempfile
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
|
|
25
|
+
from pautodock import molop, multimol2op
|
|
26
|
+
from pautodock.fileutils import get_bin_path
|
|
27
|
+
from pautodock.mgltoolsinstall import install_mgltools
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class ADParallel(object):
|
|
31
|
+
def __init__(self, receptor, ligand, db, wpath):
|
|
32
|
+
try:
|
|
33
|
+
self.atdpath = get_bin_path("autodock")
|
|
34
|
+
except ValueError:
|
|
35
|
+
self.atdpath = None
|
|
36
|
+
try:
|
|
37
|
+
self.vinapath = get_bin_path("vina")
|
|
38
|
+
except ValueError:
|
|
39
|
+
self.vinapath = None
|
|
40
|
+
|
|
41
|
+
if not self.atdpath and not self.vinapath:
|
|
42
|
+
msg = "Error!! autodock and vina are not installed!\n"
|
|
43
|
+
msg += "Unable to run any calculation."
|
|
44
|
+
raise ValueError(msg)
|
|
45
|
+
|
|
46
|
+
self.mglpath = Path(f"{Path.home()}/.pautodock/MGLTools")
|
|
47
|
+
if not self.mglpath.exists():
|
|
48
|
+
install_mgltools(f"{Path.home()}/.pautodock")
|
|
49
|
+
self.receptor = receptor
|
|
50
|
+
self.ligand = ligand
|
|
51
|
+
self.db = db
|
|
52
|
+
self.wpath = wpath
|
|
53
|
+
self.results = []
|
|
54
|
+
self.cx = 0.0
|
|
55
|
+
self.cy = 0.0
|
|
56
|
+
self.cz = 0.0
|
|
57
|
+
self.gsize_x = 30
|
|
58
|
+
self.gsize_y = 30
|
|
59
|
+
self.gsize_z = 30
|
|
60
|
+
self.speed = "slow"
|
|
61
|
+
self.atd = True
|
|
62
|
+
self.vina = True
|
|
63
|
+
|
|
64
|
+
def read_atom_types(self, rec_mol):
|
|
65
|
+
"""
|
|
66
|
+
Read atom types in pdb and return in a list
|
|
67
|
+
"""
|
|
68
|
+
atlst = []
|
|
69
|
+
f = open(rec_mol, "r")
|
|
70
|
+
for line in f:
|
|
71
|
+
if "ATOM" in line:
|
|
72
|
+
at = line.strip().split(" ")[-1]
|
|
73
|
+
if at in atlst:
|
|
74
|
+
continue
|
|
75
|
+
else:
|
|
76
|
+
if len(at) > 0:
|
|
77
|
+
atlst.append(at)
|
|
78
|
+
else:
|
|
79
|
+
continue
|
|
80
|
+
f.close()
|
|
81
|
+
atlst = list(set(atlst))
|
|
82
|
+
atypes_str = "%s" % atlst[0]
|
|
83
|
+
for i in range(1, len(atlst)):
|
|
84
|
+
atypes_str += " %s" % atlst[i]
|
|
85
|
+
return atypes_str, atlst
|
|
86
|
+
|
|
87
|
+
def write_autodock_param_files(self, path, rec_pdbqt, mol_pdbqt, cc):
|
|
88
|
+
path_ = Path(path).absolute()
|
|
89
|
+
rat_str, _ = self.read_atom_types(rec_pdbqt)
|
|
90
|
+
lat_str, lat_lst = self.read_atom_types(path + "/" + mol_pdbqt)
|
|
91
|
+
# write the GPF
|
|
92
|
+
f = open(path + "/grid.gpf", "w")
|
|
93
|
+
f.write(
|
|
94
|
+
"npts %d %d %d # num.grid points in xyz\n"
|
|
95
|
+
% (self.gsize_x, self.gsize_y, self.gsize_z)
|
|
96
|
+
)
|
|
97
|
+
f.write("gridfld %s/receptor_model.maps.fld # grid_data_file\n" % (path_))
|
|
98
|
+
f.write("spacing 0.33 # spacing(A)\n")
|
|
99
|
+
f.write("receptor_types %s # receptor atom types\n" % (rat_str))
|
|
100
|
+
f.write("ligand_types %s # ligand atom types\n" % (lat_str))
|
|
101
|
+
f.write("receptor %s # macromolecule\n" % (rec_pdbqt))
|
|
102
|
+
f.write(
|
|
103
|
+
"gridcenter %.3f %.3f %.3f # xyz-coordinates or auto\n"
|
|
104
|
+
% (cc[0], cc[1], cc[2])
|
|
105
|
+
)
|
|
106
|
+
f.write("smooth 0.5 # store minimum energy w/in rad(A)\n")
|
|
107
|
+
for at in lat_lst:
|
|
108
|
+
f.write(
|
|
109
|
+
"map %s/receptor_model.%s.map # atom-specific aff. map\n" % (path_, at)
|
|
110
|
+
)
|
|
111
|
+
f.write("elecmap %s/receptor_model.e.map # El. Pot potential map\n" % (path_))
|
|
112
|
+
f.write("dsolvmap %s/receptor_model.d.map # desolv. potential map\n" % (path_))
|
|
113
|
+
f.write("dielectric -0.1465 # <0, AD4 dist-dep.diel;>0, constant\n")
|
|
114
|
+
f.close()
|
|
115
|
+
|
|
116
|
+
# Write autodock file
|
|
117
|
+
f = open(path + "/ind.dpf", "w")
|
|
118
|
+
f.write("autodock_parameter_version 4.2")
|
|
119
|
+
f.write("# used by autodock to validate parameter set\n")
|
|
120
|
+
f.write("outlev 1 # diagnostic output level\n")
|
|
121
|
+
f.write("intelec # calculate internal electrostatics\n")
|
|
122
|
+
f.write("seed time pid # seeds for random generator\n")
|
|
123
|
+
f.write("ligand_types %s # atoms types in ligand\n" % (lat_str))
|
|
124
|
+
f.write("fld %s/receptor_model.maps.fld # grid_data_file\n" % (path_))
|
|
125
|
+
for at in lat_lst:
|
|
126
|
+
f.write(
|
|
127
|
+
"map %s/receptor_model.%s.map # atom-specific aff. map\n" % (path_, at)
|
|
128
|
+
)
|
|
129
|
+
f.write("elecmap %s/receptor_model.e.map # electrostatics map\n" % (path_))
|
|
130
|
+
f.write("desolvmap %s/receptor_model.d.map # desolvation map\n" % (path_))
|
|
131
|
+
f.write("move %s/%s # small molecule\n" % (path_, mol_pdbqt))
|
|
132
|
+
f.write(
|
|
133
|
+
"about %.4f %.4f %.4f # small molecule center\n"
|
|
134
|
+
% (cc[0], cc[1], cc[2])
|
|
135
|
+
)
|
|
136
|
+
f.write("tran0 %.4f %.4f %.4f " % (cc[0], cc[1], cc[2]))
|
|
137
|
+
f.write("# initial coordinates/A or random\n")
|
|
138
|
+
f.write("quaternion0 random ")
|
|
139
|
+
f.write("# initial orientation\n")
|
|
140
|
+
f.write("dihe0 random ")
|
|
141
|
+
f.write("# initial dihedrals (relative) or random\n")
|
|
142
|
+
f.write("torsdof 5 ")
|
|
143
|
+
f.write("# torsional degrees of freedom\n")
|
|
144
|
+
f.write("rmstol 2.0 # cluster_tolerance/A\n")
|
|
145
|
+
f.write("extnrg 1000.0 # external grid energy\n")
|
|
146
|
+
f.write("e0max 0.0 10000 ")
|
|
147
|
+
f.write("# max initial energy; max number of retries\n")
|
|
148
|
+
f.write("ga_pop_size 150 ")
|
|
149
|
+
f.write("# number of individuals in population\n")
|
|
150
|
+
if self.speed == "slow":
|
|
151
|
+
f.write("ga_num_evals 25000000 ")
|
|
152
|
+
elif self.speed == "medium":
|
|
153
|
+
f.write("ga_num_evals 2500000 ")
|
|
154
|
+
else:
|
|
155
|
+
f.write("ga_num_evals 250000 ")
|
|
156
|
+
f.write(" # maximum number of energy evaluations\n")
|
|
157
|
+
f.write("ga_num_generations 27000 ")
|
|
158
|
+
f.write("# maximum number of generations\n")
|
|
159
|
+
f.write("ga_elitism 1 ")
|
|
160
|
+
f.write("# number of top individuals to survive to next generation\n")
|
|
161
|
+
f.write("ga_mutation_rate 0.02 # rate of gene mutation\n")
|
|
162
|
+
f.write("ga_crossover_rate 0.8 # rate of crossover\n")
|
|
163
|
+
f.write("ga_window_size 10 # \n")
|
|
164
|
+
f.write("ga_cauchy_alpha 0.0 ")
|
|
165
|
+
f.write("# Alpha parameter of Cauchy distribution\n")
|
|
166
|
+
f.write("ga_cauchy_beta 1.0 ")
|
|
167
|
+
f.write("# Beta parameter Cauchy distribution\n")
|
|
168
|
+
f.write("set_ga")
|
|
169
|
+
f.write(" # set the above parameters for GA or LGA\n")
|
|
170
|
+
f.write("sw_max_its 300")
|
|
171
|
+
f.write("# iterations of Solis & Wets local search\n")
|
|
172
|
+
f.write("sw_max_succ 4 ")
|
|
173
|
+
f.write(" # consecutive successes before changing rho\n")
|
|
174
|
+
f.write("sw_max_fail 4 ")
|
|
175
|
+
f.write(" # consecutive failures before changing rho\n")
|
|
176
|
+
f.write("sw_rho 1.0 ")
|
|
177
|
+
f.write("# size of local search space to sample\n")
|
|
178
|
+
f.write("sw_lb_rho 0.01 # lower bound on rho\n")
|
|
179
|
+
f.write("ls_search_freq 0.06 ")
|
|
180
|
+
f.write("# probability of performing local search on individual\n")
|
|
181
|
+
f.write("set_psw1 ")
|
|
182
|
+
f.write("# set the above pseudo-Solis & Wets parameters\n")
|
|
183
|
+
f.write("unbound_model bound ")
|
|
184
|
+
f.write("# state of unbound ligand\n")
|
|
185
|
+
f.write("ga_run 10 ")
|
|
186
|
+
f.write("# do this many hybrid GA-LS runs\n")
|
|
187
|
+
f.write("analysis ")
|
|
188
|
+
f.write("# perform a ranked cluster analysis\n")
|
|
189
|
+
f.close()
|
|
190
|
+
grid_path = Path(path + "/grid.gpf").absolute()
|
|
191
|
+
ind_path = Path(path + "/ind.dpf").absolute()
|
|
192
|
+
return grid_path, ind_path
|
|
193
|
+
|
|
194
|
+
def write_vina_param_files(self, path, cc, ss):
|
|
195
|
+
f = open(path + "/vina_conf.txt", "w")
|
|
196
|
+
f.write("center_x = %.4f\n" % (cc[0]))
|
|
197
|
+
f.write("center_y = %.4f\n" % (cc[1]))
|
|
198
|
+
f.write("center_z = %.4f\n" % (cc[2]))
|
|
199
|
+
f.write("size_x = %d\n" % (ss[0]))
|
|
200
|
+
f.write("size_y = %d\n" % (ss[1]))
|
|
201
|
+
f.write("size_z = %d\n" % (ss[2]))
|
|
202
|
+
f.write("num_modes = 9\n")
|
|
203
|
+
f.close()
|
|
204
|
+
return Path(path + "/vina_conf.txt").absolute()
|
|
205
|
+
|
|
206
|
+
def RunAutoGrid(self, cmd):
|
|
207
|
+
atg_path = str(Path("%s/autogrid4" % (self.atdpath)).absolute())
|
|
208
|
+
return os.system("%s %s" % (atg_path, cmd))
|
|
209
|
+
|
|
210
|
+
def RunAutoDock(self, cmd):
|
|
211
|
+
atd_path = str(Path("%s/autodock4" % (self.atdpath)).absolute())
|
|
212
|
+
return os.system("%s %s" % (atd_path, cmd))
|
|
213
|
+
|
|
214
|
+
def RunVina(self, cmd):
|
|
215
|
+
vina_path = str(Path("%s/vina" % (self.vinapath)).absolute())
|
|
216
|
+
return os.system("%s %s" % (vina_path, cmd))
|
|
217
|
+
|
|
218
|
+
def ReadOutput(self, ofile):
|
|
219
|
+
r = []
|
|
220
|
+
header = []
|
|
221
|
+
benergy = []
|
|
222
|
+
c_rmsd = []
|
|
223
|
+
r_rmsd = []
|
|
224
|
+
f = open(str(Path(ofile).absolute()), "r")
|
|
225
|
+
for line in f:
|
|
226
|
+
if "Partition function, Q =" in line:
|
|
227
|
+
header.append("Part. Func.")
|
|
228
|
+
r.append(molop.nsplit(line.strip(), " ")[4])
|
|
229
|
+
elif "Free energy, A ~" in line:
|
|
230
|
+
r.append(molop.nsplit(line.strip(), " ")[4])
|
|
231
|
+
header.append("Free Energy")
|
|
232
|
+
elif "Internal energy, U =" in line:
|
|
233
|
+
header.append("Internal Energy")
|
|
234
|
+
r.append(molop.nsplit(line.strip(), " ")[4])
|
|
235
|
+
elif "Entropy, S =" in line:
|
|
236
|
+
header.append("Entropy")
|
|
237
|
+
r.append(molop.nsplit(line.strip(), " ")[3])
|
|
238
|
+
elif "RANKING" in line:
|
|
239
|
+
v = molop.nsplit(line.strip(), " ")
|
|
240
|
+
benergy.append(float(v[3]))
|
|
241
|
+
c_rmsd.append(float(v[4]))
|
|
242
|
+
r_rmsd.append(float(v[5]))
|
|
243
|
+
f.close()
|
|
244
|
+
header.append("Binding Energy Average")
|
|
245
|
+
r.append(round(sum(benergy) / float(len(benergy)), 3))
|
|
246
|
+
header.append("Cluster RMSD Average")
|
|
247
|
+
r.append(round(sum(c_rmsd) / float(len(c_rmsd)), 3))
|
|
248
|
+
header.append("Ref. RMSD Average")
|
|
249
|
+
r.append(round(sum(r_rmsd) / float(len(r_rmsd)), 3))
|
|
250
|
+
return header, r
|
|
251
|
+
|
|
252
|
+
def LigandPosesBaricentreDistance(self, dock_pdbqt: str) -> float:
|
|
253
|
+
"""
|
|
254
|
+
Calculate the distance between the ligand and docking pose baricentres.
|
|
255
|
+
"""
|
|
256
|
+
poses_cc = molop.get_mol_baricentre(dock_pdbqt)
|
|
257
|
+
if int(self.cx) == 0:
|
|
258
|
+
self.cx, self.cy, self.cz = molop.get_mol_baricentre(self.ligand)
|
|
259
|
+
return math.sqrt(
|
|
260
|
+
(self.cx - poses_cc[0]) ** 2
|
|
261
|
+
+ (self.cy - poses_cc[1]) ** 2
|
|
262
|
+
+ (self.cz - poses_cc[2]) ** 2
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
def read_vina_output(self, ofile):
|
|
266
|
+
benergy = []
|
|
267
|
+
f = open(str(Path(ofile).absolute()), "r")
|
|
268
|
+
getres = False
|
|
269
|
+
for line in f:
|
|
270
|
+
if getres:
|
|
271
|
+
# Filter double outputs
|
|
272
|
+
if "Writing output ... done." in line or "AutoDock Vina" in line:
|
|
273
|
+
getres = False
|
|
274
|
+
else:
|
|
275
|
+
try:
|
|
276
|
+
v = molop.nsplit(line.strip(), " ")
|
|
277
|
+
benergy.append(float(v[1]))
|
|
278
|
+
except ValueError as err:
|
|
279
|
+
logging.error("Error with file %s - %s" % (ofile, err))
|
|
280
|
+
else:
|
|
281
|
+
if "-----+------------+----------+----------" in line:
|
|
282
|
+
getres = True
|
|
283
|
+
else:
|
|
284
|
+
continue
|
|
285
|
+
|
|
286
|
+
f.close()
|
|
287
|
+
if len(benergy) > 0:
|
|
288
|
+
return (
|
|
289
|
+
round(sum(benergy) / float(len(benergy)), 3),
|
|
290
|
+
min(benergy),
|
|
291
|
+
max(benergy),
|
|
292
|
+
)
|
|
293
|
+
else:
|
|
294
|
+
return 9999.0, 9999.0, 9999.0
|
|
295
|
+
|
|
296
|
+
def gen_vs_output(self, vinalogout, dpfout, mnames, otab):
|
|
297
|
+
"""
|
|
298
|
+
Collect vina results
|
|
299
|
+
"""
|
|
300
|
+
# Collect the vina results
|
|
301
|
+
vbind = []
|
|
302
|
+
for i, vout in enumerate(vinalogout):
|
|
303
|
+
avg_b, min_b, max_b = self.read_vina_output(vout)
|
|
304
|
+
try:
|
|
305
|
+
dock_poses = (
|
|
306
|
+
f"{Path(vout).parent.absolute()}/dock_confs_{mnames[i]}.pdbqt"
|
|
307
|
+
)
|
|
308
|
+
lp_dst = self.LigandPosesBaricentreDistance(dock_poses)
|
|
309
|
+
except FileNotFoundError as err:
|
|
310
|
+
logging.error("%s not found", err)
|
|
311
|
+
lp_dst = 9999.0
|
|
312
|
+
vbind.append([avg_b, min_b, max_b, lp_dst])
|
|
313
|
+
# Collect results
|
|
314
|
+
fo = open(otab, "w")
|
|
315
|
+
firstline = True
|
|
316
|
+
for i in range(len(mnames)):
|
|
317
|
+
h = []
|
|
318
|
+
r = []
|
|
319
|
+
if len(dpfout) > 0:
|
|
320
|
+
if Path(dpfout[i]).is_file():
|
|
321
|
+
h, r = self.ReadOutput(dpfout[i])
|
|
322
|
+
if firstline:
|
|
323
|
+
firstline = False
|
|
324
|
+
fo.write("Molname;")
|
|
325
|
+
for j in range(len(h)):
|
|
326
|
+
fo.write("%s;" % (h[j]))
|
|
327
|
+
fo.write("Avg. vina Binding Energy;")
|
|
328
|
+
fo.write("Min vina Binding Energy;Max vina Binding Energy;")
|
|
329
|
+
fo.write("Template-Ligand Baricenter Distance (docking pose check)\n")
|
|
330
|
+
fo.write("%s;" % (mnames[i]))
|
|
331
|
+
for j in range(len(r)):
|
|
332
|
+
fo.write("%s;" % (r[j]))
|
|
333
|
+
fo.write(
|
|
334
|
+
"%f;%f;%f;%f\n" % (vbind[i][0], vbind[i][1], vbind[i][2], vbind[i][3])
|
|
335
|
+
)
|
|
336
|
+
fo.close()
|
|
337
|
+
|
|
338
|
+
def make_vina_cmd(
|
|
339
|
+
self, vconf_path, rec_pdbqt, mol_pdbqt, mpath, molname, vinalogout
|
|
340
|
+
) -> str:
|
|
341
|
+
vc = f'--config "{vconf_path}"'
|
|
342
|
+
vc += f' --receptor "{rec_pdbqt}"'
|
|
343
|
+
vc += f' --ligand "{mol_pdbqt}"'
|
|
344
|
+
vc += f' --out "{mpath}/dock_confs_{molname}.pdbqt" >> {vinalogout}'
|
|
345
|
+
return vc
|
|
346
|
+
|
|
347
|
+
def virtual_screening(self, otab):
|
|
348
|
+
# Prepare the receptor
|
|
349
|
+
rec = molop.Receptor(self.receptor, self.mglpath)
|
|
350
|
+
rec_pdbqt = rec.topdbqt()
|
|
351
|
+
if self.ligand is not None:
|
|
352
|
+
self.cx, self.cy, self.cz = molop.get_mol_baricentre(self.ligand)
|
|
353
|
+
# Prepare the database split multi mol2
|
|
354
|
+
tmppath = tempfile.mkdtemp()
|
|
355
|
+
mol2lst = multimol2op.split_mol2(self.db, tmppath)
|
|
356
|
+
agcmdlst = []
|
|
357
|
+
adcmdlst = []
|
|
358
|
+
vinacmdlst = []
|
|
359
|
+
vinalogout = []
|
|
360
|
+
dpfout = []
|
|
361
|
+
mnames = []
|
|
362
|
+
# Create a directory with the name of the mol2 molecule
|
|
363
|
+
# and copy the receptor and itself
|
|
364
|
+
for mol2 in mol2lst:
|
|
365
|
+
molname_ext = str(Path(mol2).resolve().name)
|
|
366
|
+
molname = molname_ext.replace(".mol2", "")
|
|
367
|
+
mnames.append(molname)
|
|
368
|
+
mpath = str(Path(self.wpath + "/" + molname).absolute())
|
|
369
|
+
if not Path(f"{mpath}/dock_confs_{molname}.pdbqt").exists():
|
|
370
|
+
if not Path(mpath).exists():
|
|
371
|
+
os.makedirs(mpath)
|
|
372
|
+
if not Path(mpath + "/" + molname_ext).exists():
|
|
373
|
+
shutil.move(str(Path(mol2).resolve()), mpath)
|
|
374
|
+
|
|
375
|
+
mol = molop.Molecule(
|
|
376
|
+
str(Path(mpath + "/" + molname_ext).absolute()), self.mglpath
|
|
377
|
+
)
|
|
378
|
+
mol_pdbqt = mol.topdbqt([self.cx, self.cy, self.cz])
|
|
379
|
+
mol_pdbqt_name = str(Path(mol_pdbqt).resolve().name)
|
|
380
|
+
if self.atd:
|
|
381
|
+
gpf_path, dpf_path = self.write_autodock_param_files(
|
|
382
|
+
mpath, rec_pdbqt, mol_pdbqt_name, [self.cx, self.cy, self.cz]
|
|
383
|
+
)
|
|
384
|
+
first_arg = str(gpf_path)
|
|
385
|
+
second_arg = str(gpf_path).replace(".gpf", "")
|
|
386
|
+
ag = f'-p "{first_arg}" -l "{second_arg}.glg"'
|
|
387
|
+
agcmdlst.append(ag)
|
|
388
|
+
dpfout.append(str(dpf_path).replace(".dpf", ".dlg"))
|
|
389
|
+
ad = f'-p "{str(dpf_path)}" -l "{dpfout[-1]}"'
|
|
390
|
+
adcmdlst.append(ad)
|
|
391
|
+
|
|
392
|
+
if self.vina:
|
|
393
|
+
vinalogout.append(f"{mpath}/vina_log.txt")
|
|
394
|
+
# If the log and the docking pose extists then
|
|
395
|
+
# there is no need to run the calculation
|
|
396
|
+
vconf_path = self.write_vina_param_files(
|
|
397
|
+
mpath,
|
|
398
|
+
[self.cx, self.cy, self.cz],
|
|
399
|
+
[self.gsize_x, self.gsize_y, self.gsize_z],
|
|
400
|
+
)
|
|
401
|
+
vinacmdlst.append(
|
|
402
|
+
self.make_vina_cmd(
|
|
403
|
+
vconf_path,
|
|
404
|
+
rec_pdbqt,
|
|
405
|
+
mol_pdbqt,
|
|
406
|
+
mpath,
|
|
407
|
+
molname,
|
|
408
|
+
vinalogout[-1],
|
|
409
|
+
)
|
|
410
|
+
)
|
|
411
|
+
else:
|
|
412
|
+
vinalogout.append(f"{mpath}/vina_log.txt")
|
|
413
|
+
shutil.rmtree(tmppath)
|
|
414
|
+
ncpu = multiprocessing.cpu_count()
|
|
415
|
+
if self.atd:
|
|
416
|
+
# Run AutoGrid
|
|
417
|
+
pool = multiprocessing.Pool(ncpu)
|
|
418
|
+
pool.map(self.RunAutoGrid, agcmdlst)
|
|
419
|
+
# RunAutodock
|
|
420
|
+
pool = multiprocessing.Pool(ncpu)
|
|
421
|
+
pool.map(self.RunAutoDock, adcmdlst)
|
|
422
|
+
|
|
423
|
+
if self.vina:
|
|
424
|
+
# RunVina
|
|
425
|
+
pool = multiprocessing.Pool(ncpu)
|
|
426
|
+
pool.map(self.RunVina, vinacmdlst)
|
|
427
|
+
|
|
428
|
+
# Write the output table
|
|
429
|
+
self.gen_vs_output(vinalogout, dpfout, mnames, otab)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""fileutils.py
|
|
4
|
+
|
|
5
|
+
This file is part of PAutoDock.
|
|
6
|
+
Copyright (C) 2020 Giuseppe Marco Randazzo <gmrandazzo@gmail.com>
|
|
7
|
+
PAutoDock is distributed under GPLv3 license.
|
|
8
|
+
To know more in detail how the license work,
|
|
9
|
+
please read the file "LICENSE" or
|
|
10
|
+
go to "http://www.gnu.org/licenses/gpl-3.0.en.html"
|
|
11
|
+
|
|
12
|
+
Provides the basic operation for molecular files.
|
|
13
|
+
|
|
14
|
+
"""
|
|
15
|
+
import logging
|
|
16
|
+
import platform
|
|
17
|
+
import tarfile
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
import requests
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def get_bin_path(bin_name: str):
|
|
24
|
+
"""
|
|
25
|
+
Get the path to the bin_name executable based on the operating system.
|
|
26
|
+
"""
|
|
27
|
+
paths = {"Linux": ["/usr/bin/", "/usr/local/bin"], "Darwin": ["/opt/homebrew/bin/"]}
|
|
28
|
+
system = platform.system()
|
|
29
|
+
if system not in paths:
|
|
30
|
+
raise ValueError("Platform not supported")
|
|
31
|
+
|
|
32
|
+
for bin_path in paths.get(system):
|
|
33
|
+
if bin_path and Path(f"{bin_path}/{bin_name}").exists():
|
|
34
|
+
return bin_path
|
|
35
|
+
raise ValueError(f"Unable to find {bin_name} installed.")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def download_file(url, destination):
|
|
39
|
+
"""
|
|
40
|
+
Download a file from a URL to a local destination.
|
|
41
|
+
"""
|
|
42
|
+
try:
|
|
43
|
+
response = requests.get(url, stream=True)
|
|
44
|
+
response.raise_for_status()
|
|
45
|
+
with open(destination, "wb") as file:
|
|
46
|
+
for chunk in response.iter_content(chunk_size=8192):
|
|
47
|
+
file.write(chunk)
|
|
48
|
+
logging.info(f"Downloaded: {destination}")
|
|
49
|
+
except requests.RequestException as err:
|
|
50
|
+
logging.error(f"Failed to download file: {err}")
|
|
51
|
+
return False
|
|
52
|
+
return True
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def extract_tar_gz(file_path, extract_to):
|
|
56
|
+
"""
|
|
57
|
+
Extract a .tar.gz file to a specified directory.
|
|
58
|
+
"""
|
|
59
|
+
try:
|
|
60
|
+
with tarfile.open(file_path, "r:gz") as tar:
|
|
61
|
+
tar.extractall(path=extract_to)
|
|
62
|
+
logging.info(f"Extracted: {file_path} to {extract_to}")
|
|
63
|
+
except (tarfile.TarError, IOError) as err:
|
|
64
|
+
logging.error(f"Failed to extract file: {err}")
|
|
65
|
+
return False
|
|
66
|
+
return True
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""mgltoolsinstall.py
|
|
4
|
+
|
|
5
|
+
This file is part of PAutoDock.
|
|
6
|
+
Copyright (C) 2020 Giuseppe Marco Randazzo <gmrandazzo@gmail.com>
|
|
7
|
+
PAutoDock is distributed under GPLv3 license.
|
|
8
|
+
To know more in detail how the license work,
|
|
9
|
+
please read the file "LICENSE" or
|
|
10
|
+
go to "http://www.gnu.org/licenses/gpl-3.0.en.html"
|
|
11
|
+
|
|
12
|
+
Provides the basic operation for molecular files.
|
|
13
|
+
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
import platform
|
|
18
|
+
import subprocess
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
from pautodock.fileutils import download_file, extract_tar_gz
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def install_mgltools(dir: str):
|
|
25
|
+
"""
|
|
26
|
+
Install MGLTools from the official website.
|
|
27
|
+
"""
|
|
28
|
+
directory = Path(dir)
|
|
29
|
+
directory.mkdir(exist_ok=True)
|
|
30
|
+
destination = directory / "mgltools_1.5.7.tar.gz"
|
|
31
|
+
dir_name = None
|
|
32
|
+
|
|
33
|
+
system = platform.system()
|
|
34
|
+
if system == "Linux":
|
|
35
|
+
url = "https://ccsb.scripps.edu/download/532/"
|
|
36
|
+
dir_name = "mgltools_x86_64Linux2_1.5.7"
|
|
37
|
+
elif system == "Darwin":
|
|
38
|
+
url = "https://ccsb.scripps.edu/download/529/"
|
|
39
|
+
dir_name = "mgltools_1.5.7_MacOS-X"
|
|
40
|
+
else:
|
|
41
|
+
logging.error("Unsupported platform")
|
|
42
|
+
return False
|
|
43
|
+
|
|
44
|
+
if not destination.exists():
|
|
45
|
+
if not download_file(url, destination):
|
|
46
|
+
return False
|
|
47
|
+
|
|
48
|
+
if extract_tar_gz(destination, directory):
|
|
49
|
+
install_dir = directory / "MGLTools"
|
|
50
|
+
install_script = directory / dir_name / "install.sh"
|
|
51
|
+
cmd_args = ["sh", str(install_script), "-d", str(install_dir)]
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
subprocess.check_output(
|
|
55
|
+
cmd_args,
|
|
56
|
+
cwd=directory / dir_name,
|
|
57
|
+
shell=False,
|
|
58
|
+
text=True,
|
|
59
|
+
stderr=subprocess.DEVNULL,
|
|
60
|
+
)
|
|
61
|
+
logging.info("MGLTools installed successfully.")
|
|
62
|
+
return True
|
|
63
|
+
except subprocess.CalledProcessError as err:
|
|
64
|
+
logging.error(f"Installation failed: {err}")
|
|
65
|
+
return False
|
|
66
|
+
else:
|
|
67
|
+
return False
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""molop.py
|
|
4
|
+
|
|
5
|
+
This file is part of PAutoDock.
|
|
6
|
+
Copyright (C) 2020 Giuseppe Marco Randazzo <gmrandazzo@gmail.com>
|
|
7
|
+
PAutoDock is distributed under GPLv3 license.
|
|
8
|
+
To know more in detail how the license work,
|
|
9
|
+
please read the file "LICENSE" or
|
|
10
|
+
go to "http://www.gnu.org/licenses/gpl-3.0.en.html"
|
|
11
|
+
|
|
12
|
+
Provides the basic operation for molecular files.
|
|
13
|
+
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
import subprocess
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
from pautodock.fileutils import get_bin_path
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def nsplit(s, delim=None):
|
|
24
|
+
return [x for x in s.split(delim) if x]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def extract_coordinates(line, ftype):
|
|
28
|
+
if ftype == "pdb":
|
|
29
|
+
if "HETATM" in line:
|
|
30
|
+
x = float(line[29:39].strip())
|
|
31
|
+
y = float(line[39:47].strip())
|
|
32
|
+
z = float(line[47:55].strip())
|
|
33
|
+
return [float(x), float(y), float(z)]
|
|
34
|
+
elif ftype == "pdbqt":
|
|
35
|
+
if "ATOM" in line:
|
|
36
|
+
x = float(line[31:39].strip())
|
|
37
|
+
y = float(line[38:46].strip())
|
|
38
|
+
z = float(line[46:54].strip())
|
|
39
|
+
return [float(x), float(y), float(z)]
|
|
40
|
+
else:
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def get_mol_baricentre(mol: str) -> tuple:
|
|
45
|
+
"""
|
|
46
|
+
Get molecular baricentre from a molecule
|
|
47
|
+
"""
|
|
48
|
+
cc = [0.0, 0.0, 0.0]
|
|
49
|
+
n = 0
|
|
50
|
+
if mol.endswith(".pdbqt"):
|
|
51
|
+
ftype = "pdbqt"
|
|
52
|
+
elif mol.endswith(".pdb"):
|
|
53
|
+
ftype = "pdb"
|
|
54
|
+
else:
|
|
55
|
+
raise ValueError(
|
|
56
|
+
"Molecual format not supported {mol}. Supported formats: pdb or pdbqt"
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
with open(mol, "r", encoding="utf-8") as f:
|
|
60
|
+
for line in f:
|
|
61
|
+
if ("ATOM" in line or "HETATM" in line) and "REMARK" not in line:
|
|
62
|
+
try:
|
|
63
|
+
ex_cc = extract_coordinates(line.strip(), ftype)
|
|
64
|
+
if ex_cc:
|
|
65
|
+
for i, val in enumerate(ex_cc):
|
|
66
|
+
cc[i] += val
|
|
67
|
+
n += 1
|
|
68
|
+
except IndexError as err:
|
|
69
|
+
logging.error("%s get_mol_baricentre problem with %s", err, line)
|
|
70
|
+
return [cc[i] / float(n) for i in range(len(cc))]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class Receptor(object):
|
|
74
|
+
def __init__(self, receptor, mglpath):
|
|
75
|
+
self.receptor = receptor
|
|
76
|
+
self.mglpath = str(Path(mglpath).resolve())
|
|
77
|
+
|
|
78
|
+
def topdbqt(self):
|
|
79
|
+
python_env = (
|
|
80
|
+
"export LD_LIBRARY_PATH=\"%s/lib\"${LD_LIBRARY_PATH:+':'$LD_LIBRARY_PATH};"
|
|
81
|
+
% (self.mglpath)
|
|
82
|
+
)
|
|
83
|
+
python_env += "%s/bin/python2" % (self.mglpath)
|
|
84
|
+
prep_rec = self.mglpath
|
|
85
|
+
prep_rec += "/MGLToolsPckgs/AutoDockTools/Utilities24/"
|
|
86
|
+
prep_rec += "prepare_receptor4.py"
|
|
87
|
+
pdbqt = self.receptor.replace(".pdb", ".pdbqt")
|
|
88
|
+
cmd = "%s %s -r '%s' -o '%s'" % (python_env, prep_rec, self.receptor, pdbqt)
|
|
89
|
+
subprocess.call([cmd], shell=True)
|
|
90
|
+
return str(Path(pdbqt).resolve())
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class Molecule(object):
|
|
94
|
+
def __init__(self, molecule, mglpath):
|
|
95
|
+
self.molecule = molecule
|
|
96
|
+
self.mglpath = str(Path(mglpath).resolve())
|
|
97
|
+
self.obabel_path = get_bin_path("obabel")
|
|
98
|
+
|
|
99
|
+
def topdbqt(self, tran0=[]):
|
|
100
|
+
"""
|
|
101
|
+
tran0 is the vector of centre x,y,z where to translate the molecule
|
|
102
|
+
"""
|
|
103
|
+
obabel = f"{self.obabel_path}/obabel"
|
|
104
|
+
molname = self.molecule
|
|
105
|
+
if ".mol2" in molname.lower():
|
|
106
|
+
molname = molname.replace(".mol2", ".pdbqt")
|
|
107
|
+
else:
|
|
108
|
+
molname = molname.replace(".pdb", ".pdbqt")
|
|
109
|
+
cmd = "%s -p gastaiger -imol2 '%s' -opdbqt -O '%s'" % (
|
|
110
|
+
obabel,
|
|
111
|
+
self.molecule,
|
|
112
|
+
molname,
|
|
113
|
+
)
|
|
114
|
+
subprocess.call([cmd], shell=True)
|
|
115
|
+
# Translate to the new center
|
|
116
|
+
fpdbqt = str(Path(molname).resolve())
|
|
117
|
+
if len(tran0) > 0:
|
|
118
|
+
mem = []
|
|
119
|
+
fi = open(fpdbqt, "r")
|
|
120
|
+
for line in fi:
|
|
121
|
+
if "ATOM" in line:
|
|
122
|
+
ex_cc = extract_coordinates(line.strip(), "pdbqt")
|
|
123
|
+
if ex_cc:
|
|
124
|
+
copy_line = line
|
|
125
|
+
x = float(ex_cc[0]) + tran0[0]
|
|
126
|
+
copy_line.replace(str(ex_cc[0]), str(x))
|
|
127
|
+
y = float(ex_cc[1]) + tran0[0]
|
|
128
|
+
copy_line.replace(str(ex_cc[1]), str(y))
|
|
129
|
+
z = float(ex_cc[2]) + tran0[0]
|
|
130
|
+
copy_line.replace(str(ex_cc[2]), str(z))
|
|
131
|
+
mem.append(copy_line)
|
|
132
|
+
else:
|
|
133
|
+
msg = "Molecule.topdbqt Error!\n"
|
|
134
|
+
msg += " X Y Z coordinates not found in "
|
|
135
|
+
msg += f"line {line.strip()}"
|
|
136
|
+
raise ValueError(msg)
|
|
137
|
+
else:
|
|
138
|
+
mem.append(line)
|
|
139
|
+
fi.close()
|
|
140
|
+
|
|
141
|
+
fo = open(fpdbqt, "w")
|
|
142
|
+
for line in mem:
|
|
143
|
+
fo.write(line)
|
|
144
|
+
fo.close()
|
|
145
|
+
return fpdbqt
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""multimol2op.py
|
|
4
|
+
|
|
5
|
+
This file is part of PAutoDock.
|
|
6
|
+
Copyright (C) 2020 Giuseppe Marco Randazzo <gmrandazzo@gmail.com>
|
|
7
|
+
PAutoDock is distributed under GPLv3 license.
|
|
8
|
+
To know more in detail how the license work,
|
|
9
|
+
please read the file "LICENSE" or
|
|
10
|
+
go to "http://www.gnu.org/licenses/gpl-3.0.en.html"
|
|
11
|
+
|
|
12
|
+
Provides the basic operation for MOL2 files in parallel
|
|
13
|
+
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import os
|
|
17
|
+
import shutil
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def read_molname(filemol2: str):
|
|
22
|
+
f = open(filemol2, "r")
|
|
23
|
+
molname = None
|
|
24
|
+
next_is_name = False
|
|
25
|
+
for line in f:
|
|
26
|
+
if line.strip().lower() == "@<TRIPOS>MOLECULE".lower():
|
|
27
|
+
next_is_name = True
|
|
28
|
+
else:
|
|
29
|
+
if next_is_name is True:
|
|
30
|
+
molname = line.strip()
|
|
31
|
+
next_is_name = False
|
|
32
|
+
f.close()
|
|
33
|
+
return molname
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def get_mol2_name(filemol2: str):
|
|
37
|
+
molname = read_molname("tmp_")
|
|
38
|
+
filename = molname + ".mol2"
|
|
39
|
+
cc = 1
|
|
40
|
+
while True:
|
|
41
|
+
if os.path.isfile(filename) is False:
|
|
42
|
+
break
|
|
43
|
+
else:
|
|
44
|
+
filename = molname + "_" + str(cc) + ".mol2"
|
|
45
|
+
cc = cc + 1
|
|
46
|
+
return filename
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def split_mol2(mmol2, path="./"):
|
|
50
|
+
mol2splitted = []
|
|
51
|
+
fmol2 = open(mmol2, "r")
|
|
52
|
+
ftmp = open("tmp_", "w")
|
|
53
|
+
firstmol = True
|
|
54
|
+
for line in fmol2:
|
|
55
|
+
if line.strip().lower() == "@<TRIPOS>MOLECULE".lower():
|
|
56
|
+
if ftmp.closed is False and firstmol is False:
|
|
57
|
+
ftmp.close()
|
|
58
|
+
filename = get_mol2_name("tmp_")
|
|
59
|
+
mpath = str(Path(path + "/" + filename).absolute())
|
|
60
|
+
if Path(mpath).exists() is False:
|
|
61
|
+
shutil.move("tmp_", mpath)
|
|
62
|
+
mol2splitted.append(mpath)
|
|
63
|
+
else:
|
|
64
|
+
os.remove("tmp_")
|
|
65
|
+
ftmp = open("tmp_", "w")
|
|
66
|
+
firstmol = False
|
|
67
|
+
ftmp.write(line)
|
|
68
|
+
else:
|
|
69
|
+
ftmp.write(line)
|
|
70
|
+
|
|
71
|
+
if ftmp.closed is False:
|
|
72
|
+
ftmp.close()
|
|
73
|
+
filename = get_mol2_name("tmp_")
|
|
74
|
+
mpath = str(Path(path + "/" + filename).absolute())
|
|
75
|
+
if Path(mpath).exists() is False:
|
|
76
|
+
shutil.move("tmp_", mpath)
|
|
77
|
+
mol2splitted.append(mpath)
|
|
78
|
+
else:
|
|
79
|
+
os.remove("tmp_")
|
|
80
|
+
fmol2.close()
|
|
81
|
+
return mol2splitted
|