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

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.lib.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.10.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 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) 

118 

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

125 

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

133 

134 # Save the DataFrame to a CSV file 

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

136 

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) 

141 

142 return self.return_code 

143 

144 

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

150 

151 

152lpp_flip_flop.__doc__ = LPPFlipFlop.__doc__ 

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

154 

155if __name__ == '__main__': 

156 main()