Coverage for biobb_flexdyn / flexdyn / concoord_disco.py: 69%

119 statements  

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

1#!/usr/bin/env python3 

2 

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

4from typing import Optional 

5import os 

6import shutil 

7from pathlib import Path 

8from biobb_common.tools import file_utils as fu 

9from biobb_common.generic.biobb_object import BiobbObject 

10from biobb_common.tools.file_utils import launchlogger 

11 

12 

13class ConcoordDisco(BiobbObject): 

14 """ 

15 | biobb_flexdyn ConcoordDisco 

16 | Wrapper of the Disco tool from the Concoord package. 

17 | Structure generation based on a set of geometric constraints extracted with the Concoord Dist tool. 

18 

19 Args: 

20 input_pdb_path (str): Input structure file in PDB format. File type: input. `Sample file <https://github.com/bioexcel/biobb_flexdyn/raw/master/biobb_flexdyn/test/data/flexdyn/structure.pdb>`_. Accepted formats: pdb (edam:format_1476). 

21 input_dat_path (str): Input dat with structure interpretation and bond definitions. File type: input. `Sample file <https://github.com/bioexcel/biobb_flexdyn/raw/master/biobb_flexdyn/test/data/flexdyn/dist.dat>`_. Accepted formats: dat (edam:format_1637), txt (edam:format_2330). 

22 output_traj_path (str): Output trajectory file. File type: output. `Sample file <https://github.com/bioexcel/biobb_flexdyn/raw/master/biobb_flexdyn/test/reference/flexdyn/disco_trj.pdb>`_. Accepted formats: pdb (edam:format_1476), xtc (edam:format_3875), gro (edam:format_2033). 

23 output_rmsd_path (str): Output rmsd file. File type: output. `Sample file <https://github.com/bioexcel/biobb_flexdyn/raw/master/biobb_flexdyn/test/reference/flexdyn/disco_rmsd.dat>`_. Accepted formats: dat (edam:format_1637). 

24 output_bfactor_path (str): Output B-factor file. File type: output. `Sample file <https://github.com/bioexcel/biobb_flexdyn/raw/master/biobb_flexdyn/test/reference/flexdyn/disco_bfactor.pdb>`_. Accepted formats: pdb (edam:format_1476). 

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

26 * **binary_path** (*str*) - ("disco") Concoord disco binary path to be used. 

27 * **vdw** (*int*) - (1) Select a set of Van der Waals parameters. Values: 1 (OPLS-UA -united atoms- parameters), 2 (OPLS-AA -all atoms- parameters), 3 (PROLSQ repel parameters), 4 (Yamber2 parameters), 5 (Li et al. parameters), 6 (OPLS-X parameters -recommended for NMR structure determination-) 

28 * **num_structs** (*int*) - (500) Number of structures to be generated 

29 * **num_iterations** (*int*) - (2500) Maximum number of iterations per structure 

30 * **chirality_check** (*int*) - (2) Chirality check. Values: 0 (no chirality checks), 1 (only check afterwards), 2 (check on the fly) 

31 * **bs** (*int*) - (0) Number of rounds of triangular bound smoothing (default 0), (if >= 6, tetragonal BS is activated) 

32 * **nofit** (*bool*) - (False) Do not fit generated structures to reference 

33 * **seed** (*int*) - (741265) Initial random seed 

34 * **violation** (*float*) - (1.0) Maximal acceptable sum of violations (nm) 

35 * **nofit** (*bool*) - (False) Do not fit generated structures to reference 

36 * **convergence** (*int*) - (50) Consider convergence failed after this number of non-productive iterations 

37 * **trials** (*int*) - (25) Maximum number of trials per run 

38 * **damp** (*int*) - (1) Damping factor for distance corrections. Values: 1 (default), 2 (for cases with convergence problems) 

39 * **dyn** (*int*) - (1) Number of rounds to dynamically set tolerances 

40 * **bump** (*bool*) - (False) Do extra bump check 

41 * **pairlist_freq** (*int*) - (10) Pairlist update frequency in steps (only valid together with bump) 

42 * **cutoff** (*float*) - (0.5) Cut-off radius for pairlist (nm) (only valid together with bump) 

43 * **ref** (*bool*) - (False) Use input coordinates instead of random starting coordinates 

44 * **scale** (*int*) - (1) Pre-scale coordinates with this factor 

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

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

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

48 

49 Examples: 

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

51 

52 from biobb_flexdyn.flexdyn.concoord_disco import concoord_disco 

53 prop = { 

54 'vdw' : 4, 

55 'num_structs' : 20 

56 } 

57 concoord_disco( input_pdb_path='/path/to/dist_input.pdb', 

58 input_dat_path='/path/to/dist_input.dat', 

59 output_traj_path='/path/to/disco_out_traj.pdb', 

60 output_rmsd_path='/path/to/disco_out_rmsd.dat', 

61 output_bfactor_path='/path/to/disco_out_bfactor.pdb', 

62 properties=prop) 

63 

64 Info: 

65 * wrapped_software: 

66 * name: Concoord 

67 * version: >=2.1.2 

68 * license: other 

69 * ontology: 

70 * name: EDAM 

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

72 

73 """ 

