Coverage for biobb_chemistry/babelm/babel_remove_hydrogens.py: 95%

77 statements  

« prev     ^ index     » next       coverage.py v7.17.2, created at 2026-11-06 12:40 +0000

1#!/usr/bin/env python3 

2 

3"""Module containing the BabelRemoveHydrogens class and the command line interface.""" 

4from typing import Optional 

5from biobb_common.generic.biobb_object import BiobbObject 

6from biobb_common.tools.file_utils import launchlogger 

7 

8from biobb_chemistry.babelm.common import ( 

9 _from_string_to_list, 

10 check_input_path, 

11 check_output_path, 

12 get_coordinates, 

13 get_input_format, 

14 get_output_format, 

15 get_ph, 

16 remove_non_pdbqt_records, 

17) 

18 

19 

20class BabelRemoveHydrogens(BiobbObject): 

21 """ 

22 | biobb_chemistry BabelRemoveHydrogens 

23 | This class is a wrapper of the Open Babel tool. 

24 | Removes hydrogens to a given structure or trajectory. Open Babel is a chemical toolbox designed to speak the many languages of chemical data. It's an open, collaborative project allowing anyone to search, convert, analyze, or store data from molecular modeling, chemistry, solid-state materials, biochemistry, or related areas. `Visit the official page <http://openbabel.org/wiki/Main_Page>`_. 

25 

26 Args: 

27 input_path (str): Path to the input file. File type: input. `Sample file <https://github.com/bioexcel/biobb_chemistry/raw/master/biobb_chemistry/test/data/babelm/babel.H.pdb>`_. Accepted formats: dat (edam:format_1637), ent (edam:format_1476), fa (edam:format_1929), fasta (edam:format_1929), gro (edam:format_2033), inp (edam:format_3878), log (edam:format_2030), mcif (edam:format_1477), mdl (edam:format_3815), mmcif (edam:format_1477), mol (edam:format_3815), mol2 (edam:format_3816), pdb (edam:format_1476), pdbqt (edam:format_1476), png (edam:format_3603), sdf (edam:format_3814), smi (edam:format_1196), smiles (edam:format_1196), txt (edam:format_2033), xml (edam:format_2332), xtc (edam:format_3875). 

28 output_path (str): Path to the output file. File type: output. `Sample file <https://github.com/bioexcel/biobb_chemistry/raw/master/biobb_chemistry/test/reference/babelm/ref_babel.nohydrogens.pdb>`_. Accepted formats: ent (edam:format_1476), fa (edam:format_1929), fasta (edam:format_1929), gro (edam:format_2033), inp (edam:format_3878), mcif (edam:format_1477), mdl (edam:format_3815), mmcif (edam:format_1477), mol (edam:format_3815), mol2 (edam:format_3816), pdb (edam:format_1476), pdbqt (edam:format_1476), png (edam:format_3603), sdf (edam:format_3814), smi (edam:format_1196), smiles (edam:format_1196), txt (edam:format_2033). 

29 properties (dic - Python dictionary object containing the tool parameters, not input/output files): 

30 * **input_format** (*str*) - (None) Format of input file. If not provided, input_path extension will be taken. Values: dat (Information represented in a data record), ent (Protein Data Bank format), fa (FASTA sequence format), fasta (FASTA sequence format), gro (GROMACS structure), inp (AMBER trajectory format), log (Events file), mcif (Entry format of PDB database in mmCIF format), mdl (file format for holding information about the atoms; bonds; connectivity and coordinates of a molecule), mmcif (Entry format of PDB database in mmCIF format), mol (file format for holding information about the atoms; bonds; connectivity and coordinates of a molecule), mol2 (Complete and portable representation of a SYBYL molecule), pdb (Protein Data Bank format), pdbqt (Protein Data Bank format with charges), png (File format for image compression), sdf (One of a family of chemical-data file formats developed by MDL Information Systems), smi (Chemical structure specified in Simplified Molecular Input Line Entry System line notation.), smiles (Chemical structure specified in Simplified Molecular Input Line Entry System line notation.), txt (Textual format), xml (eXtensible Markup Language), xtc (Portable binary format for trajectories produced by GROMACS package). 

31 * **output_format** (*str*) - (None) Format of output file. If not provided, output_path extension will be taken. Values: ent (Protein Data Bank format), fa (FASTA sequence format), fasta (FASTA sequence format), gro (GROMACS structure), inp (AMBER trajectory format), mcif (Entry format of PDB database in mmCIF format), mdl (file format for holding information about the atoms; bonds; connectivity and coordinates of a molecule), mmcif (Entry format of PDB database in mmCIF format), mol (file format for holding information about the atoms; bonds; connectivity and coordinates of a molecule), mol2 (Complete and portable representation of a SYBYL molecule), pdb (Protein Data Bank format), pdbqt (Protein Data Bank format with charges), png (File format for image compression), sdf (One of a family of chemical-data file formats developed by MDL Information Systems), smi (Chemical structure specified in Simplified Molecular Input Line Entry System line notation.), smiles (Chemical structure specified in Simplified Molecular Input Line Entry System line notation.), txt (Textual format), xtc (Portable binary format for trajectories produced by GROMACS package). 

32 * **fs_input** (*list*) - (None) Format-specific input options. Values: b (disable automatic bonding), d (input file is in dlg -AutoDock docking log- format). 

33 * **fs_output** (*list*) - (None) Format-specific output options. Values: b (enable automatic bonding), r (output as a rigid molecule), c (combine separate molecular pieces of input into a single rigid molecule), s (output as a flexible residue), p (preserve atom indices from input file), h (preserve hydrogens), n (preserve atom names). 

34 * **coordinates** (*int*) - (None) Type of coordinates: 2D or 3D. Values: 2 (2D coordinates), 3 (3D coordinates). 

35 * **effort** (*str*) - ("medium") Computational effort wanted to dedicate for the conformer generation coordinates calculations, only for 3D coordinates. Values: fastest (only generate coordinates, no force field or conformer search), fast (perform quick forcefield optimization), medium (forcefield optimization + fast conformer search), better (more optimization + fast conformer search), best (more optimization + significant conformer search). 

36 * **ph** (*float*) - (7.4) [0~14|0.1] Add hydrogens appropriate for pH. 

37 * **binary_path** (*str*) - ("obabel") Path to the obabel executable binary. 

38 * **remove_tmp** (*bool*) - (True) [WF property] Remove temporal files. 

39 * **restart** (*bool*) - (False) [WF property] Do not execute if output files exist. 

40 * **sandbox_path** (*str*) - ("./") [WF property] Parent path to the sandbox directory. 

41 * **container_path** (*str*) - (None) Container path definition. 

42 * **container_image** (*str*) - ('informaticsmatters/obabel:latest') Container image definition. 

43 * **container_volume_path** (*str*) - ('/tmp') Container volume path definition. 

44 * **container_working_dir** (*str*) - (None) Container working directory definition. 

45 * **container_user_id** (*str*) - (None) Container user_id definition. 

46 * **container_shell_path** (*str*) - ('/bin/bash') Path to default shell inside the container. 

47 

48 Examples: 

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

50 

51 from biobb_chemistry.babelm.babel_remove_hydrogens import babel_remove_hydrogens 

52 prop = { 

53 'input_format': 'pdb', 

54 'output_format': 'pdb', 

55 'coordinates': 3, 

56 'ph': 7.4 

57 } 

58 babel_remove_hydrogens(input_path='/path/to/myStructure.pdb', 

59 output_path='/path/to/newStructure.pdb', 

60 properties=prop) 

61 

62 Info: 

63 * wrapped_software: 

64 * name: Open Babel 

65 * version: 2.4.1 

66 * license: GNU 

67 * ontology: 

68 * name: EDAM 

69 * schema: http://edamontology.org/EDAM.owl 

70 

71 """ 

