Coverage for biobb_pmx/pmxbiobb/pmxmerge_ff.py: 94%

51 statements  

« prev     ^ index     » next       coverage.py v7.14.1, created at 2026-05-29 06:59 +0000

1#!/usr/bin/env python3 

2 

3"""Module containing the PMX merge_ff class and the command line interface.""" 

4 

5import glob 

6import os 

7import sys 

8from pathlib import Path 

9from typing import Optional 

10 

11from biobb_common.generic.biobb_object import BiobbObject 

12from biobb_common.tools import file_utils as fu 

13from biobb_common.tools.file_utils import launchlogger 

14from pmx import ligand_alchemy # type: ignore 

15 

16 

17class Pmxmerge_ff(BiobbObject): 

18 """ 

19 | biobb_pmx Pmxmerge_ff 

20 | Wrapper class for the `PMX merge_ff <https://github.com/deGrootLab/pmx>`_ module. 

21 | Merge ligand topology files. 

22 

23 Args: 

24 input_topology_path (str): Path to the input ligand topologies as a zip file containing a list of itp files. File type: input. `Sample file <https://github.com/bioexcel/biobb_pmx/raw/master/biobb_pmx/test/data/pmx/itps_to_merge.zip>`_. Accepted formats: zip (edam:format_3987). 

25 output_topology_path (str): Path to the merged ligand topology file. File type: output. `Sample file <https://github.com/bioexcel/biobb_pmx/raw/master/biobb_pmx/test/reference/pmx/ref_mergedTopology.itp>`_. Accepted formats: itp (edam:format_3883). 

26 properties (dic): 

27 * **remove_tmp** (*bool*) - (True) [WF property] Remove temporal files. 

28 * **restart** (*bool*) - (False) [WF property] Do not execute if output files exist. 

29 * **sandbox_path** (*str*) - ("./") [WF property] Parent path to the sandbox directory. 

30 

31 Examples: 

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

33 

34 from biobb_pmx.pmxbiobb.pmxmerge_ff import pmxmerge_ff 

35 prop = { 

36 'remove_tmp' : True 

37 } 

38 pmxmerge_ff(input_topology_path='/path/to/myTopologies.zip', 

39 output_topology_path='/path/to/myMergedTopology.itp', 

40 properties=prop) 

41 

42 Info: 

43 * wrapped_software: 

44 * name: PMX merge_ff 

45 * version: >=1.0.1 

46 * license: GNU 

47 * ontology: 

48 * name: EDAM 

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

50 

51 """ 

52 

53 def __init__( 

54 self, 

55 input_topology_path: str, 

56 output_topology_path: str, 

57 properties: Optional[dict] = None, 

58 **kwargs, 

59 ) -> 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_topology_path": input_topology_path}, 

69 "out": {"output_topology_path": output_topology_path}, 

70 } 

71 

72 # Properties specific for BB 

73 # None yet 

74 

75 # Properties common in all PMX BB 

76 self.gmx_lib = properties.get("gmx_lib", None) 

77 if not self.gmx_lib and os.environ.get("CONDA_PREFIX", ""): 

78 python_version = f"{sys.version_info.major}.{sys.version_info.minor}" 

79 self.gmx_lib = str( 

80 Path(os.environ.get("CONDA_PREFIX", "")).joinpath( 

81 f"lib/python{python_version}/site-packages/pmx/data/mutff/" 

82 ) 

83 ) 

84 if properties.get("container_path"): 

85 self.gmx_lib = str( 

86 Path("/usr/local/").joinpath( 

87 "lib/python3.7/site-packages/pmx/data/mutff/" 

88 ) 

89 ) 

90 

91 # Check the properties 

92 self.check_properties(properties) 

93 self.check_arguments() 

94 

95 @launchlogger 

96 def launch(self) -> int: 

97 """Execute the :class:`Pmxmerge_ff <pmx.pmxmerge_ff.Pmxmerge_ff>` pmx.pmxmerge_ff.Pmxmerge_ff object.""" 

98 

99 # Setup Biobb 

100 if self.check_restart(): 

101 return 0 

102 self.stage_files() 

103 

104 # Creating temporary folder 

105 tmp_folder = fu.create_unique_dir() 

106 fu.log("Creating %s temporary folder" % tmp_folder, self.out_log) 

107 

108 fu.unzip_list( 

109 self.stage_io_dict["in"]["input_topology_path"], 

110 tmp_folder, 

111 out_log=self.out_log, 

112 ) 

113 files = glob.glob(tmp_folder + "/*.itp") 

114 ffsIn_list = [] 

115 for itp in files: 

116 ffsIn_list.append(itp) 

117 

118 fu.log("Running merge_FF_files from pmx package...\n", self.out_log) 

119 ligand_alchemy._merge_FF_files( 

120 self.stage_io_dict["out"]["output_topology_path"], ffsIn=ffsIn_list 

121 ) 

122 # ffsIn=[self.stage_io_dict["in"]["input_topology1_path"],self.stage_io_dict["in"]["input_topology2_path"]] ) 

123 

124 fu.log("Exit code 0\n", self.out_log) 

125 

126 if self.gmx_lib: 

127 self.env_vars_dict["GMXLIB"] = self.gmx_lib 

128 

129 # Run Biobb block 

130 # self.run_biobb() 

131 

132 # Copy files to host 

133 self.copy_to_host() 

134 

135 self.tmp_files.append(tmp_folder) 

136 self.remove_tmp_files() 

137 

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

139 return self.return_code 

140 

141 

142def pmxmerge_ff( 

143 input_topology_path: str, 

144 output_topology_path: str, 

145 properties: Optional[dict] = None, 

146 **kwargs, 

147) -> int: 

148 """Create the :class:`Pmxmerge_ff <pmx.pmxmerge_ff.Pmxmerge_ff>` class and 

149 execute the :meth:`launch() <pmx.pmxmerge_ff.Pmxmerge_ff.launch> method.""" 

150 return Pmxmerge_ff(**dict(locals())).launch() 

151 

152 

153pmxmerge_ff.__doc__ = Pmxmerge_ff.__doc__ 

154main = Pmxmerge_ff.get_main(pmxmerge_ff, "Run PMX merge_ff module") 

155 

156if __name__ == "__main__": 

157 main()