Coverage for biobb_haddock/haddock_restraints/haddock3_passive_from_active.py: 71%

66 statements  

« prev     ^ index     » next       coverage.py v7.10.2, created at 2025-08-07 08:48 +0000

1#!/usr/bin/env python3 

2 

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

4 

5import argparse 

6from typing import Optional 

7 

8from biobb_common.configuration import settings 

9from biobb_common.generic.biobb_object import BiobbObject 

10from biobb_common.tools.file_utils import launchlogger 

11from biobb_common.tools import file_utils as fu 

12 

13 

14class Haddock3PassiveFromActive(BiobbObject): 

15 """ 

16 | biobb_haddock Haddock3PassiveFromActive 

17 | Wrapper class for the Haddock3-Restraints passive_from_active module. 

18 | `Haddock3-Restraints passive_from_active <https://www.bonvinlab.org/haddock3/clients/haddock.clis.restraints.passive_from_active.html>`_ given a list of active_residues and a PDB structure, it will return a list of surface exposed passive residues within a radius (6.5Å by default) from the active residues. 

19 

20 Args: 

21 input_pdb_path (str): Path to the input PDB structure file. File type: input. `Sample file <https://raw.githubusercontent.com/bioexcel/biobb_haddock/master/biobb_haddock/test/data/haddock_restraints/1A2P_ch.pdb>`_. Accepted formats: pdb (edam:format_1476). 

22 output_actpass_path (str): Path to the output file with list of passive residues. File type: output. `Sample file <https://raw.githubusercontent.com/bioexcel/biobb_haddock/master/biobb_haddock/test/reference/haddock_restraints/1A2P_manual_actpass.txt>`_. Accepted formats: txt (edam:format_2330), dat (edam:format_2330), list (edam:format_2330), out (edam:format_2330). 

23 input_active_list_path (str) (Optional): Path to the input file with list of active residues. File type: input. Accepted formats: txt (edam:format_2330), dat (edam:format_2330), list (edam:format_2330). 

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

25 * **active_list** (*str*) - ('') List of active residues as a comma-separated string. Required if input_active_list_path is not provided. 

26 * **chain_id** (*str*) - (None) Chain ID to consider when calculating passive residues. 

27 * **surface_list_path** (*str*) - ("") Path to file with list of surface residues to filter. 

28 * **radius** (*float*) - (6.5) Radius in Angstroms to look for surface residues around active ones. 

29 * **binary_path** (*str*) - ("haddock3-restraints") Path to the haddock3-restraints executable binary. 

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

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

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

33 * **container_path** (*str*) - (None) Path to the binary executable of your container. 

34 * **container_image** (*str*) - (None) Container Image identifier. 

35 * **container_volume_path** (*str*) - ("/data") Path to an internal directory in the container. 

36 * **container_working_dir** (*str*) - (None) Path to the internal CWD in the container. 

37 * **container_user_id** (*str*) - (None) User number id to be mapped inside the container. 

38 * **container_shell_path** (*str*) - ("/bin/bash") Path to the binary executable of the container shell. 

39 

40 Examples: 

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

42 

43 from biobb_haddock.haddock_restraints.haddock3_passive_from_active import haddock3_passive_from_active 

44 haddock3_passive_from_active( 

45 input_pdb_path='/path/to/structure.pdb', 

46 input_active_list_path='/path/to/active_residues.txt', 

47 output_actpass_path='/path/to/actpass.tbl.txt', 

48 properties={ 

49 'chain_id': 'A', 

50 'radius': 6.5 

51 } 

52 ) 

53 

54 Info: 

55 * wrapped_software: 

56 * name: Haddock33-restraints 

57 * version: 2025.5 

58 * license: Apache-2.0 

59 * ontology: 

60 * name: EDAM 

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

62 """ 

63 

64 def __init__( 

65 self, 

66 input_pdb_path: str, 

67 output_actpass_path: str, 

68 input_active_list_path: Optional[str] = None, 

69 properties: Optional[dict] = None, 

70 **kwargs, 

71 ) -> None: 

72 properties = properties or {} 

73 

74 # Call parent class constructor 

75 super().__init__(properties) 

76 

77 # Input/Output files 

78 self.io_dict = { 

79 "in": { 

80 "input_pdb_path": input_pdb_path 

81 }, 

82 "out": { 

83 "output_actpass_path": output_actpass_path 

84 }, 

85 } 

86 

87 # Add input_active_list_path to io_dict if provided 

88 if input_active_list_path: 

89 self.io_dict["in"]["input_active_list_path"] = input_active_list_path 

90 

91 # Properties specific for BB 

92 self.active_list = properties.get("active_list", "") 

93 self.chain_id = properties.get("chain_id", None) 

94 self.surface_list_path = properties.get("surface_list_path", "") 

95 self.radius = properties.get("radius", 6.5) 

96 self.binary_path = properties.get("binary_path", "haddock3-restraints") 

