Coverage for biobb_vs/fpocket/fpocket_filter.py: 83%

86 statements  

« prev     ^ index     » next       coverage.py v7.6.10, created at 2025-01-28 12:00 +0000

1#!/usr/bin/env python3 

2 

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

4 

5import argparse 

6import json 

7from typing import Optional 

8 

9from biobb_common.configuration import settings 

10from biobb_common.generic.biobb_object import BiobbObject 

11from biobb_common.tools import file_utils as fu 

12from biobb_common.tools.file_utils import launchlogger 

13 

14from biobb_vs.fpocket.common import ( 

15 check_input_path, 

16 check_output_path, 

17 check_range, 

18 process_output_fpocket_filter, 

19) 

20from biobb_vs.utils.common import _from_string_to_list 

21 

22 

23class FPocketFilter(BiobbObject): 

24 """ 

25 | biobb_vs FPocketFilter 

26 | Performs a search over the outputs of the fpocket building block. 

27 | Finds one or more binding sites in the outputs of the fpocket building block from given parameters. 

28 

29 Args: 

30 input_pockets_zip (str): Path to all the pockets found by fpocket. File type: input. `Sample file <https://github.com/bioexcel/biobb_vs/raw/master/biobb_vs/test/data/fpocket/input_pockets.zip>`_. Accepted formats: zip (edam:format_3987). 

31 input_summary (str): Path to the JSON summary file returned by fpocket. File type: input. `Sample file <https://github.com/bioexcel/biobb_vs/raw/master/biobb_vs/test/data/fpocket/input_summary.json>`_. Accepted formats: json (edam:format_3464). 

32 output_filter_pockets_zip (str): Path to the selected pockets after filtering. File type: output. `Sample file <https://github.com/bioexcel/biobb_vs/raw/master/biobb_vs/test/reference/fpocket/ref_output_filter_pockets.zip>`_. Accepted formats: zip (edam:format_3987). 

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

34 * **score** (*list*) - (None) List of two float numbers between 0 and 1 indicating the score range. Indicates the fpocket score after the evaluation of pocket prediction accuracy as defined in the `fpocket paper <https://doi.org/10.1186/1471-2105-10-168>`_. 

35 * **druggability_score** (*list*) - (None) List of two float numbers between 0 and 1 indicating the druggability_score range. It's a value between 0 and 1, 0 signifying that the pocket is likely to not bind a drug like molecule and 1, that it is very likely to bind the latter. 

36 * **volume** (*list*) - (None) List of two float numbers indicating the volume range. Indicates the pocket volume. 

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

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

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

40 

41 Examples: 

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

43 

44 from biobb_vs.fpocket.fpocket_filter import fpocket_filter 

45 prop = { 

46 'score': [0.2, 1], 

47 'druggability_score': [0.2, 0.8], 

48 'volume': [100, 600.2] 

49 } 

50 fpocket_filter(input_pockets_zip='/path/to/myPockets.zip', 

51 input_summary='/path/to/mySummary.json', 

52 output_filter_pockets_zip='/path/to/newPockets.json', 

53 properties=prop) 

54 

55 Info: 

56 * wrapped_software: 

57 * name: In house 

58 * license: Apache-2.0 

59 * ontology: 

60 * name: EDAM 

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

62 

63 """ 

64 

65 def __init__( 

66 self, 

67 input_pockets_zip, 

68 input_summary, 

69 output_filter_pockets_zip, 

70 properties=None, 

71 **kwargs, 

72 ) -> None: 

73 properties = properties or {} 

74 

75 # Call parent class constructor 

76 super().__init__(properties) 

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

78 

79 # Input/Output files 

80 self.io_dict = { 

81 "in": { 

82 "input_pockets_zip": input_pockets_zip, 

83 "input_summary": input_summary, 

84 }, 

85 "out": {"output_filter_pockets_zip": output_filter_pockets_zip}, 

86 } 

87 

88 # Properties specific for BB 

89 self.score = [ 

90 float(elem) for elem in _from_string_to_list(properties.get("score", None)) 

91 ] 

92 self.druggability_score = [ 

93 float(elem) 

94 for elem in _from_string_to_list(properties.get("druggability_score", None)) 

95 ] 

96 

97 self.volume = [ 

98 float(elem) for elem in _from_string_to_list(properties.get("volume", None)) 

99 ] 

100 self.properties = properties 

101 

102 # Check the properties 

103 self.check_properties(properties) 

104 self.check_arguments() 

105 

106 def check_data_params(self, out_log, err_log): 

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

108 self.io_dict["in"]["input_pockets_zip"] = check_input_path( 

109 self.io_dict["in"]["input_pockets_zip"], 

110 "input_pockets_zip", 

111 out_log, 

112 self.__class__.__name__, 

113 ) 

114 self.io_dict["in"]["input_summary"] = check_output_path( 

115 self.io_dict["in"]["input_summary"], 

116 "input_summary", 

117 False, 

118 out_log, 

119 self.__class__.__name__, 

120 ) 

121 self.io_dict["out"]["output_filter_pockets_zip"] = check_output_path( 

122 self.io_dict["out"]["output_filter_pockets_zip"], 

123 "output_filter_pockets_zip", 

124 True, 

125 out_log, 

126 self.__class__.__name__, 

127 ) 

128 

129 def score_matcher(self, score): 

130 return lambda d: d["score"] > score[0] and d["score"] <= score[1] 

131 

132 def druggability_score_matcher(self, druggability_score): 

133 return ( 

134 lambda d: d["druggability_score"] > druggability_score[0] and d["druggability_score"] <= druggability_score[1] 

135 ) 

