Coverage for biobb_mem / lipyphilic_biobb / lpp_flip_flop.py: 93%
55 statements
« prev ^ index » next coverage.py v7.13.3, created at 2026-02-05 09:07 +0000
« prev ^ index » next coverage.py v7.13.3, created at 2026-02-05 09:07 +0000
1#!/usr/bin/env python3
3"""Module containing the Lipyphilic FlipFlop class and the command line interface."""
4from biobb_common.generic.biobb_object import BiobbObject
5from biobb_common.tools.file_utils import launchlogger
6import MDAnalysis as mda
7from biobb_mem.lipyphilic_biobb.common import ignore_no_box
8from lipyphilic.analysis.flip_flop import FlipFlop
9import pandas as pd
10import numpy as np
13class LPPFlipFlop(BiobbObject):
14 """
15 | biobb_mem LPPFlipFlop
16 | Wrapper of the LiPyphilic FlipFlop module for finding flip-flop events in a lipid bilayer.
17 | LiPyphilic is a Python package for analyzing MD simulations of lipid bilayers. The parameter names and defaults are the same as the ones in the official `Lipyphilic documentation <https://lipyphilic.readthedocs.io/en/stable/reference/lib/flip_flop.html>`_.
19 Args:
20 input_top_path (str): Path to the input structure or topology file. File type: input. `Sample file <https://github.com/bioexcel/biobb_mem/raw/main/biobb_mem/test/data/A01JD/A01JD.pdb>`_. Accepted formats: crd (edam:3878), gro (edam:2033), mdcrd (edam:3878), mol2 (edam:3816), pdb (edam:1476), pdbqt (edam:1476), prmtop (edam:3881), psf (edam:3882), top (edam:3881), tpr (edam:2333), xml (edam:2332), xyz (edam:3887).
21 input_traj_path (str): Path to the input trajectory to be processed. File type: input. `Sample file <https://github.com/bioexcel/biobb_mem/raw/main/biobb_mem/test/data/A01JD/A01JD.xtc>`_. Accepted formats: arc (edam:2333), crd (edam:3878), dcd (edam:3878), ent (edam:1476), gro (edam:2033), inpcrd (edam:3878), mdcrd (edam:3878), mol2 (edam:3816), nc (edam:3650), pdb (edam:1476), pdbqt (edam:1476), restrt (edam:3886), tng (edam:3876), trr (edam:3910), xtc (edam:3875), xyz (edam:3887).
22 input_leaflets_path (str): Path to the input leaflet assignments. File type: input. `Sample file <https://github.com/bioexcel/biobb_mem/raw/main/biobb_mem/test/reference/lipyphilic_biobb/leaflets_data.csv>`_. Accepted formats: csv (edam:format_3752), npy (edam:format_4003).
23 output_flip_flop_path (str): Path to the output flip-flop data. File type: output. `Sample file <https://github.com/bioexcel/biobb_mem/raw/main/biobb_mem/test/reference/lipyphilic_biobb/flip_flop.csv>`_. Accepted formats: csv (edam:format_3752).
24 properties (dic - Python dictionary object containing the tool parameters, not input/output files):
25 * **start** (*int*) - (None) Starting frame for slicing.
26 * **stop** (*int*) - (None) Ending frame for slicing.
27 * **steps** (*int*) - (None) Step for slicing.
28 * **lipid_sel** (*str*) - ("all") Selection string for the lipids in a membrane. The selection should cover **all** residues in the membrane, including cholesterol.
29 * **frame_cutoff** (*float*) - (1) To be counted as a successful flip-flop, a molecule must reside in its new leaflet for at least ‘frame_cutoff’ consecutive frames. The default is 1, in which case the molecule only needs to move to the opposing leaflet for a single frame for the flip-flop to be successful.
30 * **ignore_no_box** (*bool*) - (False) Ignore the absence of box information in the trajectory. If the trajectory does not contain box information, the box will be set to the minimum and maximum positions of the atoms in the trajectory.
31 * **remove_tmp** (*bool*) - (True) [WF property] Remove temporal files.
32 * **restart** (*bool*) - (False) [WF property] Do not execute if output files exist.
33 * **sandbox_path** (*str*) - ("./") [WF property] Parent path to the sandbox directory.
35 Examples:
36 This is a use example of how to use the building block from Python::
38 from biobb_mem.lipyphilic_biobb.lpp_flip_flop import lpp_flip_flop
39 prop = {
40 'lipid_sel': 'name GL1 GL2 ROH',
41 }
42 lpp_flip_flop(input_top_path='/path/to/myTopology.tpr',
43 input_traj_path='/path/to/myTrajectory.xtc',
44 input_leaflets_path='/path/to/leaflets.csv',
45 output_flip_flop_path='/path/to/flip_flops.csv',
46 properties=prop)
48 Info:
49 * wrapped_software:
50 * name: LiPyphilic
51 * version: 0.11.0
52 * license: GPL-2.0
53 * ontology:
54 * name: EDAM
55 * schema: http://edamontology.org/EDAM.owl
57 """
59 def __init__(self, input_top_path, input_traj_path,
60 input_leaflets_path, output_flip_flop_path,
61 properties=None, **kwargs) -> None:
62 properties = properties or {}
64 # Call parent class constructor
65 super().__init__(properties)
66 self.locals_var_dict = locals().copy()
68 # Input/Output files
69 self.io_dict = {
70 "in": {"input_top_path": input_top_path,
71 "input_traj_path": input_traj_path,
72 "input_leaflets_path": input_leaflets_path},
73 "out": {"output_flip_flop_path": output_flip_flop_path}
74 }
75 self.start = properties.get('start', None)
76 self.stop = properties.get('stop', None)
77 self.steps = properties.get('steps', None)
78 self.lipid_sel = properties.get('lipid_sel', 'all')
79 self.frame_cutoff = properties.get('frame_cutoff', 1)
80 # Properties specific for BB
81 self.ignore_no_box = properties.get('ignore_no_box', True)
82 self.properties = properties
84 # Check the properties
85 self.check_properties(properties)
86 self.check_arguments()
88 @launchlogger
89 def launch(self) -> int:
90 """Execute the :class:`LPPFlipFlop <lipyphilic_biobb.lpp_flip_flop.LPPFlipFlop>` object."""
92 # Setup Biobb
93 if self.check_restart():
94 return 0
95 self.stage_files()
97 # Load the trajectory
98 u = mda.Universe(self.stage_io_dict["in"]["input_top_path"], self.stage_io_dict["in"]["input_traj_path"])
99 ignore_no_box(u, self.ignore_no_box, self.out_log, self.global_log)
100 # Load the leaflets
101 leaflets_path = self.stage_io_dict["in"]["input_leaflets_path"]
102 if leaflets_path.endswith('.csv'):
103 df = pd.read_csv(leaflets_path)
104 n_frames = len(df['frame'].unique())
105 n_residues = len(df['resindex'].unique())
106 leaflets = df['leaflet_index'].values.reshape(n_frames, n_residues).T
107 leaflets = np.asarray(leaflets, dtype=np.int8)
108 else: # .npy file
109 leaflets = np.load(leaflets_path).astype(np.int8)
110 # Create FlipFlop object
111 flip_flop = FlipFlop(
112 universe=u,
113 lipid_sel=self.lipid_sel,
114 leaflets=leaflets,
115 frame_cutoff=self.frame_cutoff,
116 )
117 # Run the analysis
118 flip_flop.run(start=self.start, stop=self.stop, step=self.steps)
120 # Save the results
121 resnames = []
122 if flip_flop.flip_flops.size > 0:
123 resnames = u.residues.resnames[flip_flop.flip_flops[:, 0]]
124 else:
125 print('No flip-flop events found.')
127 df = pd.DataFrame({
128 'resname': resnames,
129 'resindex': flip_flop.flip_flops[:, 0],
130 'start_frame': flip_flop.flip_flops[:, 1],
131 'end_frame': flip_flop.flip_flops[:, 2],
132 'end_leaflet': flip_flop.flip_flops[:, 3]
133 })
135 # Save the DataFrame to a CSV file
136 df.to_csv(self.stage_io_dict["out"]["output_flip_flop_path"], index=False)
138 # Copy files to host
139 self.copy_to_host()
140 self.remove_tmp_files()
141 self.check_arguments(output_files_created=True, raise_exception=False)
143 return self.return_code
146def lpp_flip_flop(input_top_path: str, input_traj_path: str, input_leaflets_path: str = None,
147 output_flip_flop_path: str = None, properties: dict = None, **kwargs) -> int:
148 """Execute the :class:`LPPFlipFlop <lipyphilic_biobb.lpp_flip_flop.LPPFlipFlop>` class and
149 execute the :meth:`launch() <lipyphilic_biobb.lpp_flip_flop.LPPFlipFlop.launch>` method."""
150 return LPPFlipFlop(**dict(locals())).launch()
153lpp_flip_flop.__doc__ = LPPFlipFlop.__doc__
154main = LPPFlipFlop.get_main(lpp_flip_flop, "Find flip-flop events in a lipid bilayer.")
156if __name__ == '__main__':
157 main()