Coverage for biobb_amber/leap/leap_gen_top.py: 65%

103 statements  

« prev     ^ index     » next       coverage.py v7.5.1, created at 2024-05-07 08:11 +0000

1#!/usr/bin/env python3 

2 

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

4import argparse 

5from pathlib import PurePath 

6from biobb_common.generic.biobb_object import BiobbObject 

7from biobb_common.configuration import settings 

8from biobb_common.tools import file_utils as fu 

9from biobb_common.tools.file_utils import launchlogger 

10from biobb_amber.leap.common import check_input_path, check_output_path 

11 

12 

13class LeapGenTop(BiobbObject): 

14 """ 

15 | biobb_amber.leap.leap_gen_top LeapGenTop 

16 | Wrapper of the `AmberTools (AMBER MD Package) leap tool <https://ambermd.org/AmberTools.php>`_ module. 

17 | Generates a MD topology from a molecule structure using tLeap tool from the AmberTools MD package. 

18 

19 Args: 

20 input_pdb_path (str): Input 3D structure PDB file. File type: input. `Sample file <https://github.com/bioexcel/biobb_amber/raw/master/biobb_amber/test/data/leap/structure.leapin.pdb>`_. Accepted formats: pdb (edam:format_1476). 

21 input_lib_path (str) (Optional): Input ligand library parameters file. File type: input. `Sample file <https://github.com/bioexcel/biobb_amber/raw/master/biobb_amber/test/data/leap/ligand.lib>`_. Accepted formats: lib (edam:format_3889), zip (edam:format_3987). 

22 input_frcmod_path (str) (Optional): Input ligand frcmod parameters file. File type: input. `Sample file <https://github.com/bioexcel/biobb_amber/raw/master/biobb_amber/test/data/leap/ligand.frcmod>`_. Accepted formats: frcmod (edam:format_3888), zip (edam:format_3987). 

23 input_params_path (str) (Optional): Additional leap parameter files to load with loadAmberParams Leap command. File type: input. `Sample file <https://github.com/bioexcel/biobb_amber/raw/master/biobb_amber/test/data/leap/frcmod.ionsdang_spce.txt>`_. Accepted formats: in (edam:format_2330), leapin (edam:format_2330), txt (edam:format_2330), zip (edam:format_3987). 

24 input_source_path (str) (Optional): Additional leap command files to load with source Leap command. File type: input. `Sample file <https://github.com/bioexcel/biobb_amber/raw/master/biobb_amber/test/data/leap/leaprc.water.spce.txt>`_. Accepted formats: in (edam:format_2330), leapin (edam:format_2330), txt (edam:format_2330), zip (edam:format_3987). 

25 output_pdb_path (str): Output 3D structure PDB file matching the topology file. File type: output. `Sample file <https://github.com/bioexcel/biobb_amber/raw/master/biobb_amber/test/reference/leap/structure.leap.pdb>`_. Accepted formats: pdb (edam:format_1476). 

26 output_top_path (str): Output topology file (AMBER ParmTop). File type: output. `Sample file <https://github.com/bioexcel/biobb_amber/raw/master/biobb_amber/test/reference/leap/structure.leap.top>`_. Accepted formats: top (edam:format_3881), parmtop (edam:format_3881), prmtop (edam:format_3881). 

27 output_crd_path (str): Output coordinates file (AMBER crd). File type: output. `Sample file <https://github.com/bioexcel/biobb_amber/raw/master/biobb_amber/test/reference/leap/structure.leap.crd>`_. Accepted formats: crd (edam:format_3878), mdcrd (edam:format_3878), inpcrd (edam:format_3878). 

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

29 * **forcefield** (*list*) - (["protein.ff14SB","DNA.bsc1","gaff"]) Forcefield to be used for the structure generation. Values: protein.ff14SB, protein.ff19SB, DNA.bsc1, DNA.OL15, RNA.OL3, gaff. 

30 * **binary_path** (*str*) - ("tleap") Path to the tleap executable binary. 

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

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

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

34 * **container_image** (*str*) - ('afandiadib/ambertools:serial') Container image definition. 

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

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

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

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

39 

40 Examples: 

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

42 

43 from biobb_amber.leap.leap_gen_top import leap_gen_top 

44 prop = { 

45 'forcefield': ['protein.ff14SB'] 

46 } 

47 leap_gen_top(input_pdb_path='/path/to/structure.pdb', 

48 output_pdb_path='/path/to/newStructure.pdb', 

49 output_top_path='/path/to/newTopology.top', 

50 output_crd_path='/path/to/newCoordinates.crd', 

51 properties=prop) 

52 

53 Info: 

54 * wrapped_software: 

55 * name: AmberTools tLeap 

56 * version: >20.9 

57 * license: LGPL 2.1 

58 * ontology: 

59 * name: EDAM 

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

61 

62 """ 

