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

1#!/usr/bin/env python3 

2 

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 

9 

10from biobb_structure_utils.gro_lib.gro import Gro 

11 

12 

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. 

18 

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. 

27 

28 Examples: 

29 This is a use example of how to use the building block from Python:: 

30 

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) 

38 

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 

46 

47 """ 

48 

49 def __init__( 

50 self, input_structure_path, output_structure_path, properties=None, **kwargs 

51 ) -> None: 

52 properties = properties or {} 

53 

54 # Call parent class constructor 

55 super().__init__(properties) 

56 self.locals_var_dict = locals().copy() 

57 

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 } 

63 

64 # Properties specific for BB 

65 self.ligand = properties.get("ligand", "AQ4") 

66 

67 # Check the properties 

68 self.check_properties(properties) 

69 self.check_arguments() 

70 

71 @launchlogger 

72 def launch(self) -> int: 

73 """Execute the :class:`RemoveLigand <utils.remove_ligand.RemoveLigand>` utils.remove_ligand.RemoveLigand object.""" 

74 

75 # Setup Biobb 

76 if self.check_restart(): 

77 return 0 

78 self.stage_files() 

79 

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"]) 

94 

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) 

113 

114 self.return_code = 0 

115 ########## 

116 

117 # Copy files to host 

118 self.copy_to_host() 

119 

120 # Remove temporal files 

121 self.remove_tmp_files() 

122 

123 self.check_arguments(output_files_created=True, raise_exception=False) 

124 

125 return self.return_code 

126 

127 

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() 

137 

138 

139remove_ligand.__doc__ = RemoveLigand.__doc__ 

140main = RemoveLigand.get_main(remove_ligand, "Remove the selected ligand atoms from a 3D structure.") 

141 

142if __name__ == "__main__": 

143 main()