Coverage for biobb_pmx/pmxbiobb/pmxmutate.py: 72%
75 statements
« prev ^ index » next coverage.py v7.6.10, created at 2025-01-23 10:10 +0000
« prev ^ index » next coverage.py v7.6.10, created at 2025-01-23 10:10 +0000
1#!/usr/bin/env python3
3"""Module containing the PMX mutate class and the command line interface."""
5import argparse
6import os
7import shutil
8import sys
9from pathlib import Path
10from typing import Optional
12from biobb_common.configuration import settings
13from biobb_common.generic.biobb_object import BiobbObject
14from biobb_common.tools import file_utils as fu
15from biobb_common.tools.file_utils import launchlogger
17from biobb_pmx.pmxbiobb.common import MUTATION_DICT, create_mutations_file
20class Pmxmutate(BiobbObject):
21 """
22 | biobb_pmx Pmxmutate
23 | Wrapper class for the `PMX mutate <https://github.com/deGrootLab/pmx>`_ module.
24 | Mutate residues in a protein structure.
26 Args:
27 input_structure_path (str): Path to the input structure file. File type: input. `Sample file <https://github.com/bioexcel/biobb_pmx/raw/master/biobb_pmx/test/data/pmx/frame99.pdb>`_. Accepted formats: pdb (edam:format_1476), gro (edam:format_2033).
28 output_structure_path (str): Path to the output structure file. File type: output. `Sample file <https://github.com/bioexcel/biobb_pmx/raw/master/biobb_pmx/test/reference/pmx/ref_output_structure.pdb>`_. Accepted formats: pdb (edam:format_1476), gro (edam:format_2033).
29 input_b_structure_path (str) (Optional): Path to the mutated input structure file. File type: input. Accepted formats: pdb (edam:format_1476), gro (edam:format_2033).
30 properties (dic):
31 * **mutation_list** (*str*) - ("2Ala") Mutation list in the format "Chain:Resnum MUT_AA_Code" or "Chain:Resnum MUT_NA_Code" (no spaces between the elements) separated by commas. If no chain is provided as chain code all the chains in the pdb file will be mutated. ie: "A:15CYS". Possible MUT_AA_Code: 'ALA', 'ARG', 'ASN', 'ASP', 'ASPH', 'ASPP', 'ASH', 'CYS', 'CYS2', 'CYN', 'CYX', 'CYM', 'CYSH', 'GLU', 'GLUH', 'GLUP', 'GLH', 'GLN', 'GLY', 'HIS', 'HIE', 'HISE', 'HSE', 'HIP', 'HSP', 'HISH', 'HID', 'HSD', 'ILE', 'LEU', 'LYS', 'LYSH', 'LYP', 'LYN', 'LSN', 'MET', 'PHE', 'PRO', 'SER', 'SP1', 'SP2', 'THR', 'TRP', 'TYR', 'VAL'. Possible MUT_NA_Codes: 'A', 'T', 'C', 'G', 'U'.
32 * **force_field** (*str*) - ("amber99sb-star-ildn-mut") Forcefield to use.
33 * **resinfo** (*bool*) - (False) Show the list of 3-letter -> 1-letter residues.
34 * **gmx_lib** (*str*) - ("$CONDA_PREFIX/lib/python3.7/site-packages/pmx/data/mutff/") Path to the GMXLIB folder in your computer.
35 * **binary_path** (*str*) - ("pmx") Path to the PMX command line interface.
36 * **remove_tmp** (*bool*) - (True) [WF property] Remove temporal files.
37 * **restart** (*bool*) - (False) [WF property] Do not execute if output files exist.
38 * **sandbox_path** (*str*) - ("./") [WF property] Parent path to the sandbox directory.
39 * **container_path** (*str*) - (None) Path to the binary executable of your container.
40 * **container_image** (*str*) - (None) Container Image identifier.
41 * **container_volume_path** (*str*) - ("/inout") Path to an internal directory in the container.
42 * **container_working_dir** (*str*) - (None) Path to the internal CWD in the container.
43 * **container_user_id** (*str*) - (None) User number id to be mapped inside the container.
44 * **container_shell_path** (*str*) - ("/bin/bash") Path to the binary executable of the container shell.
46 Examples:
47 This is a use example of how to use the building block from Python::
49 from biobb_pmx.pmxbiobb.pmxmutate import pmxmutate
50 prop = {
51 'mutation_list': '2Ala, 3Val',
52 'gmx_lib': '/path/to/myGMXLIB/',
53 'force_field': 'amber99sb-star-ildn-mut'
54 }
55 pmxmutate(input_structure_path='/path/to/myStructure.pdb',
56 output_structure_path='/path/to/newStructure.pdb',
57 input_b_structure_path='/path/to/myStructureB.pdb'
58 properties=prop)
60 Info:
61 * wrapped_software:
62 * name: PMX mutate
63 * version: >=1.0.1
64 * license: GNU
65 * ontology:
66 * name: EDAM
67 * schema: http://edamontology.org/EDAM.owl
69 """
71 def __init__(
72 self,
73 input_structure_path: str,
74 output_structure_path: str,
75 input_b_structure_path: Optional[str] = None,
76 properties: Optional[dict] = None,
77 **kwargs,
78 ) -> None:
79 properties = properties or {}
81 # Call parent class constructor
82 super().__init__(properties)
83 self.locals_var_dict = locals().copy()
85 # Input/Output files
86 self.io_dict = {
87 "in": {
88 "input_structure_path": input_structure_path,
89 "input_b_structure_path": input_b_structure_path,
90 },
91 "out": {"output_structure_path": output_structure_path},
92 }
94 # Properties specific for BB
95 self.force_field = properties.get("force_field", "amber99sb-star-ildn-mut")
96 self.resinfo = properties.get("resinfo", False)
97 self.mutation_list = properties.get("mutation_list", "2Ala")
98 self.input_mutations_file = properties.get("mutations_file")
100 # Properties common in all PMX BB
101 self.gmx_lib = properties.get("gmx_lib", None)
102 if not self.gmx_lib and os.environ.get("CONDA_PREFIX"):
103 python_version = f"{sys.version_info.major}.{sys.version_info.minor}"
104 self.gmx_lib = str(
105 Path(os.environ.get("CONDA_PREFIX", "")).joinpath(
106 f"lib/python{python_version}/site-packages/pmx/data/mutff/"
107 )
108 )
109 if properties.get("container_path"):
110 self.gmx_lib = str(
111 Path("/usr/local/").joinpath(
112 "lib/python3.8/site-packages/pmx/data/mutff/"
113 )
114 )
115 self.binary_path = properties.get("binary_path", "pmx")
117 # Check the properties
118 self.check_properties(properties)
119 self.check_arguments()
121 @launchlogger
122 def launch(self) -> int:
123 """Execute the :class:`Pmxmutate <pmx.pmxmutate.Pmxmutate>` pmx.pmxmutate.Pmxmutate object."""
125 # Setup Biobb
126 if self.check_restart():
127 return 0
128 self.stage_files()
130 # Check if executable exists
131 if not self.container_path:
132 if not Path(self.binary_path).is_file():
133 if not shutil.which(self.binary_path):
134 raise FileNotFoundError(
135 "Executable %s not found. Check if it is installed in your system and correctly defined in the properties"
136 % self.binary_path
137 )
139 # Generate mutations file
141 mutations_dir = fu.create_unique_dir()
142 self.input_mutations_file = create_mutations_file(
143 input_mutations_path=str(Path(mutations_dir).joinpath("mutations.txt")),
144 mutation_list=self.mutation_list,
145 mutation_dict=MUTATION_DICT,
146 )
148 # Copy extra files to container: mutations file
149 if self.container_path:
150 fu.log("Container execution enabled", self.out_log)
152 shutil.copy2(
153 self.input_mutations_file, self.stage_io_dict.get("unique_dir", "")
154 )
155 self.input_mutations_file = str(
156 Path(self.container_volume_path).joinpath(
157 Path(self.input_mutations_file).name
158 )
159 )
161 self.cmd = [
162 self.binary_path,
163 "mutate",
164 "-f",
165 self.stage_io_dict["in"]["input_structure_path"],
166 "-o",
167 self.stage_io_dict["out"]["output_structure_path"],
168 "-ff",
169 self.force_field,
170 "--script",
171 self.input_mutations_file,
172 ]
174 if self.stage_io_dict["in"].get("input_b_structure_path"):
175 self.cmd.append("-fB")
176 self.cmd.append(self.stage_io_dict["in"]["input_b_structure_path"])
177 if self.resinfo:
178 self.cmd.append("-resinfo")
180 if self.gmx_lib:
181 self.env_vars_dict["GMXLIB"] = self.gmx_lib
183 # Run Biobb block
184 self.run_biobb()
186 # Copy files to host
187 self.copy_to_host()
189 # self.tmp_files.append(self.stage_io_dict.get("unique_dir", ""))
190 self.tmp_files.extend([mutations_dir])
191 self.remove_tmp_files()
193 self.check_arguments(output_files_created=True, raise_exception=False)
194 return self.return_code
197def pmxmutate(
198 input_structure_path: str,
199 output_structure_path: str,
200 input_b_structure_path: Optional[str] = None,
201 properties: Optional[dict] = None,
202 **kwargs,
203) -> int:
204 """Execute the :class:`Pmxmutate <pmx.pmxmutate.Pmxmutate>` class and
205 execute the :meth:`launch() <pmx.pmxmutate.Pmxmutate.launch> method."""
207 return Pmxmutate(
208 input_structure_path=input_structure_path,
209 output_structure_path=output_structure_path,
210 input_b_structure_path=input_b_structure_path,
211 properties=properties,
212 **kwargs,
213 ).launch()
215 pmxmutate.__doc__ = Pmxmutate.__doc__
218def main():
219 """Command line execution of this building block. Please check the command line documentation."""
220 parser = argparse.ArgumentParser(
221 description="Run PMX mutate module",
222 formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, width=99999),
223 )
224 parser.add_argument(
225 "-c",
226 "--config",
227 required=False,
228 help="This file can be a YAML file, JSON file or JSON string",
229 )
231 # Specific args of each building block
232 required_args = parser.add_argument_group("required arguments")
233 required_args.add_argument(
234 "--input_structure_path", required=True, help="Path to the input structure file"
235 )
236 required_args.add_argument(
237 "--output_structure_path",
238 required=True,
239 help="Path to the output structure file",
240 )
241 parser.add_argument(
242 "--input_b_structure_path",
243 required=False,
244 help="Path to the mutated input structure file",
245 )
247 args = parser.parse_args()
248 config = args.config if args.config else None
249 properties = settings.ConfReader(config=config).get_prop_dic()
251 # Specific call of each building block
252 pmxmutate(
253 input_structure_path=args.input_structure_path,
254 output_structure_path=args.output_structure_path,
255 input_b_structure_path=args.input_b_structure_path,
256 properties=properties,
257 )
260if __name__ == "__main__":
261 main()