63 

64 def __init__(self, input_pdb_path: str, output_pdb_path: str, 

65 output_top_path: str, output_crd_path: str, 

66 input_lib_path: str = None, input_frcmod_path: str = None, 

67 input_params_path: str = None, input_source_path: str = None, 

68 properties: dict = None, **kwargs): 

69 

70 properties = properties or {} 

71 

72 # Call parent class constructor 

73 super().__init__(properties) 

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

75 

76 # Input/Output files 

77 self.io_dict = { 

78 'in': {'input_pdb_path': input_pdb_path, 

79 'input_lib_path': input_lib_path, 

80 'input_frcmod_path': input_frcmod_path, 

81 'input_params_path': input_params_path, 

82 'input_source_path': input_source_path}, 

83 'out': {'output_pdb_path': output_pdb_path, 

84 'output_top_path': output_top_path, 

85 'output_crd_path': output_crd_path} 

86 } 

87 

88 # # Ligand Parameter lists 

89 # self.ligands_lib_list = [] 

90 # if input_lib_path: 

91 # self.ligands_lib_list.append(input_lib_path) 

92 # 

93 # self.ligands_frcmod_list = [] 

94 # if input_frcmod_path: 

95 # self.ligands_frcmod_list.append(input_frcmod_path) 

96 

97 # Properties specific for BB 

98 self.properties = properties 

99 self.forcefield = properties.get('forcefield', ["protein.ff14SB", "DNA.bsc1", "gaff"]) 

