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
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-16 13:07 +0000
1#!/usr/bin/env python3
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
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.
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.
49 Examples:
50 This is a use example of how to use the building block from Python::
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)
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
73 """
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:
78 properties = properties or {}
80 # Call parent class constructor
81 super().__init__(properties)
82 self.locals_var_dict = locals().copy()
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 }
93 # Properties specific for BB
94 self.properties = properties
95 self.binary_path = properties.get('binary_path', 'disco')
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')
115 # Check the properties
116 self.check_properties(properties)
117 self.check_arguments()
119 @launchlogger
120 def launch(self):
121 """Launches the execution of the FlexDyn ConcoordDisco module."""
123 # Setup Biobb
124 if self.check_restart():
125 return 0
126 self.stage_files()
128 # Copy auxiliary files (MARGINS, ATOMS, BONDS) according to the VdW property to the working dir
129 concoord_lib = os.getenv("CONCOORDLIB")
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", ""))
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 ]
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)
176 # Properties
177 if self.num_structs:
178 self.cmd.append('-n')
179 self.cmd.append(str(self.num_structs))
181 if self.num_iterations:
182 self.cmd.append('-i')
183 self.cmd.append(str(self.num_iterations))
185 if self.chirality_check:
186 self.cmd.append('-c')
187 self.cmd.append(str(self.chirality_check))
189 if self.bs:
190 self.cmd.append('-bs')
191 self.cmd.append(str(self.bs))
193 if self.cutoff:
194 self.cmd.append('-rc')
195 self.cmd.append(str(self.cutoff))
197 if self.seed:
198 self.cmd.append('-s')
199 self.cmd.append(str(self.seed))
201 if self.damp:
202 self.cmd.append('-damp')
203 self.cmd.append(str(self.damp))
205 if self.violation:
206 self.cmd.append('-viol')
207 self.cmd.append(str(self.violation))
209 if self.convergence:
210 self.cmd.append('-con')
211 self.cmd.append(str(self.convergence))
213 if self.trials:
214 self.cmd.append('-t')
215 self.cmd.append(str(self.trials))
217 if self.dyn:
218 self.cmd.append('-dyn')
219 self.cmd.append(str(self.dyn))
221 if self.pairlist_freq:
222 self.cmd.append('-l')
223 self.cmd.append(str(self.pairlist_freq))
225 if self.scale:
226 self.cmd.append('-is')
227 self.cmd.append(str(self.scale))
229 if self.nofit:
230 self.cmd.append('-f')
232 if self.bump:
233 self.cmd.append('-bump')
235 if self.ref:
236 self.cmd.append('-ref')
238 # Run Biobb block
239 self.run_biobb()
241 # Copy files to host
242 self.copy_to_host()
244 # remove temporary folder(s)
245 self.remove_tmp_files()
247 self.check_arguments(output_files_created=True, raise_exception=False)
249 return self.return_code
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()
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.")
263if __name__ == '__main__':
264 main()