Coverage for biobb_flexserv / pcasuite / pcz_stiffness.py: 97%
64 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-05 13:10 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-05 13:10 +0000
1#!/usr/bin/env python3
3"""Module containing the PCZstiffness class and the command line interface."""
4from typing import Optional
5import shutil
6import json
7import math
8from pathlib import PurePath
9from biobb_common.tools import file_utils as fu
10from biobb_common.generic.biobb_object import BiobbObject
11from biobb_common.tools.file_utils import launchlogger
14class PCZstiffness(BiobbObject):
15 """
16 | biobb_flexserv PCZstiffness
17 | Extract PCA stiffness from a compressed PCZ file.
18 | Wrapper of the pczdump tool from the PCAsuite FlexServ module.
20 Args:
21 input_pcz_path (str): Input compressed trajectory file. File type: input. `Sample file <https://github.com/bioexcel/biobb_flexserv/raw/master/biobb_flexserv/test/data/pcasuite/pcazip.pcz>`_. Accepted formats: pcz (edam:format_3874).
22 output_json_path (str): Output json file with PCA Stiffness. File type: output. `Sample file <https://github.com/bioexcel/biobb_flexserv/raw/master/biobb_flexserv/test/reference/pcasuite/pcz_stiffness.json>`_. Accepted formats: json (edam:format_3464).
23 properties (dict - Python dictionary object containing the tool parameters, not input/output files):
24 * **binary_path** (*str*) - ("pczdump") pczdump binary path to be used.
25 * **eigenvector** (*int*) - (0) PCA mode (eigenvector) from which to extract stiffness.
26 * **temperature** (*int*) - (300) Temperature with which compute the apparent stiffness.
27 * **remove_tmp** (*bool*) - (True) [WF property] Remove temporal files.
28 * **restart** (*bool*) - (False) [WF property] Do not execute if output files exist.
29 * **sandbox_path** (*str*) - ("./") [WF property] Parent path to the sandbox directory.
31 Examples:
32 This is a use example of how to use the building block from Python::
34 from biobb_flexserv.pcasuite.pcz_stiffness import pcz_stiffness
36 prop = {
37 'eigenvector': 1
38 }
40 pcz_stiffness( input_pcz_path='/path/to/pcazip_input.pcz',
41 output_json_path='/path/to/pcz_stiffness.json',
42 properties=prop)
44 Info:
45 * wrapped_software:
46 * name: FlexServ PCAsuite
47 * version: >=1.0
48 * license: Apache-2.0
49 * ontology:
50 * name: EDAM
51 * schema: http://edamontology.org/EDAM.owl
53 """
55 def __init__(self, input_pcz_path: str,
56 output_json_path: str, properties: Optional[dict] = None, **kwargs) -> 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_pcz_path': input_pcz_path},
67 'out': {'output_json_path': output_json_path}
68 }
70 # Properties specific for BB
71 self.properties = properties
72 self.binary_path = properties.get('binary_path', 'pczdump')
73 self.eigenvector = properties.get('eigenvector', 0)
74 self.temperature = properties.get('temperature', 300)
76 # Check the properties
77 self.check_properties(properties)
78 self.check_arguments()
80 @launchlogger
81 def launch(self):
82 """Launches the execution of the FlexServ pcz_stiffness module."""
84 # Setup Biobb
85 if self.check_restart():
86 return 0
87 # self.stage_files()
89 # Internal file paths
90 # try:
91 # # Using rel paths to shorten the amount of characters due to fortran path length limitations
92 # input_pcz = str(Path(self.stage_io_dict["in"]["input_pcz_path"]).relative_to(Path.cwd()))
93 # output_json = str(Path(self.stage_io_dict["out"]["output_json_path"]).relative_to(Path.cwd()))
94 # except ValueError:
95 # # Container or remote case
96 # input_pcz = self.stage_io_dict["in"]["input_pcz_path"]
97 # output_json = self.stage_io_dict["out"]["output_json_path"]
99 # Manually creating a Sandbox to avoid issues with input parameters buffer overflow:
100 # Long strings defining a file path makes Fortran or C compiled programs crash if the string
101 # declared is shorter than the input parameter path (string) length.
102 # Generating a temporary folder and working inside this folder (sandbox) fixes this problem.
103 # The problem was found in Galaxy executions, launching Singularity containers (May 2023).
105 # Creating temporary folder
106 tmp_folder = fu.create_unique_dir()
107 fu.log('Creating %s temporary folder' % tmp_folder, self.out_log)
109 shutil.copy2(self.io_dict["in"]["input_pcz_path"], tmp_folder)
111 # Temporary output
112 # temp_out = str(Path(self.stage_io_dict.get("unique_dir", "")).joinpath("output.dat"))
113 temp_out = "output.dat"
114 temp_json = "output.json"
116 # Command line
117 # pczdump -i structure.ca.std.pcz --stiffness -o pcz.stiffness
118 # self.cmd = [self.binary_path,
119 # "-i", input_pcz,
120 # "-o", temp_out,
121 # "--stiffness={}".format(self.eigenvector),
122 # "--temperature={}".format(self.temperature)
123 # ]
125 self.cmd = ['cd', tmp_folder, ';',
126 self.binary_path,
127 "-i", PurePath(self.io_dict["in"]["input_pcz_path"]).name,
128 "-o", temp_out,
129 "--stiff={}".format(self.eigenvector),
130 "--temperature={}".format(self.temperature)
131 ]
133 # Run Biobb block
134 self.run_biobb()
136 # Parse output stiffness
137 info_dict = {}
138 info_dict['stiffness'] = []
139 info_dict['stiffness_log'] = []
140 row = 0
141 with open(PurePath(tmp_folder).joinpath(temp_out), 'r') as file:
142 for line in file:
143 info = line.strip().split(',')
144 line_array = []
145 line_array_log = []
146 for nums in info:
147 if nums:
148 line_array.append(float(nums))
149 if float(nums) != 0:
150 line_array_log.append(math.log10(float(nums)))
151 else:
152 line_array_log.append(float(nums))
154 info_dict['stiffness'].append(line_array)
155 info_dict['stiffness'][row][row] = float('inf')
156 info_dict['stiffness_log'].append(line_array_log)
157 info_dict['stiffness_log'][row][row] = float('inf')
158 row += 1
160 with open(PurePath(tmp_folder).joinpath(temp_json), 'w') as out_file:
161 out_file.write(json.dumps(info_dict, indent=4))
163 # Copy outputs from temporary folder to output path
164 shutil.copy2(PurePath(tmp_folder).joinpath(temp_json), PurePath(self.io_dict["out"]["output_json_path"]))
166 # Copy files to host
167 # self.copy_to_host()
169 # Remove temporary folder(s)
170 self.tmp_files.append(tmp_folder)
171 self.remove_tmp_files()
173 self.check_arguments(output_files_created=True, raise_exception=False)
175 return self.return_code
178def pcz_stiffness(input_pcz_path: str, output_json_path: str,
179 properties: Optional[dict] = None, **kwargs) -> int:
180 """Create :class:`PCZstiffness <flexserv.pcasuite.pcz_stiffness>`flexserv.pcasuite.PCZstiffness class and
181 execute :meth:`launch() <flexserv.pcasuite.pcz_stiffness.launch>` method"""
182 return PCZstiffness(**dict(locals())).launch()
185pcz_stiffness.__doc__ = PCZstiffness.__doc__
186main = PCZstiffness.get_main(pcz_stiffness, "Extract PCA Stiffness from a compressed PCZ file.")
188if __name__ == '__main__':
189 main()