74 

75 def __init__(self, input_pdb_path: str, input_dat_path: str, output_traj_path: str, 

76 output_rmsd_path: str, output_bfactor_path: str, properties: Optional[dict] = None, **kwargs) -> None: 

77 

78 properties = properties or {} 

79 

80 # Call parent class constructor 

81 super().__init__(properties) 

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

83 

84 # Input/Output files 

85 self.io_dict = { 

86 'in': {'input_pdb_path': input_pdb_path, 

87 'input_dat_path': input_dat_path}, 

88 'out': {'output_traj_path': output_traj_path, 

89 'output_rmsd_path': output_rmsd_path, 

90 'output_bfactor_path': output_bfactor_path} 

91 } 

92 

93 # Properties specific for BB 

94 self.properties = properties 

95 self.binary_path = properties.get('binary_path', 'disco') 

96 

97 self.vdw = properties.get('vdw') 

98 self.num_structs = properties.get('num_structs') 

99 self.num_iterations = properties.get('num_iterations') 

100 self.chirality_check = properties.get('chirality_check') 

101 self.bs = properties.get('bs') 

102 self.nofit = properties.get('nofit') 

103 self.seed = properties.get('seed') 

104 self.violation = properties.get('violation') 

105 self.convergence = properties.get('convergence') 

106 self.trials = properties.get('trials') 

107 self.damp = properties.get('damp') 

108 self.dyn = properties.get('dyn') 

109 self.bump = properties.get('bump') 

110 self.pairlist_freq = properties.get('pairlist_freq') 

111 self.cutoff = properties.get('cutoff') 

112 self.ref = properties.get('ref') 

113 self.scale = properties.get('scale') 

114 

115 # Check the properties 

116 self.check_properties(properties) 

117 self.check_arguments() 

118 

119 @launchlogger 

120 def launch(self): 

121 """Launches the execution of the FlexDyn ConcoordDisco module.""" 

122 

123 # Setup Biobb 

124 if self.check_restart(): 

125 return 0 

126 self.stage_files() 

127 

128 # Copy auxiliary files (MARGINS, ATOMS, BONDS) according to the VdW property to the working dir 

129 concoord_lib = os.getenv("CONCOORDLIB") 

130 

131 # MARGINS_li.DAT, MARGINS_oplsaa.DAT, MARGINS_oplsua.DAT, MARGINS_oplsx.DAT, MARGINS_repel.DAT, MARGINS_yamber2.DAT 

132 # 1 (OPLS-UA -united atoms- parameters), 2 (OPLS-AA -all atoms- parameters), 3 (PROLSQ repel parameters), 4 (Yamber2 parameters), 5 (Li et al. parameters), 6 (OPLS-X parameters -recommended for NMR structure determination-). 

133 vdw_values = ["vdw_values", "oplsua", "oplsaa", "repel", "yamber2", "li", "oplsx"] 

134 if self.vdw is None: 

135 raise ValueError("The 'vdw' property cannot be None") 

136 vdw_index = int(self.vdw) 

137 margins_file = str(concoord_lib) + "/MARGINS_" + vdw_values[vdw_index] + ".DAT" 

138 atoms_file = str(concoord_lib) + "/ATOMS_" + vdw_values[vdw_index] + ".DAT" 

139 bonds_file = str(concoord_lib) + "/BONDS.DAT" 

140 shutil.copy2(margins_file, self.stage_io_dict.get("unique_dir", "")) 

141 shutil.copy2(margins_file, self.stage_io_dict.get("unique_dir", "")+"/MARGINS.DAT") 

142 shutil.copy2(atoms_file, self.stage_io_dict.get("unique_dir", "")) 

143 shutil.copy2(bonds_file, self.stage_io_dict.get("unique_dir", "")) 

144 

145 # Command line 

146 # (concoord) OROZCO67:biobb_flexdyn hospital$ disco -d biobb_flexdyn/test/reference/flexdyn/dist.dat 

147 # -p biobb_flexdyn/test/reference/flexdyn/dist.pdb -op patata.pdb 

148 self.cmd = ["cd ", self.stage_io_dict.get('unique_dir', ''), ";", self.binary_path, 

149 # "-p", str(Path(self.stage_io_dict["in"]["input_pdb_path"]).relative_to(Path.cwd())), 

150 # "-d", str(Path(self.stage_io_dict["in"]["input_dat_path"]).relative_to(Path.cwd())), 

151 # "-or", str(Path(self.stage_io_dict["out"]["output_rmsd_path"]).relative_to(Path.cwd())), 

152 # "-of", str(Path(self.stage_io_dict["out"]["output_bfactor_path"]).relative_to(Path.cwd())) 

153 "-p", str(Path(self.stage_io_dict["in"]["input_pdb_path"]).relative_to(Path(self.stage_io_dict.get('unique_dir', '')))), 

154 "-d", str(Path(self.stage_io_dict["in"]["input_dat_path"]).relative_to(Path(self.stage_io_dict.get('unique_dir', '')))), 

155 "-or", str(Path(self.stage_io_dict["out"]["output_rmsd_path"]).relative_to(Path(self.stage_io_dict.get('unique_dir', '')))), 

156 "-of", str(Path(self.stage_io_dict["out"]["output_bfactor_path"]).relative_to(Path(self.stage_io_dict.get('unique_dir', '')))) 

157 ] 

