Coverage for biobb_mem/lipyphilic_biobb/lpp_flip_flop.py: 93%
54 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-08 09:07 +0000
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-08 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.lib.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.10.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 else: # .npy file
108 leaflets = np.load(leaflets_path)
109 # Create FlipFlop object
110 flip_flop = FlipFlop(
111 universe=u,
112 lipid_sel=self.lipid_sel,
113 leaflets=leaflets,
114 frame_cutoff=self.frame_cutoff,
115 )
116 # Run the analysis
117 flip_flop.run(start=self.start, stop=self.stop, step=self.steps)
119 # Save the results
120 resnames = []
121 if flip_flop.flip_flops.size > 0:
122 resnames = u.residues.resnames[flip_flop.flip_flops[:, 0]]
123 else:
124 print('No flip-flop events found.')
126 df = pd.DataFrame({
127 'resname': resnames,
128 'resindex': flip_flop.flip_flops[:, 0],
129 'start_frame': flip_flop.flip_flops[:, 1],
130 'end_frame': flip_flop.flip_flops[:, 2],
131 'end_leaflet': flip_flop.flip_flops[:, 3]
132 })
134 # Save the DataFrame to a CSV file
135 df.to_csv(self.stage_io_dict["out"]["output_flip_flop_path"], index=False)
137 # Copy files to host
138 self.copy_to_host()
139 self.remove_tmp_files()
140 self.check_arguments(output_files_created=True, raise_exception=False)
142 return self.return_code
145def lpp_flip_flop(input_top_path: str, input_traj_path: str, input_leaflets_path: str = None,
146 output_flip_flop_path: str = None, properties: dict = None, **kwargs) -> int:
147 """Execute the :class:`LPPFlipFlop <lipyphilic_biobb.lpp_flip_flop.LPPFlipFlop>` class and
148 execute the :meth:`launch() <lipyphilic_biobb.lpp_flip_flop.LPPFlipFlop.launch>` method."""
149 return LPPFlipFlop(**dict(locals())).launch()
152lpp_flip_flop.__doc__ = LPPFlipFlop.__doc__
153main = LPPFlipFlop.get_main(lpp_flip_flop, "Find flip-flop events in a lipid bilayer.")
155if __name__ == '__main__':
156 main()