100 self.binary_path = properties.get('binary_path', 'tleap') 

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 input/output paths correctness """ 

108 

109 # Check input(s) 

110 self.io_dict["in"]["input_pdb_path"] = check_input_path(self.io_dict["in"]["input_pdb_path"], "input_pdb_path", False, out_log, self.__class__.__name__) 

111 self.io_dict["in"]["input_lib_path"] = check_input_path(self.io_dict["in"]["input_lib_path"], "input_lib_path", True, out_log, self.__class__.__name__) 

112 self.io_dict["in"]["input_frcmod_path"] = check_input_path(self.io_dict["in"]["input_frcmod_path"], "input_frcmod_path", True, out_log, self.__class__.__name__) 

113 # self.io_dict["in"]["input_params_path"] = check_input_path(self.io_dict["in"]["input_params_path"], "input_params_path", True, out_log, self.__class__.__name__) 

114 # self.io_dict["in"]["input_source_path"] = check_input_path(self.io_dict["in"]["input_source_path"], "input_source_path", True, out_log, self.__class__.__name__) 

115 

116 # Check output(s) 

117 self.io_dict["out"]["output_pdb_path"] = check_output_path(self.io_dict["out"]["output_pdb_path"], "output_pdb_path", False, out_log, self.__class__.__name__) 

118 self.io_dict["out"]["output_top_path"] = check_output_path(self.io_dict["out"]["output_top_path"], "output_top_path", False, out_log, self.__class__.__name__) 

119 self.io_dict["out"]["output_crd_path"] = check_output_path(self.io_dict["out"]["output_crd_path"], "output_crd_path", False, out_log, self.__class__.__name__) 

120 

121 @launchlogger 

122 def launch(self): 

123 """Launches the execution of the LeapGenTop module.""" 

124 

125 # check input/output paths and parameters 

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

127 

128 # Setup Biobb 

129 if self.check_restart(): 

130 return 0 

131 self.stage_files() 

132 

133 # Creating temporary folder & Leap configuration (instructions) file 

134 if self.container_path: 

135 instructions_file = str(PurePath(self.stage_io_dict['unique_dir']).joinpath("leap.in")) 

136 instructions_file_path = str(PurePath(self.container_volume_path).joinpath("leap.in")) 

137 self.tmp_folder = None 

138 else: 

139 self.tmp_folder = fu.create_unique_dir() 

140 instructions_file = str(PurePath(self.tmp_folder).joinpath("leap.in")) 

141 fu.log('Creating %s temporary folder' % self.tmp_folder, self.out_log) 

142 instructions_file_path = instructions_file 

143 

144 ligands_lib_list = [] 

145 if self.io_dict['in']['input_lib_path'] is not None: 

146 if self.io_dict['in']['input_lib_path'].endswith('.zip'): 

147 ligands_lib_list = fu.unzip_list(self.stage_io_dict['in']['input_lib_path'], dest_dir=self.tmp_folder, out_log=self.out_log) 

148 else: 

149 ligands_lib_list.append(self.stage_io_dict['in']['input_lib_path']) 

150 

151 ligands_frcmod_list = [] 

152 if self.io_dict['in']['input_frcmod_path'] is not None: 

153 if self.io_dict['in']['input_frcmod_path'].endswith('.zip'): 

154 ligands_frcmod_list = fu.unzip_list(self.stage_io_dict['in']['input_frcmod_path'], dest_dir=self.tmp_folder, out_log=self.out_log) 

155 else: 

156 ligands_frcmod_list.append(self.stage_io_dict['in']['input_frcmod_path']) 

157 

158 amber_params_list = [] 

159 if self.io_dict['in']['input_params_path'] is not None: 

160 if self.io_dict['in']['input_params_path'].endswith('.zip'): 

161 amber_params_list = fu.unzip_list(self.stage_io_dict['in']['input_params_path'], dest_dir=self.tmp_folder, out_log=self.out_log) 

162 else: 

163 amber_params_list.append(self.stage_io_dict['in']['input_params_path']) 

164 

165 leap_source_list = [] 

166 if self.io_dict['in']['input_source_path'] is not None: 

167 if self.io_dict['in']['input_source_path'].endswith('.zip'): 

168 leap_source_list = fu.unzip_list(self.stage_io_dict['in']['input_source_path'], dest_dir=self.tmp_folder, out_log=self.out_log) 

169 else: 

170 leap_source_list.append(self.stage_io_dict['in']['input_source_path']) 

171 

172 with open(instructions_file, 'w') as leapin: 

173 # Forcefields loaded by default: 

174 # Protein: ff14SB (PARM99 + frcmod.ff99SB + frcmod.parmbsc0 + OL3 for RNA) 

175 # leapin.write("source leaprc.protein.ff14SB \n") 

176 # DNA: parmBSC1 (ParmBSC1 (ff99 + bsc0 + bsc1) for DNA. Ivani et al. Nature Methods 13: 55, 2016) 

177 # leapin.write("source leaprc.DNA.bsc1 \n") 

178 # Ligands: GAFF (General Amber Force field, J. Comput. Chem. 2004 Jul 15;25(9):1157-74) 

179 # leapin.write("source leaprc.gaff \n") 

180 

181 # Forcefields loaded from input forcefield property 

182 for t in self.forcefield: 

183 leapin.write("source leaprc.{}\n".format(t)) 

184 

185 # Additional Leap commands 

186 for leap_commands in leap_source_list: 

187 leapin.write("source " + leap_commands + "\n") 

188 

189 # Additional Amber parameters 

190 for amber_params in amber_params_list: 

191 leapin.write("loadamberparams " + amber_params + "\n") 

192 

193 # Ions libraries 

194 leapin.write("loadOff atomic_ions.lib \n") 

195 

196 # Ligand(s) libraries (if any) 

197 for amber_lib in ligands_lib_list: 

198 leapin.write("loadOff " + amber_lib + "\n") 

199 for amber_frcmod in ligands_frcmod_list: 

200 leapin.write("loadamberparams " + amber_frcmod + "\n") 

201 

202 # Loading PDB file 

203 leapin.write("mol = loadpdb " + self.stage_io_dict['in']['input_pdb_path'] + " \n") 

204 

205 # Saving output PDB file, coordinates and topology 

206 leapin.write("savepdb mol " + self.stage_io_dict['out']['output_pdb_path'] + " \n") 

207 leapin.write("saveAmberParm mol " + self.stage_io_dict['out']['output_top_path'] + " " + self.stage_io_dict['out']['output_crd_path'] + "\n") 

208 leapin.write("quit \n") 

209 

210 # Command line 

211 self.cmd = [self.binary_path, 

212 '-f', instructions_file_path 

213 ] 

214 

215 # Run Biobb block 

216 self.run_biobb() 

217 

218 # Copy files to host 

219 self.copy_to_host() 

220 

221 # remove temporary folder(s) 

222 self.tmp_files.extend([ 

223 self.stage_io_dict.get("unique_dir"), 

224 self.tmp_folder, 

225 "leap.log" 

226 ]) 

227 self.remove_tmp_files() 

228 

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

230 

231 return self.return_code 

232 

233 

234def leap_gen_top(input_pdb_path: str, output_pdb_path: str, 

235 output_top_path: str, output_crd_path: str, 

236 input_lib_path: str = None, input_frcmod_path: str = None, 

237 input_params_path: str = None, input_source_path: str = None, 

238 properties: dict = None, **kwargs) -> int: 

239 """Create :class:`LeapGenTop <leap.leap_gen_top.LeapGenTop>`leap.leap_gen_top.LeapGenTop class and 

