Coverage for biobb_mem/fatslim/fatslim_apl.py: 78%
73 statements
« prev ^ index » next coverage.py v7.10.1, created at 2025-08-01 02:58 +0000
« prev ^ index » next coverage.py v7.10.1, created at 2025-08-01 02:58 +0000
1#!/usr/bin/env python3
3"""Module containing the FATSLiM Area per Lipid class and the command line interface."""
4import argparse
5from pathlib import PurePath
6from biobb_common.generic.biobb_object import BiobbObject
7from biobb_common.configuration import settings
8from biobb_common.tools.file_utils import launchlogger
9from biobb_common.tools import file_utils as fu
10import MDAnalysis as mda
11from biobb_mem.fatslim.common import calculate_box
12import shutil
15class FatslimAPL(BiobbObject):
16 """
17 | biobb_mem FatslimAPL
18 | Wrapper of the `FATSLiM area per lipid <https://pythonhosted.org/fatslim/documentation/apl.html>`_ module for area per lipid calculation.
19 | FATSLiM is designed to provide efficient and robust analysis of physical parameters from MD trajectories, with a focus on processing large trajectory files quickly.
21 Args:
22 input_top_path (str): Path to the input topology file. File type: input. `Sample file <https://github.com/bioexcel/biobb_mem/raw/main/biobb_mem/test/data/A01JD/A01JD.pdb>`_. Accepted formats: tpr (edam:format_2333), gro (edam:format_2033), g96 (edam:format_2033), pdb (edam:format_1476), brk (edam:format_2033), ent (edam:format_1476).
23 input_traj_path (str) (Optional): Path to the GROMACS trajectory file. File type: input. `Sample file <https://github.com/bioexcel/biobb_mem/raw/main/biobb_mem/test/data/A01JD/A01JD.xtc>`_. Accepted formats: xtc (edam:format_3875), trr (edam:format_3910), cpt (edam:format_2333), gro (edam:format_2033), g96 (edam:format_2033), pdb (edam:format_1476), tng (edam:format_3876).
24 input_ndx_path (str) (Optional): Path to the input index NDX file for lipid headgroups and the interacting group. File type: input. `Sample file <https://github.com/bioexcel/biobb_mem/raw/main/biobb_mem/test/data/A01JD/headgroups.ndx>`_. Accepted formats: ndx (edam:format_2033).
25 output_csv_path (str): Path to the output CSV file. File type: output. `Sample file <https://github.com/bioexcel/biobb_mem/raw/main/biobb_mem/test/reference/fatslim/apl.ndx>`_. Accepted formats: csv (edam:format_3752).
26 properties (dic - Python dictionary object containing the tool parameters, not input/output files):
27 * **lipid_selection** (*str*) - ("not protein and element P") Headgroups MDAnalysis `selection <https://docs.mdanalysis.org/stable/documentation_pages/selections.html>`_.
28 * **protein_selection** (*str*) - ("protein and not element H") Protein selection interacting with the membrane.
29 * **cutoff** (*float*) - (3) This option allows user to specify the cutoff distance (in nm) to be used when performing the neighbor search needed by the APL calculation algorithm
30 * **limit** (*float*) - (10) This option allows user to specify the upper limit (in nm2) for a valid area per lipid value.
31 * **begin_frame** (*int*) - (-1) First frame index to be used for analysis.
32 * **end_frame** (*int*) - (-1) Last frame index to be used for analysis.
33 * **ignore_no_box** (*bool*) - (False) Ignore the absence of box information in the topology. If the topology does not contain box information, the box will be set to the minimum and maximum positions of the atoms.
34 * **return_hydrogen** (*bool*) - (False) Include hydrogen atoms in the output index file.
35 * **binary_path** (*str*) - ("fatslim") Path to the fatslim executable binary.
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.
40 Examples:
41 This is a use example of how to use the building block from Python::
43 from biobb_mem.fatslim.fatslim_apl import fatslim_apl
44 prop = {
45 'lipid_selection': '(resname DPPC and name P8)',
46 'cutoff': 3
47 }
48 fatslim_apl(input_top_path='/path/to/myTopology.tpr',
49 input_traj_path='/path/to/myTrajectory.xtc',
50 output_csv_path='/path/to/newIndex.ndx',
51 properties=prop)
53 Info:
54 * wrapped_software:
55 * name: FATSLiM
56 * version: 0.2.2
57 * license: GNU
58 * ontology:
59 * name: EDAM
60 * schema: http://edamontology.org/EDAM.owl
62 """
64 def __init__(self, input_top_path, output_csv_path, input_traj_path=None, input_ndx_path=None, properties=None, **kwargs) -> None:
65 properties = properties or {}
67 # Call parent class constructor
68 super().__init__(properties)
69 self.locals_var_dict = locals().copy()
71 # Input/Output files
72 self.io_dict = {
73 "in": {"input_top_path": input_top_path,
74 "input_traj_path": input_traj_path,
75 "input_ndx_path": input_ndx_path},
76 "out": {"output_csv_path": output_csv_path}
77 }
79 # Properties specific for BB
80 self.lipid_selection = properties.get('lipid_selection', "not protein and element P")
81 self.protein_selection = properties.get('protein_selection', "protein and not element H")
82 self.cutoff = properties.get('cutoff', 3)
83 self.limit = properties.get('cutoff', 10)
84 self.begin_frame = properties.get('begin_frame', -1)
85 self.end_frame = properties.get('end_frame', -1)
86 self.ignore_no_box = properties.get('ignore_no_box', False)
87 self.binary_path = properties.get('binary_path', 'fatslim')
88 self.properties = properties
90 # Check the properties
91 self.check_properties(properties)
92 self.check_arguments()
94 @launchlogger
95 def launch(self) -> int:
96 """Execute the :class:`FatslimAPL <fatslim.fatslim_apl.FatslimAPL>` fatslim.fatslim_apl.FatslimAPL object."""
98 # Setup Biobb
99 if self.check_restart():
100 return 0
101 self.stage_files()
103 # Create index file using MDAnalysis
104 u = mda.Universe(topology=self.stage_io_dict["in"]["input_top_path"],
105 coordinates=self.stage_io_dict["in"].get("input_traj_path"))
106 if u.dimensions is None:
107 # FATSLiM ValueError: Box does not correspond to PBC=xyz
108 if self.ignore_no_box:
109 fu.log('Setting box dimensions using the minimum and maximum positions of the atoms.',
110 self.out_log, self.global_log)
111 calculate_box(u)
112 else:
113 fu.log('The trajectory does not contain box information. '
114 'Please set the ignore_no_box property to True to ignore this error.',
115 self.out_log, self.global_log)
117 # Build the index to select the atoms from the membrane
118 if self.stage_io_dict["in"].get('input_ndx_path', None):
119 self.tmp_ndx = self.stage_io_dict["in"]["input_ndx_path"]
120 else:
121 self.tmp_ndx = str(PurePath(fu.create_unique_dir()).joinpath('apl_inp.ndx'))
122 with mda.selections.gromacs.SelectionWriter(self.tmp_ndx, mode='w') as ndx:
123 ndx.write(u.select_atoms(self.lipid_selection), name='headgroups')
124 ndx.write(u.select_atoms(self.protein_selection), name='protein')
126 if self.stage_io_dict["in"]["input_top_path"].endswith('gro'):
127 self.cfg = self.stage_io_dict["in"]["input_top_path"]
128 self.cmd = []
129 else:
130 # Convert topology .gro and add box dimensions if not available in the topology
131 self.cfg = str(PurePath(fu.create_unique_dir()).joinpath('output.gro'))
132 self.tmp_files.extend([PurePath(self.cfg).parent])
133 self.cmd = ['gmx', 'editconf',
134 '-f', self.stage_io_dict["in"]["input_top_path"],
135 '-o', self.cfg,
136 '-box', ' '.join(map(str, u.dimensions[:3])), ';',
137 ]
138 self.tmp_csv = str(PurePath(self.stage_io_dict["unique_dir"]).joinpath('out.csv'))
139 # Build command
140 self.cmd.extend([
141 self.binary_path, "apl",
142 "-n", self.tmp_ndx,
143 "-c", self.cfg,
144 "--export-apl-raw", self.tmp_csv,
145 "--apl-cutoff", str(self.cutoff),
146 "--apl-limit", str(self.limit),
147 "--begin-frame", str(self.begin_frame),
148 "--end-frame", str(self.end_frame)
149 ])
151 # Run Biobb block
152 self.run_biobb()
153 shutil.move(self.tmp_csv[:-4]+'_frame_00000.csv', self.stage_io_dict["out"]["output_csv_path"])
154 # Copy files to host
155 self.copy_to_host()
156 # Remove temporary files
157 self.tmp_files.extend([
158 self.stage_io_dict.get("unique_dir"),
159 PurePath(self.tmp_ndx).parent
160 ])
161 self.remove_tmp_files()
163 self.check_arguments(output_files_created=True, raise_exception=False)
165 return self.return_code
168def fatslim_apl(input_top_path: str, output_csv_path: str, input_traj_path: str = None, input_ndx_path: str = None, properties: dict = None, **kwargs) -> int:
169 """Execute the :class:`FatslimAPL <fatslim.fatslim_apl.FatslimAPL>` class and
170 execute the :meth:`launch() <fatslim.fatslim_apl.FatslimAPL.launch>` method."""
172 return FatslimAPL(input_top_path=input_top_path,
173 input_traj_path=input_traj_path,
174 input_ndx_path=input_ndx_path,
175 output_csv_path=output_csv_path,
176 properties=properties, **kwargs).launch()
179def main():
180 """Command line execution of this building block. Please check the command line documentation."""
181 parser = argparse.ArgumentParser(description="Calculate the area per lipid.", formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, width=99999))
182 parser.add_argument('--config', required=False, help='Configuration file')
184 # Specific args of each building block
185 required_args = parser.add_argument_group('required arguments')
186 required_args.add_argument('--input_top_path', required=True, help='Path to the input structure or topology file. Accepted formats: ent, gro, pdb, tpr.')
187 required_args.add_argument('--output_csv_path', required=True, help='Path to the GROMACS index file. Accepted formats: ndx')
188 parser.add_argument('--input_traj_path', required=False, help='Path to the input trajectory to be processed. Accepted formats: gro, pdb, tng, trr, xtc.')
190 args = parser.parse_args()
191 args.config = args.config or "{}"
192 properties = settings.ConfReader(config=args.config).get_prop_dic()
194 # Specific call of each building block
195 fatslim_apl(input_top_path=args.input_top_path,
196 output_csv_path=args.output_csv_path,
197 properties=properties)
200if __name__ == '__main__':
201 main()