72 

73 def __init__(self, input_path, output_path, properties=None, **kwargs) -> None: 

74 properties = properties or {} 

75 

76 # Call parent class constructor 

77 super().__init__(properties) 

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

79 

80 # Input/Output files 

81 self.io_dict = { 

82 "in": {"input_path": input_path}, 

83 "out": {"output_path": output_path}, 

84 } 

85 

86 # Properties specific for BB 

87 self.input_format = properties.get("input_format", "") 

88 self.output_format = properties.get("output_format", "") 

89 self.fs_input = _from_string_to_list(properties.get("fs_input", None)) 

90 self.fs_output = _from_string_to_list(properties.get("fs_output", None)) 

91 self.coordinates = properties.get("coordinates", "") 

92 self.effort = properties.get("effort", "medium") 

93 self.ph = properties.get("ph", "") 

94 self.binary_path = properties.get("binary_path", "obabel") 

95 self.properties = properties 

96 

97 # Check the properties 

98 self.check_properties(properties) 

99 self.check_arguments() 

100 

101 def check_data_params(self, out_log, err_log): 

102 """Checks all the input/output paths and parameters""" 

103 self.io_dict["in"]["input_path"] = check_input_path( 

104 self.io_dict["in"]["input_path"], out_log, self.__class__.__name__ 

105 ) 