136 

137 def volume_matcher(self, volume): 

138 return lambda d: d["volume"] > volume[0] and d["volume"] <= volume[1] 

139 

140 @launchlogger 

141 def launch(self) -> int: 

142 """Execute the :class:`FPocketFilter <fpocket.fpocket_filter.FPocketFilter>` fpocket.fpocket_filter.FPocketFilter object.""" 

143 

144 # check input/output paths and parameters 

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

146 

147 # Setup Biobb 

148 if self.check_restart(): 

149 return 0 

150 self.stage_files() 

151 

152 # load input_summary into a dictionary 

153 with open(self.io_dict["in"]["input_summary"]) as json_file: 

154 data = json.load(json_file) 

155 

156 # build search_list 

157 search_list = [] 

158 ranges = {} 

159 if self.score: 

160 check_range( 

161 "score", self.score, [0, 1], self.out_log, self.__class__.__name__ 

162 ) 

163 search_list.append(self.score_matcher(self.score)) 

164 ranges["score"] = self.score 

165 if self.druggability_score: 

166 check_range( 

167 "druggability_score", 

168 self.druggability_score, 

169 [0, 1], 

170 self.out_log, 

171 self.__class__.__name__, 

172 ) 

173 search_list.append(self.druggability_score_matcher(self.druggability_score)) 

174 ranges["druggability_score"] = self.druggability_score 

175 if self.volume: 

176 check_range( 

177 "volume", self.volume, [0, 10000], self.out_log, self.__class__.__name__ 

178 ) 

179 search_list.append(self.volume_matcher(self.volume)) 

180 ranges["volume"] = self.volume 

181 

182 fu.log( 

183 "Performing a search under the next parameters: %s" 

184 % (", ".join(["{0}: {1}".format(k, v) for k, v in ranges.items()])), 

185 self.out_log, 

186 ) 

187 

188 # perform search 

189 search = [x for x in data if all([f(data[x]) for f in search_list])] 

190 

191 if len(search) == 0: 

192 fu.log("No matches found", self.out_log) 

193 return 0 

194 

195 str_out = "" 

196 for s in search: 

197 str_out = str_out + ( 

198 "\n**********\n%s\n**********\nscore: %s\ndruggability_score: %s\nvolume: %s\n" 

199 % ( 

200 s, 

201 data[s]["score"], 

202 data[s]["druggability_score"], 

203 data[s]["volume"], 

204 ) 

205 ) 

206 

207 fu.log("Found %d matches:%s" % (len(search), str_out), self.out_log) 

208 

209 # create tmp_folder 

210 self.tmp_folder = fu.create_unique_dir() 

211 fu.log("Creating %s temporary folder" % self.tmp_folder, self.out_log) 

212 

213 process_output_fpocket_filter( 

214 search, 

215 self.tmp_folder, 

216 self.io_dict["in"]["input_pockets_zip"], 

217 self.io_dict["out"]["output_filter_pockets_zip"], 

218 self.remove_tmp, 

219 self.out_log, 

220 ) 

221 

222 # Copy files to host 

223 self.copy_to_host() 

224 

225 self.tmp_files.extend([ 

226 # self.stage_io_dict.get("unique_dir", ""), 

227 self.tmp_folder 

228 ]) 

229 self.remove_tmp_files() 

230 

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

232 

233 return 0 

234 

235 

236def fpocket_filter( 

237 input_pockets_zip: str, 

238 input_summary: str, 

239 output_filter_pockets_zip: str, 

240 properties: Optional[dict] = None, 

241 **kwargs, 

242) -> int: 

243 """Execute the :class:`FPocketFilter <fpocket.fpocket_filter.FPocketFilter>` class and 

244 execute the :meth:`launch() <fpocket.fpocket_filter.FPocketFilter.launch>` method.""" 

245 

246 return FPocketFilter( 

247 input_pockets_zip=input_pockets_zip, 

248 input_summary=input_summary, 

249 output_filter_pockets_zip=output_filter_pockets_zip, 

250 properties=properties, 

251 **kwargs, 

252 ).launch() 

253 

254 fpocket_filter.__doc__ = FPocketFilter.__doc__ 

255 

256 

257def main(): 

258 """Command line execution of this building block. Please check the command line documentation.""" 

259 parser = argparse.ArgumentParser( 

260 description="Finds one or more binding sites in the outputs of the fpocket building block from given parameters.", 

261 formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, width=99999), 

262 ) 

263 parser.add_argument("--config", required=False, help="Configuration file") 

264 

265 # Specific args of each building block 

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

267 required_args.add_argument( 

268 "--input_pockets_zip", 

269 required=True, 

270 help="Path to all the pockets found by fpocket. Accepted formats: zip.", 

271 ) 

272 required_args.add_argument( 

273 "--input_summary", 

274 required=True, 

275 help="Path to the JSON summary file returned by fpocket. Accepted formats: json.", 

276 ) 

277 required_args.add_argument( 

278 "--output_filter_pockets_zip", 

279 required=True, 

280 help="Path to the selected pockets after filtering. Accepted formats: zip.", 

281 ) 

282 

283 args = parser.parse_args() 

284 args.config = args.config or "{}" 

285 properties = settings.ConfReader(config=args.config).get_prop_dic() 

286 

287 # Specific call of each building block 

288 fpocket_filter( 

289 input_pockets_zip=args.input_pockets_zip, 

290 input_summary=args.input_summary, 

291 output_filter_pockets_zip=args.output_filter_pockets_zip, 

292 properties=properties, 

293 ) 

294 

295 

296if __name__ == "__main__": 

297 main()