Coverage for biobb_structure_utils/utils/extract_model.py: 76%
74 statements
« prev ^ index » next coverage.py v7.6.10, created at 2025-01-28 11:54 +0000
« prev ^ index » next coverage.py v7.6.10, created at 2025-01-28 11:54 +0000
1#!/usr/bin/env python3
3"""Module containing the ExtractModel class and the command line interface."""
5import argparse
6import shutil
7from typing import Optional
9from biobb_common.configuration import settings
10from biobb_common.generic.biobb_object import BiobbObject
11from biobb_common.tools import file_utils as fu
12from biobb_common.tools.file_utils import launchlogger
14from biobb_structure_utils.utils.common import check_input_path, check_output_path
17class ExtractModel(BiobbObject):
18 """
19 | biobb_structure_utils ExtractModel
20 | This class is a wrapper of the Structure Checking tool to extract a model from a 3D structure.
21 | Wrapper for the `Structure Checking <https://github.com/bioexcel/biobb_structure_checking>`_ tool to extract a model from a 3D structure.
23 Args:
24 input_structure_path (str): Input structure file path. File type: input. `Sample file <https://github.com/bioexcel/biobb_structure_utils/raw/master/biobb_structure_utils/test/data/utils/extract_model.pdb>`_. Accepted formats: pdb (edam:format_1476), pdbqt (edam:format_1476).
25 output_structure_path (str): Output structure file path. File type: output. `Sample file <https://github.com/bioexcel/biobb_structure_utils/raw/master/biobb_structure_utils/test/reference/utils/ref_extract_model.pdb>`_. Accepted formats: pdb (edam:format_1476), pdbqt (edam:format_1476).
26 properties (dic - Python dictionary object containing the tool parameters, not input/output files):
27 * **models** (*list*) - (None) List of models to be extracted from the input_structure_path file. If empty, all the models of the structure will be returned.
28 * **binary_path** (*string*) - ("check_structure") path to the check_structure application
29 * **remove_tmp** (*bool*) - (True) [WF property] Remove temporal files.
30 * **restart** (*bool*) - (False) [WF property] Do not execute if output files exist.
31 * **sandbox_path** (*str*) - ("./") [WF property] Parent path to the sandbox directory.
33 Examples:
34 This is a use example of how to use the building block from Python::
36 from biobb_structure_utils.utils.extract_model import extract_model
37 prop = {
38 'models': [ 1, 2, 3 ]
39 }
40 extract_model(input_structure_path='/path/to/myStructure.pdb',
41 output_structure_path='/path/to/newStructure.pdb',
42 properties=prop)
44 Info:
45 * wrapped_software:
46 * name: Structure Checking from MDWeb
47 * version: >=3.0.3
48 * license: Apache-2.0
49 * ontology:
50 * name: EDAM
51 * schema: http://edamontology.org/EDAM.owl
53 """
55 def __init__(
56 self, input_structure_path, output_structure_path, properties=None, **kwargs
57 ) -> None:
58 properties = properties or {}
60 # Call parent class constructor
61 super().__init__(properties)
62 self.locals_var_dict = locals().copy()
64 # Input/Output files
65 self.io_dict = {
66 "in": {"input_structure_path": input_structure_path},
67 "out": {"output_structure_path": output_structure_path},
68 }
70 # Properties specific for BB
71 self.binary_path = properties.get("binary_path", "check_structure")
72 self.models = properties.get("models", [])
73 self.properties = properties
75 # Check the properties
76 self.check_properties(properties)
77 self.check_arguments()
79 @launchlogger
80 def launch(self) -> int:
81 """Execute the :class:`ExtractModel <utils.extract_model.ExtractModel>` utils.extract_model.ExtractModel object."""
83 self.io_dict["in"]["input_structure_path"] = check_input_path(
84 self.io_dict["in"]["input_structure_path"],
85 self.out_log,
86 self.__class__.__name__,
87 )
88 self.io_dict["out"]["output_structure_path"] = check_output_path(
89 self.io_dict["out"]["output_structure_path"],
90 self.out_log,
91 self.__class__.__name__,
92 )
94 # Setup Biobb
95 if self.check_restart():
96 return 0
97 self.stage_files()
99 # check if user has passed models properly
100 models = check_format_models(self.models, self.out_log)
102 if models == "All":
103 shutil.copyfile(
104 self.io_dict["in"]["input_structure_path"],
105 self.io_dict["out"]["output_structure_path"],
106 )
108 return 0
109 else:
110 # create temporary folder
111 tmp_folder = fu.create_unique_dir()
112 fu.log("Creating %s temporary folder" % tmp_folder, self.out_log)
114 filenames = []
116 for model in models:
117 tmp_file = tmp_folder + "/model" + str(model) + ".pdb"
119 self.cmd = [
120 self.binary_path,
121 "-i",
122 self.stage_io_dict["in"]["input_structure_path"],
123 "-o",
124 tmp_file,
125 "--force_save",
126 "models",
127 "--select",
128 str(model),
129 ]
131 # Run Biobb block
132 self.run_biobb()
134 filenames.append(tmp_file)
136 # concat tmp_file and save them into output file
137 with open(self.io_dict["out"]["output_structure_path"], "w") as outfile:
138 for i, fname in enumerate(filenames):
139 with open(fname) as infile:
140 outfile.write("MODEL " + "{:>4}".format(str(i + 1)) + "\n")
141 for line in infile:
142 if not line.startswith("END"):
143 outfile.write(line)
144 else:
145 outfile.write("ENDMDL\n")
147 # Copy files to host
148 self.copy_to_host()
150 # Remove temporal files
151 self.tmp_files.extend([
152 # self.stage_io_dict.get("unique_dir", ""),
153 tmp_folder
154 ])
155 self.remove_tmp_files()
157 self.check_arguments(output_files_created=True, raise_exception=False)
159 return self.return_code
162def check_format_models(models, out_log):
163 """Check format of models list"""
164 if not models:
165 fu.log("Empty models parameter, all models will be returned.", out_log)
166 return "All"
168 if not isinstance(models, list):
169 fu.log(
170 "Incorrect format of models parameter, all models will be returned.",
171 out_log,
172 )
173 return "All"
175 return models
178def extract_model(
179 input_structure_path: str,
180 output_structure_path: str,
181 properties: Optional[dict] = None,
182 **kwargs,
183) -> int:
184 """Execute the :class:`ExtractModel <utils.extract_model.ExtractModel>` class and
185 execute the :meth:`launch() <utils.extract_model.ExtractModel.launch>` method."""
187 return ExtractModel(
188 input_structure_path=input_structure_path,
189 output_structure_path=output_structure_path,
190 properties=properties,
191 **kwargs,
192 ).launch()
194 extract_model.__doc__ = ExtractModel.__doc__
197def main():
198 """Command line execution of this building block. Please check the command line documentation."""
199 parser = argparse.ArgumentParser(
200 description="Extract a model from a 3D structure.",
201 formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, width=99999),
202 )
203 parser.add_argument(
204 "-c",
205 "--config",
206 required=False,
207 help="This file can be a YAML file, JSON file or JSON string",
208 )
210 # Specific args of each building block
211 required_args = parser.add_argument_group("required arguments")
212 required_args.add_argument(
213 "-i",
214 "--input_structure_path",
215 required=True,
216 help="Input structure file path. Accepted formats: pdb.",
217 )
218 required_args.add_argument(
219 "-o",
220 "--output_structure_path",
221 required=True,
222 help="Output structure file path. Accepted formats: pdb.",
223 )
225 args = parser.parse_args()
226 config = args.config if args.config else None
227 properties = settings.ConfReader(config=config).get_prop_dic()
229 # Specific call of each building block
230 extract_model(
231 input_structure_path=args.input_structure_path,
232 output_structure_path=args.output_structure_path,
233 properties=properties,
234 )
237if __name__ == "__main__":
238 main()