Coverage for biobb_mem/fatslim/fatslim_apl.py: 92%

52 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 FATSLiM Area per Lipid class and the command line interface.""" 

4from biobb_common.generic.biobb_object import BiobbObject 

5from biobb_common.tools.file_utils import launchlogger 

6from biobb_mem.fatslim.common import ignore_no_box, move_output_file 

7import MDAnalysis as mda 

8 

9 

10class FatslimAPL(BiobbObject): 

11 """ 

12 | biobb_mem FatslimAPL 

13 | Wrapper of the `FATSLiM area per lipid <https://pythonhosted.org/fatslim/documentation/apl.html>`_ module for area per lipid calculation. 

14 | FATSLiM is designed to provide efficient and robust analysis of physical parameters from MD trajectories, with a focus on processing large trajectory files quickly. 

15 

16 Args: 

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

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

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

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

21 properties (dic - Python dictionary object containing the tool parameters, not input/output files): 

22 * **lipid_selection** (*str*) - ("not protein and element P") Headgroups MDAnalysis `selection <https://docs.mdanalysis.org/stable/documentation_pages/selections.html>`_. 

23 * **protein_selection** (*str*) - ("protein and not element H") Protein selection interacting with the membrane. 

24 * **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 

25 * **limit** (*float*) - (10) This option allows user to specify the upper limit (in nm2) for a valid area per lipid value. 

26 * **begin_frame** (*int*) - (-1) First frame index to be used for analysis. 

27 * **end_frame** (*int*) - (-1) Last frame index to be used for analysis. 

28 * **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. 

29 * **return_hydrogen** (*bool*) - (False) Include hydrogen atoms in the output index file. 

30 * **binary_path** (*str*) - ("fatslim") Path to the fatslim executable binary. 

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.fatslim.fatslim_apl import fatslim_apl 

39 prop = { 

40 'lipid_selection': '(resname DPPC and name P8)', 

41 'cutoff': 3 

42 } 

43 fatslim_apl(input_top_path='/path/to/myTopology.tpr', 

44 input_traj_path='/path/to/myTrajectory.xtc', 

45 output_csv_path='/path/to/newIndex.ndx', 

46 properties=prop) 

47 

48 Info: 

49 * wrapped_software: 

50 * name: FATSLiM 

51 * version: 0.2.2 

52 * license: GNU 

53 * ontology: 

54 * name: EDAM 

55 * schema: http://edamontology.org/EDAM.owl 

56 

57 """ 

58 

59 def __init__(self, input_top_path, output_csv_path, input_traj_path=None, input_ndx_path=None, properties=None, **kwargs) -> None: 

60 properties = properties or {} 

61 

62 # Call parent class constructor 

63 super().__init__(properties) 

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

65 

66 # Input/Output files 

67 self.io_dict = { 

68 "in": {"input_top_path": input_top_path, 

69 "input_traj_path": input_traj_path, 

70 "input_ndx_path": input_ndx_path}, 

71 "out": {"output_csv_path": output_csv_path} 

72 } 

73 

74 # Properties specific for BB 

75 self.lipid_selection = properties.get('lipid_selection', "not protein and element P") 

76 self.protein_selection = properties.get('protein_selection', "protein and not element H") 

77 self.cutoff = properties.get('cutoff', 3) 

78 self.limit = properties.get('cutoff', 10) 

79 self.begin_frame = properties.get('begin_frame', -1) 

80 self.end_frame = properties.get('end_frame', -1) 

81 self.ignore_no_box = properties.get('ignore_no_box', False) 

82 self.binary_path = properties.get('binary_path', 'fatslim') 

83 self.properties = properties 

84 

85 # Check the properties 

86 self.check_properties(properties) 

87 self.check_arguments() 

88 

89 @launchlogger 

90 def launch(self) -> int: 

91 """Execute the :class:`FatslimAPL <fatslim.fatslim_apl.FatslimAPL>` object.""" 

92 

93 # Setup Biobb 

94 if self.check_restart(): 

95 return 0 

96 self.stage_files() 

97 

98 # Create index file using MDAnalysis 

99 u = mda.Universe(topology=self.stage_io_dict["in"]["input_top_path"], 

100 coordinates=self.stage_io_dict["in"].get("input_traj_path")) 

101 ignore_no_box(u, self.ignore_no_box, self.out_log, self.global_log) 

102 

103 # Build the index to select the atoms from the membrane 

104 if self.stage_io_dict["in"].get('input_ndx_path', None): 

105 tmp_ndx = self.stage_io_dict["in"]["input_ndx_path"] 

106 else: 

107 tmp_ndx = self.create_tmp_file('_apl_inp.ndx') 

108 with mda.selections.gromacs.SelectionWriter(tmp_ndx, mode='w') as ndx: 

109 ndx.write(u.select_atoms(self.lipid_selection), name='headgroups') 

110 ndx.write(u.select_atoms(self.protein_selection), name='protein') 

111 

112 if self.stage_io_dict["in"]["input_top_path"].endswith('gro'): 

113 cfg = self.stage_io_dict["in"]["input_top_path"] 

114 

115 else: 

116 # Convert topology .gro and add box dimensions if not available in the topology 

117 cfg = self.create_tmp_file('_output.gro') 

118 # Save as GRO file with box information 

119 u.atoms.write(cfg) 

120 

121 tmp_csv = self.create_tmp_file('_out.csv') 

122 # Build command 

123 self.cmd = [ 

124 self.binary_path, "apl", 

125 "-n", tmp_ndx, 

126 "-c", cfg, 

127 "--export-apl-raw", tmp_csv, 

128 "--apl-cutoff", str(self.cutoff), 

129 "--apl-limit", str(self.limit), 

130 "--begin-frame", str(self.begin_frame), 

131 "--end-frame", str(self.end_frame) 

132 ] 

133 

134 # Run Biobb block 

135 self.run_biobb() 

136 move_output_file(tmp_csv, self.stage_io_dict["out"]["output_csv_path"], 

137 self.out_log, self.global_log) 

138 # Copy files to host 

139 self.copy_to_host() 

140 # Remove temporary files 

141 self.remove_tmp_files() 

142 self.check_arguments(output_files_created=True, raise_exception=False) 

143 

144 return self.return_code 

145 

146 

147def fatslim_apl(input_top_path: str, 

148 output_csv_path: str, 

149 input_traj_path: str = None, 

150 input_ndx_path: str = None, 

151 properties: dict = None, 

152 **kwargs) -> int: 

153 """Execute the :class:`FatslimAPL <fatslim.fatslim_apl.FatslimAPL>` class and 

154 execute the :meth:`launch() <fatslim.fatslim_apl.FatslimAPL.launch>` method.""" 

155 return FatslimAPL(**dict(locals())).launch() 

156 

157 

158fatslim_apl.__doc__ = FatslimAPL.__doc__ 

159main = FatslimAPL.get_main(fatslim_apl, 'Calculate the area per lipid.') 

160 

161if __name__ == '__main__': 

162 main()