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

1#!/usr/bin/env python3 

2 

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 

11 

12 

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>`_. 

18 

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. 

34 

35 Examples: 

36 This is a use example of how to use the building block from Python:: 

37 

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) 

47 

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 

56 

57 """ 

58 

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 {} 

63 

64 # Call parent class constructor 

65 super().__init__(properties) 

66 self.locals_var_dict = locals().copy() 

67 

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 

83 

84 # Check the properties 

85 self.check_properties(properties) 

86 self.check_arguments() 

87 

88 @launchlogger 

89 def launch(self) -> int: 

90 """Execute the :class:`LPPFlipFlop <lipyphilic_biobb.lpp_flip_flop.LPPFlipFlop>` object.""" 

91 

92 # Setup Biobb 

93 if self.check_restart(): 

94 return 0 

95 self.stage_files() 

96 

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) 

119 

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.') 

126 

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 }) 

134 

135 # Save the DataFrame to a CSV file 

136 df.to_csv(self.stage_io_dict["out"]["output_flip_flop_path"], index=False) 

137 

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) 

142 

143 return self.return_code 

144 

145 

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() 

151 

152 

153lpp_flip_flop.__doc__ = LPPFlipFlop.__doc__ 

154main = LPPFlipFlop.get_main(lpp_flip_flop, "Find flip-flop events in a lipid bilayer.") 

155 

156if __name__ == '__main__': 

157 main()