Coverage for biobb_structure_utils / utils / remove_ligand.py: 95%
44 statements
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-16 14:59 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-16 14:59 +0000
1#!/usr/bin/env python3
3"""Module containing the RemoveLigand class and the command line interface."""
4from typing import Optional
5from pathlib import Path
6from biobb_common.generic.biobb_object import BiobbObject
7from biobb_common.tools import file_utils as fu
8from biobb_common.tools.file_utils import launchlogger
10from biobb_structure_utils.gro_lib.gro import Gro
13class RemoveLigand(BiobbObject):
14 """
15 | biobb_structure_utils RemoveLigand
16 | Class to remove the selected ligand atoms from a 3D structure.
17 | Remove the selected ligand atoms from a 3D structure.
19 Args:
20 input_structure_path (str): Input structure file path. File type: input. `Sample file <https://github.com/bioexcel/biobb_structure_utils/raw/master/biobb_structure_utils/test/data/utils/WT_aq4_md_1.pdb>`_. Accepted formats: pdb (edam:format_1476), gro (edam:format_2033).
21 output_structure_path (str): Output structure file path. File type: output. `Sample file <https://github.com/bioexcel/biobb_structure_utils/raw/master/biobb_structure_utils/test/reference/utils/WT_apo_md_1.pdb>`_. Accepted formats: pdb (edam:format_1476), gro (edam:format_2033).
22 properties (dic - Python dictionary object containing the tool parameters, not input/output files):
23 * **ligand** (*str*) - ("AQ4") Residue code of the ligand to be removed.
24 * **remove_tmp** (*bool*) - (True) [WF property] Remove temporal files.
25 * **restart** (*bool*) - (False) [WF property] Do not execute if output files exist.
26 * **sandbox_path** (*str*) - ("./") [WF property] Parent path to the sandbox directory.
28 Examples:
29 This is a use example of how to use the building block from Python::
31 from biobb_structure_utils.utils.remove_ligand import remove_ligand
32 prop = {
33 'ligand': 'AQ4'
34 }
35 remove_ligand(input_structure_path='/path/to/myStructure.pdb',
36 output_structure_path='/path/to/newStructure.pdb',
37 properties=prop)
39 Info:
40 * wrapped_software:
41 * name: In house
42 * license: Apache-2.0
43 * ontology:
44 * name: EDAM
45 * schema: http://edamontology.org/EDAM.owl
47 """
49 def __init__(
50 self, input_structure_path, output_structure_path, properties=None, **kwargs
51 ) -> None:
52 properties = properties or {}
54 # Call parent class constructor
55 super().__init__(properties)
56 self.locals_var_dict = locals().copy()
58 # Input/Output files
59 self.io_dict = {
60 "in": {"input_structure_path": input_structure_path},
61 "out": {"output_structure_path": output_structure_path},
62 }
64 # Properties specific for BB
65 self.ligand = properties.get("ligand", "AQ4")
67 # Check the properties
68 self.check_properties(properties)
69 self.check_arguments()
71 @launchlogger
72 def launch(self) -> int:
73 """Execute the :class:`RemoveLigand <utils.remove_ligand.RemoveLigand>` utils.remove_ligand.RemoveLigand object."""
75 # Setup Biobb
76 if self.check_restart():
77 return 0
78 self.stage_files()
80 # Business code
81 extension = Path(
82 self.stage_io_dict["in"]["input_structure_path"]
83 ).suffix.lower()
84 if extension.lower() == ".gro":
85 fu.log(
86 "GRO format detected, removing all atoms from residues named %s"
87 % self.ligand,
88 self.out_log,
89 )
90 gro_st = Gro()
91 gro_st.read_gro_file(self.stage_io_dict["in"]["input_structure_path"])
92 gro_st.remove_residues([self.ligand])
93 gro_st.write_gro_file(self.stage_io_dict["out"]["output_structure_path"])
95 else:
96 fu.log(
97 "PDB format detected, removing all atoms from residues named %s"
98 % self.ligand,
99 self.out_log,
100 )
101 # Direct aproach solution implemented to avoid the issues
102 # presented in commit message (c92aab9604a6a31d13f4170ff47b231df0a588ef)
103 # with the Biopython library
104 with open(
105 self.stage_io_dict["in"]["input_structure_path"], "r"
106 ) as input_pdb, open(
107 self.stage_io_dict["out"]["output_structure_path"], "w"
108 ) as output_pdb:
109 for line in input_pdb:
110 if len(line) > 19 and self.ligand.lower() in line[17:20].lower():
111 continue
112 output_pdb.write(line)
114 self.return_code = 0
115 ##########
117 # Copy files to host
118 self.copy_to_host()
120 # Remove temporal files
121 self.remove_tmp_files()
123 self.check_arguments(output_files_created=True, raise_exception=False)
125 return self.return_code
128def remove_ligand(
129 input_structure_path: str,
130 output_structure_path: str,
131 properties: Optional[dict] = None,
132 **kwargs,
133) -> int:
134 """Create the :class:`RemoveLigand <utils.remove_ligand.RemoveLigand>` class and
135 execute the :meth:`launch() <utils.remove_ligand.RemoveLigand.launch>` method."""
136 return RemoveLigand(**dict(locals())).launch()
139remove_ligand.__doc__ = RemoveLigand.__doc__
140main = RemoveLigand.get_main(remove_ligand, "Remove the selected ligand atoms from a 3D structure.")
142if __name__ == "__main__":
143 main()