File size: 5,794 Bytes
6daa4cc
 
 
 
 
 
 
 
0303515
 
 
6daa4cc
 
28fb149
 
 
 
 
 
 
 
 
 
 
 
6daa4cc
 
 
 
 
 
 
 
28fb149
6daa4cc
 
 
 
28fb149
6daa4cc
 
 
0303515
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5c0a4b6
 
 
 
 
 
 
28fb149
 
 
 
 
 
5c0a4b6
28fb149
 
6daa4cc
28fb149
 
 
 
0303515
 
 
 
 
 
 
 
 
 
 
28fb149
 
0303515
 
 
6daa4cc
 
 
 
 
 
 
 
 
 
 
5c0a4b6
 
 
 
 
 
 
 
 
 
 
 
 
6daa4cc
 
 
5c0a4b6
 
 
b1dc6ad
5c0a4b6
b1dc6ad
 
 
5c0a4b6
b1dc6ad
 
 
 
 
5c0a4b6
b1dc6ad
 
 
 
 
5c0a4b6
6daa4cc
 
 
 
47e84bb
6daa4cc
28fb149
6daa4cc
 
 
b1dc6ad
6daa4cc
 
28fb149
6daa4cc
28fb149
 
 
 
6daa4cc
 
 
0303515
6daa4cc
28fb149
 
 
 
 
 
0303515
28fb149
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
import datetime
import os
import shutil
import subprocess
import tempfile
import uuid

import logging
from typing import List

import yaml


def set_env_variables():
    if "DiffDock-Pocket-Dir" not in os.environ:
        work_dir = os.path.abspath(os.path.join("../DiffDock-Pocket"))
        if os.path.exists(work_dir):
            os.environ["DiffDock-Pocket-Dir"] = work_dir
        else:
            raise ValueError(f"DiffDock-Pocket-Dir {work_dir} not found")

    if "LOG_LEVEL" not in os.environ:
        os.environ["LOG_LEVEL"] = "INFO"


def configure_logging(level=None):
    if level is None:
        level = getattr(logging, os.environ.get("LOG_LEVEL", "INFO"))

    # Note that this sets the universal logger,
    # which includes other libraries.
    logging.basicConfig(
        level=level,
        format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
        handlers=[
            logging.StreamHandler(),  # Outputs logs to stderr by default
            # If you also want to log to a file, uncomment the following line:
            # logging.FileHandler('my_app.log', mode='a', encoding='utf-8')
        ],
    )


def kwargs_to_cli_args(**kwargs) -> List[str]:
    """
    Converts keyword arguments to a CLI argument string.
    Boolean kwargs are added as flags if True, and omitted if False.
    """
    cli_args = []
    for key, value in kwargs.items():
        if isinstance(value, bool):
            if value:
                cli_args.append(f"--{key}")
        else:
            if value is not None:
                cli_args.append(f"--{key}={value}")

    return cli_args


def read_file_lines(fi_path: str):
    with open(fi_path, "r") as fp:
        lines = fp.readlines()
    mol = "".join(lines)
    return mol


def run_cli_command(
    protein_path: str,
    ligand: str,
    samples_per_complex: int,
    keep_local_structures: bool,
    save_visualisation: bool,
    other_arg_file: str = None,
    work_dir=None,
):
    if work_dir is None:
        work_dir = os.environ.get(
            "DiffDock-Pocket-Dir", os.path.join(os.environ["HOME"], "DiffDock-Pocket")
        )

    all_arg_dict = {}
    if other_arg_file:
        all_arg_dict = yaml.safe_load(open(other_arg_file, "r"))
        logging.debug(f"YAML dict: {all_arg_dict}")

    ui_args = ["protein_path", "ligand", "samples_per_complex",
               "keep_local_structures", "save_visualisation"]
    for ui_arg in ui_args:
        my_str = f"all_arg_dict['{ui_arg}'] = {ui_arg}"
        exec(my_str)

    command = [
        "python3",
        "inference.py"]

    command += kwargs_to_cli_args(**all_arg_dict)

    with tempfile.TemporaryDirectory() as temp_dir:
        temp_dir_path = temp_dir
        command.append(f"--out_dir={temp_dir_path}")

        # Convert command list to string for printing
        command_str = " ".join(command)
        logging.info(f"Executing command: {command_str}")

        # Running the command
        try:
            skip_running = False
            if not skip_running:
                result = subprocess.run(
                    command,
                    cwd=work_dir,
                    check=False,
                    text=True,
                    capture_output=True,
                    env=os.environ,
                )
                logging.debug(f"Command output:\n{result.stdout}")
                if result.stderr:
                    logging.error(f"Command error:\n{result.stderr}")
        except subprocess.CalledProcessError as e:
            logging.error(f"An error occurred while executing the command: {e}")

        # If there's a file for viewing, load it and view it.
        sub_dirs = [os.path.join(temp_dir_path, x) for x in os.listdir(temp_dir_path)]
        sub_dirs = list(filter(lambda x: os.path.isdir(x), sub_dirs))
        pdb_path = pdb_text = sdf_path = sdf_text = None
        if len(sub_dirs) == 1:
            sub_dir = sub_dirs[0]
            pdb_path = os.path.join(sub_dir, "rank1_reverseprocess_protein.pdb")
            sdf_path = os.path.join(sub_dir, "rank1.sdf")

        if skip_running:
            # Test/debugging only
            example_dir = os.path.join(os.environ["HOME"], "Projects", "DiffDock-Pocket", "example_data", "example_outputs")
            pdb_path = os.path.join(example_dir, "rank1_reverseprocess_protein.pdb")
            sdf_path = os.path.join(example_dir, "rank1.sdf")

        if pdb_path and os.path.exists(pdb_path):
            pdb_text = read_file_lines(pdb_path)
            sdf_text = read_file_lines(sdf_path)

        logging.debug(f"Display path: {pdb_path}")

        # Zip the output directory
        # Generate a unique filename using a timestamp and a UUID
        timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
        uuid_tag = str(uuid.uuid4())[0:8]
        unique_filename = f"diffdock_pocket_output_{timestamp}_{uuid_tag}"
        zip_base_name = os.path.join("tmp", unique_filename)
        full_zip_path = shutil.make_archive(zip_base_name, "zip", temp_dir)

        logging.debug(f"Directory '{temp_dir}' zipped to '{full_zip_path}'")

    return full_zip_path, pdb_text, sdf_text


if __name__ == "__main__":
    # Testing code
    set_env_variables()
    configure_logging()

    work_dir = os.path.abspath("../DiffDock-Pocket")
    os.environ["DiffDock-Pocket-Dir"] = work_dir
    protein_path = os.path.join(work_dir, "example_data", "3dpf_protein.pdb")
    ligand = os.path.join(work_dir, "example_data", "3dpf_ligand.sdf")
    other_arg_file = os.path.join(work_dir, "example_data", "example_args.yml")

    run_cli_command(
        protein_path,
        ligand,
        samples_per_complex=1,
        keep_local_structures=True,
        save_visualisation=True,
        other_arg_file=other_arg_file
    )