Coverage for biobb_amber/leap/leap_add_ions.py: 59%

203 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 LeapAddIons class and the command line interface.""" 

4import argparse 

5import shutil 

6import re 

7from decimal import Decimal 

8from pathlib import PurePath 

9from biobb_common.generic.biobb_object import BiobbObject 

10from biobb_common.configuration import settings 

11from biobb_common.tools import file_utils as fu 

12from biobb_common.tools.file_utils import launchlogger 

13from biobb_amber.leap.common import check_input_path, check_output_path 

14 

15 

16class LeapAddIons(BiobbObject): 

17 """ 

18 | biobb_amber LeapAddIons 

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

20 | Adds counterions to a system box for an AMBER MD system using tLeap tool from the AmberTools MD package. 

21 

22 Args: 

23 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.solv.pdb>`_. Accepted formats: pdb (edam:format_1476). 

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

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

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

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

28 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.ions.pdb>`_. Accepted formats: pdb (edam:format_1476). 

29 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.ions.top>`_. Accepted formats: top (edam:format_3881), parmtop (edam:format_3881), prmtop (edam:format_3881). 

30 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.ions.crd>`_. Accepted formats: crd (edam:format_3878), mdcrd (edam:format_3878), inpcrd (edam:format_3878). 

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

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

33 * **water_type** (*str*) - ("TIP3PBOX") Water molecule parameters to be used for the topology. Values: POL3BOX, QSPCFWBOX, SPCBOX, SPCFWBOX, TIP3PBOX, TIP3PFBOX, TIP4PBOX, TIP4PEWBOX, OPCBOX, OPC3BOX, TIP5PBOX. 

34 * **box_type** (*str*) - ("truncated_octahedron") Type for the MD system box. Values: cubic, truncated_octahedron. 

35 * **ions_type** (*str*) - ("ionsjc_tip3p") Ions type. Values: ionsjc_tip3p, ionsjc_spce, ionsff99_tip3p, ions_charmm22, ionsjc_tip4pew, None. 

36 * **neutralise** (*bool*) - ("True") Energetically neutralise the system adding the necessary counterions. 

37 * **ionic_concentration** (*float*) - (50) Additional ionic concentration to include in the system box. Units in Mol/L. 

38 * **positive_ions_number** (*int*) - (0) Number of additional positive ions to include in the system box. 

39 * **negative_ions_number** (*int*) - (0) Number of additional negative ions to include in the system box. 

40 * **positive_ions_type** (*str*) - ("Na+") Type of additional positive ions to include in the system box. Values: Na+,K+. 

41 * **negative_ions_type** (*str*) - ("Cl-") Type of additional negative ions to include in the system box. Values: Cl-. 

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

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

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

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

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

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

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

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

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

51 

52 Examples: 

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

54 

55 from biobb_amber.leap.leap_add_ions import leap_add_ions 

56 prop = { 

57 'forcefield': ['protein.ff14SB'], 

58 'water_type': 'TIP3PBOX', 

59 'neutralise' : True 

60 } 

61 leap_add_ions(input_pdb_path='/path/to/structure.pdb', 

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

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

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

65 properties=prop) 

66 

67 Info: 

68 * wrapped_software: 

69 * name: AmberTools tLeap 

70 * version: >20.9 

71 * license: LGPL 2.1 

72 * ontology: 

73 * name: EDAM 

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

75 

