Source code for haddock.modules.sampling.lightdock

"""LightDock integration sampling module."""
import shutil
import subprocess
from pathlib import Path

from haddock import log
from haddock.core.defaults import MODULE_DEFAULT_YAML
from haddock.core.typing import Any, FilePath
from haddock.libs import libpdb
from haddock.libs.libio import working_directory
from haddock.libs.libontology import Format, PDBFile
from haddock.libs.libutil import check_subprocess
from haddock.modules import BaseHaddockModule


RECIPE_PATH = Path(__file__).resolve().parent
DEFAULT_CONFIG = Path(RECIPE_PATH, MODULE_DEFAULT_YAML)


[docs] class HaddockModule(BaseHaddockModule): """HADDOCK3 Lightdock module.""" name = RECIPE_PATH.name def __init__( self, order: int, path: Path, *ignore: Any, initial_params: FilePath = DEFAULT_CONFIG, **everything: Any, ) -> None: super().__init__(order, path, initial_params)
[docs] @classmethod def confirm_installation(cls) -> None: """Confirm this module is installed.""" check_subprocess('lightdock3.py -h')
def _run(self) -> None: """Execute module.""" # Get the models generated in previous step models: list[PDBFile] = [ p for p in self.previous_io.output if p.file_type == Format.PDB ] # Check if multiple models are provided if len(models) > 1: _msg = "Only one model allowed in LightDock sampling module" self.finish_with_error(_msg) model = models[0] # Check if chain IDs are present _path = Path(model.path, model.file_name) segids, chains = libpdb.identify_chainseg(_path) if set(segids) != set(chains): log.info("No chain IDs found, using segid information") libpdb.swap_segid_chain( Path(model.path, model.file_name), Path(self.path, model.file_name), ) else: # Copy original model to this working path shutil.copyfile( Path(model.path, model.file_name), Path(self.path, model.file_name), ) model_with_chains = self.path / model.file_name # Split by chain new_models = libpdb.split_by_chain(model_with_chains) if model_with_chains in new_models: self.finish_with_error(f"Input {model_with_chains} cannot be" " split by chain") # Receptor and ligand PDB structures rec_chain = self.params["receptor_chains"][0] lig_chain = self.params["ligand_chains"][0] receptor_pdb_file = (f"{Path(model.file_name).stem}_" f"{rec_chain}.{Format.PDB}") ligand_pdb_file = (f"{Path(model.file_name).stem}_" f"{lig_chain}.{Format.PDB}") # Setup log.info("Running LightDock setup") with working_directory(self.path): swarms = self.params["swarms"] glowworms = self.params["glowworms"] noxt = self.params["noxt"] noh = self.params["noh"] cmd = (f"lightdock3_setup.py {receptor_pdb_file}" f" {ligand_pdb_file} -s {swarms} -g {glowworms}") if noxt: cmd += " --noxt" if noh: cmd += " --noh" subprocess.call(cmd, shell=True) # Simulation log.info("Running LightDock simulation") with working_directory(self.path): steps = self.params["steps"] scoring = self.params["scoring"] cores = self.params['ncores'] or 1 cmd = f"lightdock3.py setup.json {steps} -c {cores} -s {scoring}" subprocess.call(cmd, shell=True) # Clustering # Ranking log.info("Generating ranking") with working_directory(self.path): steps = self.params["steps"] swarms = self.params["swarms"] cmd = f"lgd_rank.py {swarms} {steps}" subprocess.call(cmd, shell=True) # Generate top, requires a hack to use original structures (H, OXT, # etc.) log.info("Generating top structures") with working_directory(self.path): # Save structures, needs error control shutil.copyfile( Path(self.path, receptor_pdb_file), Path(self.path, f"tmp_{receptor_pdb_file}"), ) shutil.copyfile( Path(self.path, ligand_pdb_file), Path(self.path, f"tmp_{ligand_pdb_file}") ) shutil.copy( Path(self.path, receptor_pdb_file), Path(self.path, f"lightdock_{receptor_pdb_file}"), ) shutil.copy( Path(self.path, ligand_pdb_file), Path(self.path, f"lightdock_{ligand_pdb_file}"), ) # Create top steps = self.params["steps"] top = self.params["top"] cmd = (f"lgd_top.py {receptor_pdb_file} {ligand_pdb_file}" f" rank_by_scoring.list {top}") subprocess.call(cmd, shell=True) # Tidy top files expected: list[PDBFile] = [] top = self.params["top"] for i in range(top): file_name = f"top_{i+1}.{Format.PDB}" tidy_file_name = f"haddock_top_{i+1}.{Format.PDB}" libpdb.tidy(self.path / file_name, self.path / tidy_file_name) expected.append(PDBFile(tidy_file_name, topology=model.topology, path=self.path)) self.output_models = models self.export_io_models()