106 self.io_dict["out"]["output_path"] = check_output_path( 

107 self.io_dict["out"]["output_path"], out_log, self.__class__.__name__ 

108 ) 

109 

110 def create_cmd(self, container_io_dict, out_log, err_log): 

111 """Creates the command line instruction using the properties file settings""" 

112 instructions_list = [] 

113 

114 # executable path 

115 instructions_list.append(self.binary_path) 

116 

117 # generating input 

118 infr = get_input_format( 

119 self.input_format, container_io_dict["in"]["input_path"], out_log 

120 ) 

121 iformat = "-i" + infr 

122 instructions_list.append(iformat) 

123 ipath = container_io_dict["in"]["input_path"] 

124 instructions_list.append(ipath) 

125 

126 # generating output 

127 oufr = get_output_format( 

128 self.output_format, container_io_dict["out"]["output_path"], out_log 

129 ) 

130 oformat = "-o" + oufr 

131 instructions_list.append(oformat) 

132 opath = "-O" + container_io_dict["out"]["output_path"] 

133 instructions_list.append(opath) 

134 

135 # adding coordinates 

136 crd = get_coordinates(self.coordinates, out_log) 

137 coordinates = "" 

138 if crd: 

139 coordinates = "--gen" + crd + "d" 

140 instructions_list.append(coordinates) 

141 

142 hydrogens = "-d" 

143 

144 instructions_list.append(hydrogens) 

145 

146 # adding pH 

147 p = get_ph(self.ph, out_log) 

148 ph = "" 

149 if p: 

150 ph = "-p " + p 

151 instructions_list.append(ph) 

152 

153 # fs_input 

154 if self.fs_input is not None: 

155 for fsi in self.fs_input: 

156 instructions_list.append("-a" + fsi) 

157 

158 # fs_output 

159 if self.fs_output is not None: 

160 for fso in self.fs_output: 

161 instructions_list.append("-x" + fso) 

162 

163 # adding effort (only for 3D coordinates) 

164 if crd == "3": 

165 instructions_list.append("--" + self.effort) 

166 

167 return instructions_list 

168 

169 @launchlogger 

170 def launch(self) -> int: 

171 """Execute the :class:`BabelRemoveHydrogens <babelm.babel_remove_hydrogens.BabelRemoveHydrogens>` babelm.babel_remove_hydrogens.BabelRemoveHydrogens object.""" 

172 

173 # check input/output paths and parameters 

174 self.check_data_params(self.out_log, self.err_log) 

175 

176 # Setup Biobb 

177 if self.check_restart(): 

178 return 0 

179 self.stage_files() 

180 

181 # create command line instruction 

182 self.cmd = self.create_cmd(self.stage_io_dict, self.out_log, self.err_log) 

183 

184 # Run Biobb block 

185 self.run_biobb() 

186 

187 # Copy files to host 

188 self.copy_to_host() 

189 

190 # remove the input PDB records that Open Babel >= 3.2 copies to a PDBQT output 

191 remove_non_pdbqt_records(self.output_format, self.io_dict["out"]["output_path"], self.out_log) 

192 

193 # remove temporary folder(s) 

194 self.remove_tmp_files() 

195 

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

197 

198 return self.return_code 

199 

200 

201def babel_remove_hydrogens( 

202 input_path: str, output_path: str, properties: Optional[dict] = None, **kwargs 

203) -> int: 

204 """Create the :class:`BabelRemoveHydrogens <babelm.babel_remove_hydrogens.BabelRemoveHydrogens>` class and 

205 execute the :meth:`launch() <babelm.babel_remove_hydrogens.BabelRemoveHydrogens.launch>` method.""" 

206 return BabelRemoveHydrogens(**dict(locals())).launch() 

207 

208 

209babel_remove_hydrogens.__doc__ = BabelRemoveHydrogens.__doc__ 

210main = BabelRemoveHydrogens.get_main(babel_remove_hydrogens, "Removes hydrogen atoms to small molecules.") 

211 

212 

213if __name__ == "__main__": 

214 main()