Coverage for biobb_dna / curvesplus / biobb_canion.py: 93%
68 statements
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-15 18:49 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-15 18:49 +0000
1#!/usr/bin/env python3
3"""Module containing the Canion class and the command line interface."""
4import os
5import zipfile
6from typing import Optional
7from pathlib import Path
8from biobb_common.generic.biobb_object import BiobbObject
9from biobb_common.tools import file_utils as fu
10from biobb_common.tools.file_utils import launchlogger
13class Canion(BiobbObject):
14 """
15 | biobb_dna Canion
16 | Wrapper for the Canion executable that is part of the Curves+ software suite.
17 | Analyzes the trajectory of ions around a DNA molecule.
19 Args:
20 input_cdi_path (str): Trajectory input file. File type: input. `Sample file <https://mmb.irbbarcelona.org/biobb-dev/biobb-api/public/samples/THGA_K.cdi>`_. Accepted formats: cdi (edam:format_2330).
21 input_afr_path (str): Helical axis frames corresponding to the input conformation to be analyzed. File type: input. `Sample file <https://raw.githubusercontent.com/bioexcel/biobb_dna/master/biobb_dna/test/data/curvesplus/THGA.afr>`_. Accepted formats: afr (edam:format_2330).
22 input_avg_struc_path (str): Average DNA conformation. File type: input. `Sample file <https://raw.githubusercontent.com/bioexcel/biobb_dna/master/biobb_dna/test/data/curvesplus/THGA_avg.pdb>`_. Accepted formats: pdb (edam:format_1476).
23 output_zip_path (str): Filename for .zip files containing Canion output files. File type: output. `Sample file <https://raw.githubusercontent.com/bioexcel/biobb_dna/master/biobb_dna/test/reference/curvesplus/canion_output.zip>`_. Accepted formats: zip (edam:format_3987).
24 properties (dict):
25 * **bases** (*str*) - (None) Sequence of bases to be analyzed (default is blank, meaning no specified sequence).
26 * **type** (*str*) - ('*') Ions (or atoms) to be analyzed. Options are 'Na+', 'K', 'K+', 'Cl', 'Cl-', 'CL', 'P', 'C1*', 'NH1', 'NH2', 'NZ', '1' for all cations, '-1' for all anions, '0' for neutral species or '*' for all available data.
27 * **dlow** (*float*) - (0) Select starting segment of the oglimer to analyze. If both dhig and dlow are 0, entire oglimer is analyzed.
28 * **dhig** (*float*) - (0) Select ending segment of the oglimer to analyze, being the maximum value the total number of base pairs in the oligomer. If both dhig and dlow are 0, entire oglimer is analyzed.
29 * **rlow** (*float*) - (0) Minimal distances from the helical axis taken into account in the analysis.
30 * **rhig** (*float*) - (0) Maximal distances from the helical axis taken into account in the analysis.
31 * **alow** (*float*) - (0) Minimal angle range to analyze.
32 * **ahig** (*float*) - (360) Maximal angle range to analyze.
33 * **itst** (*int*) - (0) Number of first snapshot to be analyzed.
34 * **itnd** (*int*) - (0) Number of last snapshot to be analyzed.
35 * **itdel** (*int*) - (1) Spacing between analyzed snapshots.
36 * **rmsf** (*bool*) - (False) If set to True uses the combination of the helical ion parameters and an average helical axis to map the ions into Cartesian space and then calculates their average position (pdb output) and their root mean square fluctuation values (rmsf output). A single pass rmsf algorithm to make this calculation possible with a single read of the trajectory file. This option is generally used for solute atoms and not for solvent molecules or ions.
37 * **circ** (*bool*) - (False) If set to True, minicircles are analyzed.
38 * **binary_path** (*str*) - (Canion) Path to Canion executable, otherwise the program wil look for Canion executable in the binaries folder.
39 * **remove_tmp** (*bool*) - (True) [WF property] Remove temporal files.
40 * **restart** (*bool*) - (False) [WF property] Do not execute if output files exist.
41 * **sandbox_path** (*str*) - ("./") [WF property] Parent path to the sandbox directory.
42 Examples:
43 This is a use example of how to use the building block from Python::
45 from biobb_dna.curvesplus.biobb_canion import biobb_canion
46 prop = {
47 'type': 'K+',
48 'bases': 'G'
49 }
50 biobb_canion(
51 input_cdi_path='/path/to/input.cdi',
52 input_afr_path='/path/to/input.afr',
53 input_avg_struc_path='/path/to/input.pdb',
54 output_zip_path='/path/to/output.zip',
55 properties=prop)
56 Info:
57 * wrapped_software:
58 * name: Canion
59 * version: >=2.6
60 * license: BSD 3-Clause
61 * ontology:
62 * name: EDAM
63 * schema: http://edamontology.org/EDAM.owl
64 """
66 def __init__(
67 self, input_cdi_path, input_afr_path, input_avg_struc_path,
68 output_zip_path=None, properties=None, **kwargs) -> None:
69 properties = properties or {}
71 # Call parent class constructor
72 super().__init__(properties)
73 self.locals_var_dict = locals().copy()
75 # Input/Output files
76 self.io_dict = {
77 'in': {
78 'input_cdi_path': input_cdi_path,
79 'input_afr_path': input_afr_path,
80 'input_avg_struc_path': input_avg_struc_path,
81 },
82 'out': {
83 'output_zip_path': output_zip_path
84 }
85 }
87 # Properties specific for BB
88 self.binary_path = properties.get('binary_path', 'Canion')
89 self.bases = properties.get('bases', None)
90 self.type = properties.get('type', '*')
91 self.dlow = properties.get('dlow', 0)
92 self.dhig = properties.get('dhig', 0)
93 self.rlow = properties.get('rlow', 0)
94 self.rhig = properties.get('rhig', 0)
95 self.alow = properties.get('alow', 0)
96 self.ahig = properties.get('ahig', 360)
97 self.itst = properties.get('itst', 0)
98 self.itnd = properties.get('itnd', 0)
99 self.itdel = properties.get('itdel', 1)
100 self.rmsf = ".t." if properties.get('rmsf', False) else ".f."
101 self.circ = ".t." if properties.get('circ', False) else ".f."
102 self.properties = properties
104 # Check the properties
105 self.check_properties(properties)
106 self.check_arguments()
108 @launchlogger
109 def launch(self) -> int:
110 """Execute the :class:`Canion <biobb_dna.curvesplus.biobb_canion.Canion>` object."""
112 # Setup Biobb
113 if self.check_restart():
114 return 0
115 self.stage_files()
117 ion_type_options = [
118 'Na+',
119 'K',
120 'K+',
121 'Cl',
122 'Cl-',
123 'CL',
124 'P',
125 'C1*',
126 'NH1',
127 'NH2',
128 'NZ',
129 '1',
130 '-1',
131 '0',
132 '*'
133 ]
134 if self.type not in ion_type_options:
135 raise ValueError(("Invalid value for property type! "
136 f"Option include: {ion_type_options}"))
138 # define temporary file names
139 input_cdi_file = Path(self.stage_io_dict['in']['input_cdi_path']).name
140 input_afr_file = Path(self.stage_io_dict['in']['input_afr_path']).name
141 input_avg_struc = Path(self.stage_io_dict['in']['input_avg_struc_path']).name
143 # change directory to temporary folder
144 original_directory = os.getcwd()
145 os.chdir(self.stage_io_dict.get("unique_dir", ""))
147 # create intructions
148 instructions = [
149 f"{self.binary_path} <<! ",
150 "&inp",
151 " lis=canion_output,",
152 f" dat={input_cdi_file[:-4]},",
153 f" axfrm={input_afr_file[:-4]},",
154 f" solute={input_avg_struc[:-4]},",
155 f" type={self.type},",
156 f" dlow={self.dlow},",
157 f" dhig={self.dhig},",
158 f" rlow={self.rlow},",
159 f" rhig={self.rhig},",
160 f" alow={self.alow},",
161 f" ahig={self.ahig},",
162 f" itst={self.itst},",
163 f" itnd={self.itnd},",
164 f" itdel={self.itdel},",
165 f" rmsf={self.rmsf},",
166 f" circ={self.circ},"]
167 if self.bases is not None:
168 # add topology file if needed
169 fu.log('Appending sequence of bases to be searched to command',
170 self.out_log, self.global_log)
171 instructions.append(f" seq={self.bases},")
172 instructions.append("&end")
173 instructions.append("!")
174 self.cmd = ["\n".join(instructions)]
176 fu.log('Creating command line with instructions and required arguments',
177 self.out_log, self.global_log)
178 # Run Biobb block
179 self.run_biobb()
181 # change back to original directory
182 os.chdir(original_directory)
184 # create zipfile and write output inside
185 zf = zipfile.ZipFile(
186 Path(self.stage_io_dict["out"]["output_zip_path"]),
187 "w")
188 for curves_outfile in Path(self.stage_io_dict.get("unique_dir", "")).glob("canion_output*"):
189 if curves_outfile.suffix not in (".zip"):
190 zf.write(curves_outfile, arcname=curves_outfile.name)
191 zf.close()
193 # Copy files to host
194 self.copy_to_host()
196 # Remove temporary file(s)
197 self.remove_tmp_files()
199 self.check_arguments(output_files_created=True, raise_exception=False)
201 return self.return_code
204def biobb_canion(
205 input_cdi_path: str, input_afr_path: str, input_avg_struc_path: str,
206 output_zip_path: Optional[str] = None, properties: Optional[dict] = None, **kwargs) -> int:
207 """Create :class:`Canion <biobb_dna.curvesplus.biobb_canion.Canion>` class and
208 execute the :meth:`launch() <biobb_dna.curvesplus.biobb_canion.Canion.launch>` method."""
209 return Canion(**dict(locals())).launch()
212biobb_canion.__doc__ = Canion.__doc__
213main = Canion.get_main(biobb_canion, "Execute Canion form the Curves+ software suite.")
215if __name__ == '__main__':
216 main()