Coverage for biobb_gromacs/gromacs/gmxselect.py: 67%

70 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-25 09:23 +0000

1#!/usr/bin/env python3 

2 

3"""Module containing the Select class and the command line interface.""" 

4import argparse 

5from typing import Optional 

6from pathlib import Path 

7from biobb_common.generic.biobb_object import BiobbObject 

8from biobb_common.configuration import settings 

9from biobb_common.tools import file_utils as fu 

10from biobb_common.tools.file_utils import launchlogger 

11from biobb_gromacs.gromacs.common import get_gromacs_version 

12 

13 

14class Gmxselect(BiobbObject): 

15 """ 

16 | biobb_gromacs Gmxselect 

17 | Wrapper of the `GROMACS select <http://manual.gromacs.org/current/onlinehelp/gmx-select.html>`_ module. 

18 | The GROMACS select module writes out basic data about dynamic selections. It can be used for some simple analyses, or the output can be combined with output from other programs and/or external analysis programs to calculate more complex things. 

19 

20 Args: 

21 input_structure_path (str): Path to the input GRO/PDB/TPR file. File type: input. `Sample file <https://github.com/bioexcel/biobb_gromacs/raw/master/biobb_gromacs/test/data/gromacs/make_ndx.tpr>`_. Accepted formats: pdb (edam:format_1476), gro (edam:format_2033), tpr (edam:format_2333). 

22 output_ndx_path (str): Path to the output index NDX file. File type: output. `Sample file <https://github.com/bioexcel/biobb_gromacs/raw/master/biobb_gromacs/test/reference/gromacs/ref_select.ndx>`_. Accepted formats: ndx (edam:format_2033). 

23 input_ndx_path (str) (Optional): Path to the input index NDX file. File type: input. Accepted formats: ndx (edam:format_2033). 

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

25 * **selection** (*str*) - ("a CA C N O") Heavy atoms. Atom selection string. 

26 * **append** (*bool*) - (False) Append the content of the input_ndx_path to the output_ndx_path. 

27 * **binary_path** (*str*) - ("gmx") Path to the GROMACS executable binary. 

28 * **gmx_lib** (*str*) - (None) Path set GROMACS GMXLIB environment variable. 

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

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

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

32 * **container_path** (*str*) - (None) Path to the binary executable of your container. 

33 * **container_image** (*str*) - ("gromacs/gromacs:latest") Container Image identifier. 

34 * **container_volume_path** (*str*) - ("/data") Path to an internal directory in the container. 

35 * **container_working_dir** (*str*) - (None) Path to the internal CWD in the container. 

36 * **container_user_id** (*str*) - (None) User number id to be mapped inside the container. 

37 * **container_shell_path** (*str*) - ("/bin/bash") Path to the binary executable of the container shell. 

38 

39 Examples: 

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

41 

42 from biobb_gromacs.gromacs.gmxselect import gmxselect 

43 prop = { 'selection': '"Mynewgroup" group "Protein-H" and not same residue as within 0.4 of resname ARG' } 

44 gmxselect(input_structure_path='/path/to/myStructure.gro', 

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

46 properties=prop) 

47 

48 Info: 

49 * wrapped_software: 

50 * name: GROMACS Gmxselect 

51 * version: 2024.5 

52 * license: LGPL 2.1 

53 * ontology: 

54 * name: EDAM 

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

56 """ 

57 

58 def __init__(self, input_structure_path: str, output_ndx_path: str, input_ndx_path: Optional[str] = None, 

59 properties: Optional[dict] = 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_structure_path": input_structure_path, "input_ndx_path": input_ndx_path}, 

69 "out": {"output_ndx_path": output_ndx_path} 

70 } 

71 

72 # Properties specific for BB 

73 self.selection = properties.get('selection', "a CA C N O") 

74 self.append = properties.get('append', False) 

75 

76 # Properties common in all GROMACS BB 

77 self.gmx_lib = properties.get('gmx_lib', None) 

78 self.binary_path = properties.get('binary_path', 'gmx') 

79 self.gmx_nobackup = properties.get('gmx_nobackup', True) 

80 self.gmx_nocopyright = properties.get('gmx_nocopyright', True) 