158 

159 # Output structure formats: 

160 file_extension = Path(self.stage_io_dict["out"]["output_traj_path"]).suffix 

161 if file_extension == ".pdb": 

162 self.cmd.append('-on') # NMR-PDB format (multi-model) 

163# self.cmd.append(str(Path(self.stage_io_dict["out"]["output_traj_path"]).relative_to(Path.cwd()))) 

164 self.cmd.append(str(Path(self.stage_io_dict["out"]["output_traj_path"]).relative_to(Path(self.stage_io_dict.get('unique_dir', ''))))) 

165 elif file_extension == ".gro": 

166 self.cmd.append('-ot') 

167# self.cmd.append(str(Path(self.stage_io_dict["out"]["output_traj_path"]).relative_to(Path.cwd()))) 

168 self.cmd.append(str(Path(self.stage_io_dict["out"]["output_traj_path"]).relative_to(Path(self.stage_io_dict.get('unique_dir', ''))))) 

169 elif file_extension == ".xtc": 

170 self.cmd.append('-ox') 

171# self.cmd.append(str(Path(self.stage_io_dict["out"]["output_traj_path"]).relative_to(Path.cwd()))) 

172 self.cmd.append(str(Path(self.stage_io_dict["out"]["output_traj_path"]).relative_to(Path(self.stage_io_dict.get('unique_dir', ''))))) 

173 else: 

174 fu.log("ERROR: output_traj_path ({}) must be a PDB, GRO or XTC formatted file ({})".format(self.io_dict["out"]["output_traj_path"], file_extension), self.out_log, self.global_log) 

175 

176 # Properties 

177 if self.num_structs: 

178 self.cmd.append('-n') 

179 self.cmd.append(str(self.num_structs)) 

180 

181 if self.num_iterations: 

182 self.cmd.append('-i') 

183 self.cmd.append(str(self.num_iterations)) 

184 

185 if self.chirality_check: 

186 self.cmd.append('-c') 

187 self.cmd.append(str(self.chirality_check)) 

188 

189 if self.bs: 

190 self.cmd.append('-bs') 

191 self.cmd.append(str(self.bs)) 

192 

193 if self.cutoff: 

194 self.cmd.append('-rc') 

195 self.cmd.append(str(self.cutoff)) 

196 

197 if self.seed: 

198 self.cmd.append('-s') 

199 self.cmd.append(str(self.seed)) 

200 

201 if self.damp: 

202 self.cmd.append('-damp') 

203 self.cmd.append(str(self.damp)) 

204 

205 if self.violation: 

206 self.cmd.append('-viol') 

207 self.cmd.append(str(self.violation)) 

208 

209 if self.convergence: 

210 self.cmd.append('-con') 

211 self.cmd.append(str(self.convergence)) 

212 

213 if self.trials: 

214 self.cmd.append('-t') 

215 self.cmd.append(str(self.trials)) 

216 

217 if self.dyn: 

218 self.cmd.append('-dyn') 

219 self.cmd.append(str(self.dyn)) 

220 

221 if self.pairlist_freq: 

222 self.cmd.append('-l') 

223 self.cmd.append(str(self.pairlist_freq)) 

224 

225 if self.scale: 

226 self.cmd.append('-is') 

227 self.cmd.append(str(self.scale)) 

228 

229 if self.nofit: 

230 self.cmd.append('-f') 

231 

232 if self.bump: 

233 self.cmd.append('-bump') 

234 

235 if self.ref: 

236 self.cmd.append('-ref') 

237 

238 # Run Biobb block 

239 self.run_biobb() 

240 

241 # Copy files to host 

242 self.copy_to_host() 

243 

244 # remove temporary folder(s) 

245 self.remove_tmp_files() 

246 

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

248 

249 return self.return_code 

250 

251 

252def concoord_disco(input_pdb_path: str, input_dat_path: str, 

253 output_traj_path: str, output_rmsd_path: str, output_bfactor_path: str, 

254 properties: Optional[dict] = None, **kwargs) -> int: 

255 """Create :class:`ConcoordDisco <flexdyn.concoord_disco.ConcoordDisco>`flexdyn.concoord_disco.ConcoordDisco class and 

256 execute :meth:`launch() <flexdyn.concoord_disco.ConcoordDisco.launch>` method""" 

257 return ConcoordDisco(**dict(locals())).launch() 

258 

259 

260concoord_disco.__doc__ = ConcoordDisco.__doc__ 

261main = ConcoordDisco.get_main(concoord_disco, "Structure generation based on a set of geometric constraints extracted with the Concoord Dist tool.") 

262 

263if __name__ == '__main__': 

264 main()