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

74 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2025-12-16 15:25 +0000

1#!/usr/bin/env python3 

2 

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

4import json 

5from typing import Optional 

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_vs.fpocket.common import ( 

11 check_input_path, 

12 check_output_path, 

13 check_range, 

14 process_output_fpocket_filter, 

15) 

16from biobb_vs.utils.common import _from_string_to_list 

17 

18 

19class FPocketFilter(BiobbObject): 

20 """ 

21 | biobb_vs FPocketFilter 

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

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

24 

25 Args: 

26 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). 

27 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). 

28 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). 

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

30 * **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>`_. 

31 * **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. 

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

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

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

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

36 

37 Examples: 

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

39 

40 from biobb_vs.fpocket.fpocket_filter import fpocket_filter 

41 prop = { 

42 'score': [0.2, 1], 

43 'druggability_score': [0.2, 0.8], 

44 'volume': [100, 600.2] 

45 } 

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

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

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

49 properties=prop) 

50 

51 Info: 

52 * wrapped_software: 

53 * name: In house 

54 * license: Apache-2.0 

55 * ontology: 

56 * name: EDAM 

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

58 

59 """ 

60 

61 def __init__( 

62 self, 

63 input_pockets_zip, 

64 input_summary, 

65 output_filter_pockets_zip, 

66 properties=None, 

67 **kwargs, 

68 ) -> None: 

69 properties = properties or {} 

70 

71 # Call parent class constructor 

72 super().__init__(properties) 

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

74 

75 # Input/Output files 

76 self.io_dict = { 

77 "in": { 

78 "input_pockets_zip": input_pockets_zip, 

79 "input_summary": input_summary, 

80 }, 

81 "out": {"output_filter_pockets_zip": output_filter_pockets_zip}, 

82 } 

83 

84 # Properties specific for BB 

85 self.score = [ 

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

87 ] 

88 self.druggability_score = [ 

89 float(elem) 

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

91 ] 

92 

93 self.volume = [ 

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

95 ] 

96 self.properties = properties 

97 

98 # Check the properties 

99 self.check_properties(properties) 

100 self.check_arguments() 

101 

102 def check_data_params(self, out_log, err_log): 

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

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

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

106 "input_pockets_zip", 

107 out_log, 

108 self.__class__.__name__, 

109 ) 

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

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

112 "input_summary", 

113 False, 

114 out_log, 

115 self.__class__.__name__, 

116 ) 

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

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

119 "output_filter_pockets_zip", 

120 True, 

121 out_log, 

122 self.__class__.__name__, 

123 ) 

124 

125 def score_matcher(self, score): 

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

127 

128 def druggability_score_matcher(self, druggability_score): 

129 return ( 

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

131 ) 

132 

133 def volume_matcher(self, volume): 

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

135 

136 @launchlogger 

137 def launch(self) -> int: 

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

139 

140 # check input/output paths and parameters 

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

142 

143 # Setup Biobb 

144 if self.check_restart(): 

145 return 0 

146 self.stage_files() 

147 

148 # load input_summary into a dictionary 

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

150 data = json.load(json_file) 

151 

152 # build search_list 

153 search_list = [] 

154 ranges = {} 

155 if self.score: 

156 check_range( 

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

158 ) 

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

160 ranges["score"] = self.score 

161 if self.druggability_score: 

162 check_range( 

163 "druggability_score", 

164 self.druggability_score, 

165 [0, 1], 

166 self.out_log, 

167 self.__class__.__name__, 

168 ) 

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

170 ranges["druggability_score"] = self.druggability_score 

171 if self.volume: 

172 check_range( 

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

174 ) 

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

176 ranges["volume"] = self.volume 

177 

178 fu.log( 

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

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

181 self.out_log, 

182 ) 

183 

184 # perform search 

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

186 

187 if len(search) == 0: 

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

189 return 0 

190 

191 str_out = "" 

192 for s in search: 

193 str_out = str_out + ( 

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

195 % ( 

196 s, 

197 data[s]["score"], 

198 data[s]["druggability_score"], 

199 data[s]["volume"], 

200 ) 

201 ) 

202 

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

204 

205 # create tmp_folder 

206 self.tmp_folder = fu.create_unique_dir() 

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

208 

209 process_output_fpocket_filter( 

210 search, 

211 self.tmp_folder, 

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

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

214 self.remove_tmp, 

215 self.out_log, 

216 ) 

217 

218 # Copy files to host 

219 self.copy_to_host() 

220 

221 self.tmp_files.extend([ 

222 self.tmp_folder 

223 ]) 

224 self.remove_tmp_files() 

225 

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

227 

228 return 0 

229 

230 

231def fpocket_filter( 

232 input_pockets_zip: str, 

233 input_summary: str, 

234 output_filter_pockets_zip: str, 

235 properties: Optional[dict] = None, 

236 **kwargs, 

237) -> int: 

238 """Create the :class:`FPocketFilter <fpocket.fpocket_filter.FPocketFilter>` class and 

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

240 return FPocketFilter(**dict(locals())).launch() 

241 

242 

243fpocket_filter.__doc__ = FPocketFilter.__doc__ 

244main = FPocketFilter.get_main(fpocket_filter, "Finds one or more binding sites in the outputs of the fpocket building block from given parameters.") 

245 

246 

247if __name__ == "__main__": 

248 main()