81 if self.gmx_nobackup: 

82 self.binary_path += ' -nobackup' 

83 if self.gmx_nocopyright: 

84 self.binary_path += ' -nocopyright' 

85 if not self.container_path: 

86 self.gmx_version = get_gromacs_version(self.binary_path) 

87 

88 # Check the properties 

89 self.check_properties(properties) 

90 self.check_arguments() 

91 

92 @launchlogger 

93 def launch(self) -> int: 

94 """Execute the :class:`Gmxselect <gromacs.gmxselect.Gmxselect>` object.""" 

95 

96 # Setup Biobb 

97 if self.check_restart(): 

98 return 0 

99 self.stage_files() 

100 

101 self.cmd = [self.binary_path, 'select', 

102 '-s', self.stage_io_dict["in"]["input_structure_path"], 

103 '-on', self.stage_io_dict["out"]["output_ndx_path"] 

104 ] 

105 

106 if self.stage_io_dict["in"].get("input_ndx_path") and Path( 

107 self.stage_io_dict["in"].get("input_ndx_path")).exists(): 

108 self.cmd.append('-n') 

109 self.cmd.append(self.stage_io_dict["in"].get("input_ndx_path")) 

110 

111 self.cmd.append('-select') 

112 self.cmd.append("\'"+self.selection+"\'") 

113 

114 if self.gmx_lib: 

115 self.env_vars_dict['GMXLIB'] = self.gmx_lib 

116 

117 # Run Biobb block 

118 self.run_biobb() 

119 

120 # Copy files to host 

121 self.copy_to_host() 

122 

123 if self.io_dict["in"].get("input_ndx_path"): 

124 if self.append: 

125 fu.log(f"Appending {self.io_dict['in'].get('input_ndx_path')} to {self.io_dict['out']['output_ndx_path']}", self.out_log, self.global_log) 

126 with open(self.io_dict["out"]["output_ndx_path"], 'a') as out_ndx_file: 

127 out_ndx_file.write('\n') 

128 with open(self.io_dict["in"].get("input_ndx_path", '')) as in_ndx_file: 

129 for line in in_ndx_file: 

130 out_ndx_file.write(line) 

131 

132 # Remove temporal files 

133 # self.tmp_files.append(self.stage_io_dict.get("unique_dir", '')) 

134 self.remove_tmp_files() 

135 

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

137 return self.return_code 

138 

139 

140def gmxselect(input_structure_path: str, output_ndx_path: str, 

141 input_ndx_path: Optional[str] = None, properties: Optional[dict] = None, 

142 **kwargs) -> int: 

143 """Create :class:`Gmxselect <gromacs.gmxselect.Gmxselect>` class and 

144 execute the :meth:`launch() <gromacs.gmxselect.Gmxselect.launch>` method.""" 

145 return Gmxselect(input_structure_path=input_structure_path, 

146 output_ndx_path=output_ndx_path, 

147 input_ndx_path=input_ndx_path, 

148 properties=properties, **kwargs).launch() 

149 

150 

151 gmxselect.__doc__ = Gmxselect.__doc__ 

152 

153 

154def main(): 

155 """Command line execution of this building block. Please check the command line documentation.""" 

156 parser = argparse.ArgumentParser(description="Wrapper for the GROMACS select module.", 

157 formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, width=99999)) 

158 parser.add_argument('-c', '--config', required=False, help="This file can be a YAML file, JSON file or JSON string") 

159 

160 # Specific args of each building block 

161 required_args = parser.add_argument_group('required arguments') 

162 required_args.add_argument('--input_structure_path', required=True) 

163 required_args.add_argument('--output_ndx_path', required=True) 

164 parser.add_argument('--input_ndx_path', required=False) 

165 

166 args = parser.parse_args() 

167 config = args.config if args.config else None 

168 properties = settings.ConfReader(config=config).get_prop_dic() 

169 

170 # Specific call of each building block 

171 gmxselect(input_structure_path=args.input_structure_path, 

172 output_ndx_path=args.output_ndx_path, 

173 input_ndx_path=args.input_ndx_path, 

174 properties=properties) 

175 

176 

177if __name__ == '__main__': 

178 main()