240 execute :meth:`launch() <leap.leap_gen_top.LeapGenTop.launch>` method""" 

241 

242 return LeapGenTop(input_pdb_path=input_pdb_path, 

243 input_lib_path=input_lib_path, 

244 input_frcmod_path=input_frcmod_path, 

245 input_params_path=input_params_path, 

246 input_source_path=input_source_path, 

247 output_pdb_path=output_pdb_path, 

248 output_top_path=output_top_path, 

249 output_crd_path=output_crd_path, 

250 properties=properties).launch() 

251 

252 

253def main(): 

254 parser = argparse.ArgumentParser(description='Generating a MD topology from a molecule structure using tLeap program from AmberTools MD package.', formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, width=99999)) 

255 parser.add_argument('--config', required=False, help='Configuration file') 

256 

257 # Specific args 

258 required_args = parser.add_argument_group('required arguments') 

259 required_args.add_argument('--input_pdb_path', required=True, help='Input 3D structure PDB file. Accepted formats: pdb.') 

260 required_args.add_argument('--input_lib_path', required=False, help='Input ligand library parameters file. Accepted formats: lib, zip.') 

261 required_args.add_argument('--input_frcmod_path', required=False, help='Input ligand frcmod parameters file. Accepted formats: frcmod, zip.') 

262 required_args.add_argument('--input_params_path', required=False, help='Additional leap parameter files to load with loadAmberParams Leap command. Accepted formats: leapin, in, txt, zip.') 

263 required_args.add_argument('--input_source_path', required=False, help='Additional leap command files to load with source Leap command. Accepted formats: leapin, in, txt, zip.') 

264 required_args.add_argument('--output_pdb_path', required=True, help='Output 3D structure PDB file matching the topology file. Accepted formats: pdb.') 

265 required_args.add_argument('--output_top_path', required=True, help='Output topology file (AMBER ParmTop). Accepted formats: top.') 

266 required_args.add_argument('--output_crd_path', required=True, help='Output coordinates file (AMBER crd). Accepted formats: crd.') 

267 

268 args = parser.parse_args() 

269 config = args.config if args.config else None 

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

271 

272 # Specific call 

273 leap_gen_top(input_pdb_path=args.input_pdb_path, 

274 input_lib_path=args.input_lib_path, 

275 input_frcmod_path=args.input_frcmod_path, 

276 input_params_path=args.input_params_path, 

277 input_source_path=args.input_source_path, 

278 output_pdb_path=args.output_pdb_path, 

279 output_top_path=args.output_top_path, 

280 output_crd_path=args.output_crd_path, 

281 properties=properties) 

282 

283 

284if __name__ == '__main__': 

285 main()