97 

98 # Check that either input_active_list_path or active_list is provided 

99 if not input_active_list_path and not self.active_list: 

100 raise ValueError( 

101 "Either input_active_list_path or active_list property must be provided") 

102 

103 # Check the properties 

104 self.check_properties(properties) 

105 

106 # If surface_list_path is provided overwrite the active_list 

107 if self.surface_list_path: 

108 with open(self.surface_list_path, "r") as surface_file: 

109 self.active_list = surface_file.read() 

110 

111 @launchlogger 

112 def launch(self) -> int: 

113 """Execute the :class:`Haddock3PassiveFromActive <biobb_haddock.haddock_restraints.haddock3_passive_from_active>` object.""" 

114 

115 # Setup Biobb 

116 if self.check_restart(): 

117 return 0 

118 self.stage_files() 

119 

120 # Build command line 

121 # haddock3-restraints passive_from_active <pdb_file> <active_list> [-c <chain_id>] [-s <surface_list>] [-r <radius>] 

122 self.cmd = [ 

123 self.binary_path, 

124 "passive_from_active", 

125 self.stage_io_dict['in']['input_pdb_path'], 

126 self.active_list 

127 ] 

128 

129 # Add optional parameters 

130 if self.chain_id: 

131 self.cmd.extend(["-c", self.chain_id]) 

132 

133 if self.surface_list_path: 

134 self.cmd.extend( 

135 ["-s", self.stage_io_dict['in']['surface_list_path']]) 

136 

137 # Radius not in this version 

138 # self.cmd.extend(["-r", str(self.radius)]) 

139 

140 # Redirect output to the output file 

141 self.cmd.append(">") 

142 self.cmd.append(self.stage_io_dict['out']['output_actpass_path']) 

143 self.cmd.append("2>&1") 

144 

145 # Run Biobb block 

146 self.run_biobb() 

147 

148 # Remove deprecation warning if present 

149 with open(self.stage_io_dict['out']['output_actpass_path'], 'r') as file: 

150 lines = file.readlines() 

151 fu.log('Result: ' + '\n'.join(lines), self.out_log, self.global_log) 

152 with open(self.stage_io_dict['out']['output_actpass_path'], 'w') as file: 

153 file.write(self.active_list.replace(",", " ")+"\n") 

154 if lines and "DEPRECATION NOTICE" in lines[0]: 

155 file.writelines(lines[1:]) 

156 else: 

157 file.writelines(lines) 

158 

159 # Copy files to host 

160 self.copy_to_host() 

161 

162 # Remove temporal files 

163 self.tmp_files.extend([self.stage_io_dict["unique_dir"]]) 

164 self.remove_tmp_files() 

165 

166 return self.return_code 

167 

168 

169def haddock3_passive_from_active( 

170 input_pdb_path: str, 

171 output_actpass_path: str, 

172 input_active_list_path: Optional[str] = None, 

173 properties: Optional[dict] = None, 

174 **kwargs, 

175) -> int: 

176 """Create :class:`Haddock3PassiveFromActive <biobb_haddock.haddock_restraints.haddock3_passive_from_active>` class and 

177 execute the :meth:`launch() <biobb_haddock.haddock_restraints.haddock3_passive_from_active.launch>` method.""" 

178 

179 return Haddock3PassiveFromActive( 

180 input_pdb_path=input_pdb_path, 

181 output_actpass_path=output_actpass_path, 

182 input_active_list_path=input_active_list_path, 

183 properties=properties, 

184 **kwargs, 

185 ).launch() 

186 

187 

188haddock3_passive_from_active.__doc__ = Haddock3PassiveFromActive.__doc__ 

189 

190 

191def main(): 

192 parser = argparse.ArgumentParser( 

193 description="Wrapper of the haddock3-restraints passive_from_active module.", 

194 formatter_class=lambda prog: argparse.RawTextHelpFormatter( 

195 prog, width=99999), 

196 ) 

197 parser.add_argument( 

198 "-c", 

199 "--config", 

200 required=False, 

201 help="This file can be a YAML file, JSON file or JSON string", 

202 ) 

203 

204 # Specific args of each building block 

205 required_args = parser.add_argument_group("required arguments") 

206 required_args.add_argument("--input_pdb_path", required=True) 

207 required_args.add_argument("--output_actpass_path", required=True) 

208 

209 # Optional arguments 

210 parser.add_argument("--input_active_list_path", required=False) 

211 

212 args = parser.parse_args() 

213 config = args.config if args.config else None 

214 properties = settings.ConfReader(config=config).get_prop_dic() 

215 

216 # Specific call of each building block 

217 haddock3_passive_from_active( 

218 input_pdb_path=args.input_pdb_path, 

219 output_actpass_path=args.output_actpass_path, 

220 input_active_list_path=args.input_active_list_path, 

221 properties=properties, 

222 ) 

223 

224 

225if __name__ == "__main__": 

226 main()