76 """ 

77 

78 def __init__(self, input_pdb_path: str, 

79 output_pdb_path: str, output_top_path: str, output_crd_path: str, 

80 input_lib_path: str = None, input_frcmod_path: str = None, 

81 input_params_path: str = None, input_source_path: str = None, 

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

83 

84 properties = properties or {} 

85 

86 # Call parent class constructor 

87 super().__init__(properties) 

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

89 

90 # Input/Output files 

91 self.io_dict = { 

92 'in': {'input_pdb_path': input_pdb_path, 

93 'input_lib_path': input_lib_path, 

94 'input_frcmod_path': input_frcmod_path, 

95 'input_params_path': input_params_path, 

96 'input_source_path': input_source_path}, 

97 'out': {'output_pdb_path': output_pdb_path, 

98 'output_top_path': output_top_path, 

99 'output_crd_path': output_crd_path} 

100 } 

101 

102 # Ligand Parameter lists 

103 self.ligands_lib_list = [] 

104 if input_lib_path: 

105 self.ligands_lib_list.append(input_lib_path) 

106 

107 self.ligands_frcmod_list = [] 

108 if input_frcmod_path: 

109 self.ligands_frcmod_list.append(input_frcmod_path) 

110 

111 # Properties specific for BB 

112 self.properties = properties 

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

114 self.water_type = properties.get('water_type', "TIP3PBOX") 

115 self.box_type = properties.get('box_type', "truncated_octahedron") 

116 self.ions_type = properties.get('ions_type', "ionsjc_tip3p") 

117 self.neutralise = properties.get('neutralise', True) 

118 self.ionic_concentration = properties.get('ionic_concentration', 50) 

119 self.positive_ions_number = properties.get('positive_ions_number', 0) 

120 self.positive_ions_type = properties.get('positive_ions_type', "Na+") 

121 self.negative_ions_number = properties.get('negative_ions_number', 0) 

122 self.negative_ions_type = properties.get('negative_ions_type', "Cl-") 

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

124 

125 # Check the properties 

126 self.check_properties(properties) 

127 self.check_arguments() 

128 

129 def check_data_params(self, out_log, err_log): 

130 """ Checks input/output paths correctness """ 

131 

132 # Check input(s) 

133 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__) 

134 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__) 

135 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__) 

136 # 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__) 

137 # 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__) 

138 

139 # Check output(s) 

140 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__) 

141 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__) 

142 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__) 

143 

144 def find_out_number_of_ions(self): 

145 """ Computes the number of positive and negative ions from the input ionic 

