Spaces:
Runtime error
Runtime error
File size: 5,503 Bytes
753e275 |
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 |
import os
import shutil
import tempfile
import subprocess
import dataclasses as dc
from typing import List, Optional
from Bio import PDB
from Bio.PDB import Model as PDBModel
from diffab.tools.renumber import renumber as renumber_chothia
from .base import DockingEngine
def fix_docked_pdb(pdb_path):
fixed = []
with open(pdb_path, 'r') as f:
for ln in f.readlines():
if (ln.startswith('ATOM') or ln.startswith('HETATM')) and len(ln) == 56:
fixed.append( ln[:-1] + ' 1.00 0.00 \n' )
else:
fixed.append(ln)
with open(pdb_path, 'w') as f:
f.write(''.join(fixed))
class HDock(DockingEngine):
def __init__(
self,
hdock_bin='./bin/hdock',
createpl_bin='./bin/createpl',
):
super().__init__()
self.hdock_bin = os.path.realpath(hdock_bin)
self.createpl_bin = os.path.realpath(createpl_bin)
self.tmpdir = tempfile.TemporaryDirectory()
self._has_receptor = False
self._has_ligand = False
self._receptor_chains = []
self._ligand_chains = []
def __enter__(self):
return self
def __exit__(self, typ, value, traceback):
self.tmpdir.cleanup()
def set_receptor(self, pdb_path):
shutil.copyfile(pdb_path, os.path.join(self.tmpdir.name, 'receptor.pdb'))
self._has_receptor = True
def set_ligand(self, pdb_path):
shutil.copyfile(pdb_path, os.path.join(self.tmpdir.name, 'ligand.pdb'))
self._has_ligand = True
def _dump_complex_pdb(self):
parser = PDB.PDBParser(QUIET=True)
model_receptor = parser.get_structure(None, os.path.join(self.tmpdir.name, 'receptor.pdb'))[0]
docked_pdb_path = os.path.join(self.tmpdir.name, 'ligand_docked.pdb')
fix_docked_pdb(docked_pdb_path)
structure_ligdocked = parser.get_structure(None, docked_pdb_path)
pdb_io = PDB.PDBIO()
paths = []
for i, model_ligdocked in enumerate(structure_ligdocked):
model_complex = PDBModel.Model(0)
for chain in model_receptor:
model_complex.add(chain.copy())
for chain in model_ligdocked:
model_complex.add(chain.copy())
pdb_io.set_structure(model_complex)
save_path = os.path.join(self.tmpdir.name, f"complex_{i}.pdb")
pdb_io.save(save_path)
paths.append(save_path)
return paths
def dock(self):
if not (self._has_receptor and self._has_ligand):
raise ValueError('Missing receptor or ligand.')
subprocess.run(
[self.hdock_bin, "receptor.pdb", "ligand.pdb"],
cwd=self.tmpdir.name, check=True
)
subprocess.run(
[self.createpl_bin, "Hdock.out", "ligand_docked.pdb"],
cwd=self.tmpdir.name, check=True
)
return self._dump_complex_pdb()
@dc.dataclass
class DockSite:
chain: str
resseq: int
class HDockAntibody(HDock):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._heavy_chain_id = None
self._epitope_sites: Optional[List[DockSite]] = None
def set_ligand(self, pdb_path):
raise NotImplementedError('Please use set_antibody')
def set_receptor(self, pdb_path):
raise NotImplementedError('Please use set_antigen')
def set_antigen(self, pdb_path, epitope_sites: Optional[List[DockSite]]=None):
super().set_receptor(pdb_path)
self._epitope_sites = epitope_sites
def set_antibody(self, pdb_path):
heavy_chains, _ = renumber_chothia(pdb_path, os.path.join(self.tmpdir.name, 'ligand.pdb'))
self._has_ligand = True
self._heavy_chain_id = heavy_chains[0]
def _prepare_lsite(self):
lsite_content = f"95-102:{self._heavy_chain_id}\n" # Chothia CDR H3
with open(os.path.join(self.tmpdir.name, 'lsite.txt'), 'w') as f:
f.write(lsite_content)
print(f"[INFO] lsite content: {lsite_content}")
def _prepare_rsite(self):
rsite_content = ""
for site in self._epitope_sites:
rsite_content += f"{site.resseq}:{site.chain}\n"
with open(os.path.join(self.tmpdir.name, 'rsite.txt'), 'w') as f:
f.write(rsite_content)
print(f"[INFO] rsite content: {rsite_content}")
def dock(self):
if not (self._has_receptor and self._has_ligand):
raise ValueError('Missing receptor or ligand.')
self._prepare_lsite()
cmd_hdock = [self.hdock_bin, "receptor.pdb", "ligand.pdb", "-lsite", "lsite.txt"]
if self._epitope_sites is not None:
self._prepare_rsite()
cmd_hdock += ["-rsite", "rsite.txt"]
subprocess.run(
cmd_hdock,
cwd=self.tmpdir.name, check=True
)
cmd_pl = [self.createpl_bin, "Hdock.out", "ligand_docked.pdb", "-lsite", "lsite.txt"]
if self._epitope_sites is not None:
self._prepare_rsite()
cmd_pl += ["-rsite", "rsite.txt"]
subprocess.run(
cmd_pl,
cwd=self.tmpdir.name, check=True
)
return self._dump_complex_pdb()
if __name__ == '__main__':
with HDockAntibody('hdock', 'createpl') as dock:
dock.set_antigen('./data/dock/receptor.pdb', [DockSite('A', 991)])
dock.set_antibody('./data/example_dock/3qhf_fv.pdb')
print(dock.dock())
|