146 concentration and the number of water molecules in the system box.""" 

147 

148 # Finding number of water molecules in the box 

149 cnt = 0 

150 with open(self.io_dict['in']['input_pdb_path']) as fp: 

151 for line in fp: 

152 # Water molecules are identified with different resids 

153 # by different forcefields / MD packages 

154 pq = re.compile((r'WAT|HOH|TP3|TIP3|SOL'), re.M) 

155 if pq.search(line): 

156 # Incrementing number of water molecules just in the water 

157 # oxygen atom, ignoring hydrogen atoms 

158 pq2 = re.compile(r"H", re.M) 

159 if not pq2.search(line): 

160 cnt = cnt + 1 

161 

162 # To get to X mM ions we need 

163 # n(NaCl) = #waters / 55 Mol * X M 

164 # where X M = X mM / 1000 

165 self.nio = int((cnt / 55) * (self.ionic_concentration / 1000)) 

166 

167 @launchlogger 

168 def launch(self): 

169 """Launches the execution of the LeapAddIons module.""" 

170 

171 # check input/output paths and parameters 

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

173 

174 # Setup Biobb 

175 if self.check_restart(): 

176 return 0 

177 self.stage_files() 

178 

179 # Water Type 

180 # leaprc.water.tip4pew, tip4pd, tip3p, spceb, spce, opc, fb4, fb3 

181 # Values: POL3BOX, QSPCFWBOX, SPCBOX, SPCFWBOX, TIP3PBOX, TIP3PFBOX, TIP4PBOX, TIP4PEWBOX, OPCBOX, OPC3BOX, TIP5PBOX. 

182 source_wat_command = "source leaprc.water.tip3p" 

183 if self.water_type == "TIP4PEWBOX": 

184 source_wat_command = "leaprc.water.tip4pew" 

185 if self.water_type == "TIP4PBOX": 

186 source_wat_command = "leaprc.water.tip4pd" 

187 if re.match(r"SPC", self.water_type): 

188 source_wat_command = "source leaprc.water.spce" 

189 if re.match(r"OPC", self.water_type): 

190 source_wat_command = "source leaprc.water.opc" 

191 

192 # Counterions 

193 ions_command = "" 

194 if self.neutralise: 

195 # ions_command = ions_command + "addions mol " + self.negative_ions_type + " 0 \n" 

196 # ions_command = ions_command + "addions mol " + self.positive_ions_type + " 0 \n" 

197 ions_command = ions_command + "addionsRand mol " + self.negative_ions_type + " 0 \n" 

198 ions_command = ions_command + "addionsRand mol " + self.positive_ions_type + " 0 \n" 

199 

200 if self.ionic_concentration and self.negative_ions_number == 0 and self.positive_ions_number == 0: 

201 self.find_out_number_of_ions() 

202 nneg = self.nio # Update with function 

203 npos = self.nio # Update with function 

204 # ions_command = ions_command + "addions mol " + self.negative_ions_type + " " + str(nneg) + " \n" 

205 # ions_command = ions_command + "addions mol " + self.positive_ions_type + " " + str(npos) + " \n" 

206 ions_command = ions_command + "addionsRand mol " + self.negative_ions_type + " " + str(nneg) + " \n" 

207 ions_command = ions_command + "addionsRand mol " + self.positive_ions_type + " " + str(npos) + " \n" 

208 else: 

209 if self.negative_ions_number != 0: 

210 # ions_command = ions_command + "addions mol " + self.negative_ions_type + " " + str(self.negative_ions_number) + " \n" 

211 ions_command = ions_command + "addionsRand mol " + self.negative_ions_type + " " + str(self.negative_ions_number) + " \n" 

212 if self.positive_ions_number != 0: 

213 # ions_command = ions_command + "addions mol " + self.positive_ions_type + " " + str(self.positive_ions_number) + " \n" 

214 ions_command = ions_command + "addionsRand mol " + self.positive_ions_type + " " + str(self.positive_ions_number) + " \n" 

215 

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

217 if self.container_path: 

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

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

220 self.tmp_folder = None 

221 else: 

222 self.tmp_folder = fu.create_unique_dir() 

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

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

225 instructions_file_path = instructions_file 

226 

227 ligands_lib_list = [] 

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

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

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

231 else: 

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

233 

234 ligands_frcmod_list = [] 

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

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

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

238 else: 

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

240 

241 amber_params_list = [] 

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

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

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

245 else: 

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

247 

248 leap_source_list = [] 

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

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

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

252 else: 

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

254 

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

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

257 # Forcefields loaded by default: 

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

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

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

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

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

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

264 

265 # Forcefields loaded from input forcefield property 

266 for t in self.forcefield: 

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

268 

269 # Additional Leap commands 

270 for leap_commands in leap_source_list: 

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

272 

273 # Water Model loaded from input water_model property 

274 leapin.write(source_wat_command + " \n") 

275 

276 # Ions Type 

277 if self.ions_type != "None": 

278 leapin.write("loadamberparams frcmod." + self.ions_type + "\n") 

279 

280 # Additional Amber parameters 

281 for amber_params in amber_params_list: 

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

283 

284 # Ligand(s) libraries (if any) 

285 for amber_lib in ligands_lib_list: 

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

287 for amber_frcmod in ligands_frcmod_list: 

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

289 

290 # Loading PDB file 

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

292 

293 # Adding ions 

294 leapin.write(ions_command) 

295 

296 # Generating box 

297 leapin.write("setBox mol vdw \n") 

298 

299 # Saving output PDB file, coordinates and topology 

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

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

302 leapin.write("quit \n") 

303 

304 # Command line 

305 self.cmd = [self.binary_path, 

306 '-f', instructions_file_path 

307 ] 

308 

309 # Run Biobb block 

310 self.run_biobb() 

311 

312 # Copy files to host 

313 self.copy_to_host() 

314 

315 if self.box_type != "cubic": 

316 fu.log('Fixing truncated octahedron Box in the topology and coordinates files', self.out_log, self.global_log) 

317 

318 # Taking box info from input PDB file, CRYST1 tag (first line) 

319 with open(self.io_dict['in']['input_pdb_path']) as file: 

320 lines = file.readlines() 

321 pdb_line = lines[0] 

322 

323 if 'OCTBOX' not in pdb_line: 

324 fu.log('WARNING: box info not found in input PDB file (OCTBOX). Needed to correctly assign the octahedron box. Assuming cubic box.', self.out_log, self.global_log) 

325 else: 

326 # PDB info: CRYST1 86.316 86.316 86.316 109.47 109.47 109.47 P 1 

327 # PDB info: OCTBOX 86.1942924 86.1942924 86.1942924 109.4712190 109.4712190 109.4712190 

328 # regex_box = 'CRYST1\s*(\d+\.\d+)\s*(\d+\.\d+)\s*(\d+\.\d+)\s*(\d+\.\d+)\s*(\d+\.\d+)\s*(\d+\.\d+)\s*P 1' 

329 regex_box = r'OCTBOX\s*(\d+\.\d+)\s*(\d+\.\d+)\s*(\d+\.\d+)\s*(\d+\.\d+)\s*(\d+\.\d+)\s*(\d+\.\d+)' 

330 box = re.findall(regex_box, pdb_line)[0] 

331 box_line = "" 

332 for coord in box: 

333 box_line += "{:12.7f}".format(float(coord)) 

334 

335 # PRMTOP info: 1.09471219E+02 8.63157502E+01 8.63157502E+01 8.63157502E+01 

336 top_box_line = "" 

337 top_box_line += ' %.8E' % Decimal(float(box[3])) 

338 top_box_line += ' %.8E' % Decimal(float(box[0])) 

339 top_box_line += ' %.8E' % Decimal(float(box[1])) 

340 top_box_line += ' %.8E' % Decimal(float(box[2])) 

341 

342 # Removing box generated by tleap from the crd file (last line) 

343 with open(self.io_dict['out']['output_crd_path']) as file: 

344 lines = file.readlines() 

345 crd_lines = lines[:-1] 

346 

347 # Adding old box coordinates (taken from the input pdb) 

348 crd_lines.append(box_line) 

349 

350 with open(self.io_dict['out']['output_crd_path'], 'w') as file: 

351 for line in crd_lines: 

352 file.write(str(line)) 

353 file.write("\n") 

354 

355 # Now fixing IFBOX param in prmtop. 

356 box_flag = False 

357 ifbox_flag = 0 

358 # %FLAG BOX_DIMENSIONS 

359 # %FORMAT(5E16.8) 

360 # 1.09471219E+02 8.63157502E+01 8.63157502E+01 8.63157502E+01 

361 

362 tmp_parmtop = str(PurePath(self.tmp_folder).joinpath("top_temp.parmtop")) 

363 shutil.copyfile(self.io_dict['out']['output_top_path'], tmp_parmtop) 

364 

365 with open(self.io_dict['out']['output_top_path'], 'w') as new_top: 

366 with open(tmp_parmtop, 'r') as old_top: 

367 for line in old_top: 

368 if 'BOX_DIMENSIONS' in line: 

369 box_flag = True 

370 new_top.write(line) 

371 elif box_flag and 'FORMAT' not in line: 

372 new_top.write(top_box_line + "\n") 

373 box_flag = False 

374 elif 'FLAG POINTERS' in line or ifbox_flag == 1 or ifbox_flag == 2 or ifbox_flag == 3: 

375 ifbox_flag += 1 

376 new_top.write(line) 

377 elif ifbox_flag == 4: 

378 # new_top.write(top_box_line + "\n") 

379 new_top.write(line[:56] + ' 2' + line[64:]) 

380 ifbox_flag += 1 

381 else: 

382 new_top.write(line) 

383 

384 # remove temporary folder(s) 

385 self.tmp_files.extend([ 

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

387 self.tmp_folder, 

388 "leap.log" 

389 ]) 

390 self.remove_tmp_files() 

391 

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

393 

394 return self.return_code 

395 

396 

397def leap_add_ions(input_pdb_path: str, output_pdb_path: str, 

398 output_top_path: str, output_crd_path: str, 

399 input_lib_path: str = None, input_frcmod_path: str = None, 

400 input_params_path: str = None, input_source_path: str = None, 

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

402 """Create :class:`LeapAddIons <leap.leap_add_ions.LeapAddIons>`leap.leap_add_ions.LeapAddIons class and 

403 execute :meth:`launch() <leap.leap_add_ions.LeapAddIons.launch>` method""" 

404 

405 return LeapAddIons(input_pdb_path=input_pdb_path, 

406 input_lib_path=input_lib_path, 

407 input_frcmod_path=input_frcmod_path, 

408 input_params_path=input_params_path, 

409 input_source_path=input_source_path, 

410 output_pdb_path=output_pdb_path, 

411 output_top_path=output_top_path, 

412 output_crd_path=output_crd_path, 

413 properties=properties).launch() 

414 

415 

416def main(): 

417 parser = argparse.ArgumentParser(description='Adds counterions to a system box for an AMBER MD system using tLeap.', formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, width=99999)) 

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

419 

420 # Specific args 

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

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

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

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

425 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.') 

426 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.') 

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

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

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

430 

431 args = parser.parse_args() 

432 config = args.config if args.config else None 

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

434 

435 # Specific call 

436 leap_add_ions(input_pdb_path=args.input_pdb_path, 

437 input_lib_path=args.input_lib_path, 

438 input_frcmod_path=args.input_frcmod_path, 

439 input_params_path=args.input_params_path, 

440 input_source_path=args.input_source_path, 

441 output_pdb_path=args.output_pdb_path, 

442 output_top_path=args.output_top_path, 

443 output_crd_path=args.output_crd_path, 

444 properties=properties) 

445 

446 

447if __name__ == '__main__': 

448 main()