Coverage for biobb_cmip/cmip/cmip_prepare_structure.py: 75%

61 statements  

« prev     ^ index     » next       coverage.py v7.6.10, created at 2025-01-28 09:52 +0000

1#!/usr/bin/env python3 

2 

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

4import argparse 

5from typing import Optional 

6import warnings 

7from pathlib import Path 

8from biobb_common.generic.biobb_object import BiobbObject 

9from biobb_common.configuration import settings 

10from biobb_common.tools import file_utils as fu 

11from biobb_common.tools.file_utils import launchlogger 

12 

13# Write the CMIP PDB 

14from biobb_cmip.cmip.common import write_cmip_pdb 

15# Dani's methods using a topology and a PDB file 

16from biobb_cmip.cmip.common import get_topology_cmip_elements_canonical 

17from biobb_cmip.cmip.common import get_topology_charges 

18# JLG methods using just the PDB file 

19from biobb_cmip.cmip.common import get_pdb_charges 

20from biobb_cmip.cmip.common import get_pdb_cmip_elements_canonical 

21 

22 

23class CmipPrepareStructure(BiobbObject): 

24 """ 

25 | biobb_cmip PrepareStructure 

26 | Generate a CMIP suitable PDB input. 

27 | Generate a CMIP suitable PDB input from a common PDB file or a Topology + PDB file. 

28 

29 Args: 

30 input_pdb_path (str): Path to the input PDB file. File type: input. `Sample file <https://github.com/bioexcel/biobb_cmip/raw/master/biobb_cmip/test/data/cmip/egfr.pdb>`_. Accepted formats: pdb (edam:format_1476). 

31 input_topology_path (str) (Optional): Path to the input topology path. File type: input. `Sample file <https://github.com/bioexcel/biobb_cmip/raw/master/biobb_cmip/test/data/cmip/egfr_topology.zip>`_. Accepted formats: zip (edam:format_3987), top (edam:format_3880), psf (edam:format_3882), prmtop (edam:format_3881). 

32 output_cmip_pdb_path (str): Path to the output PDB file. File type: output. `Sample file <https://github.com/bioexcel/biobb_cmip/raw/master/biobb_cmip/test/reference/cmip/egfr_cmip.pdb>`_. Accepted formats: pdb (edam:format_1476). 

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

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

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

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

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

38 * **container_image** (*str*) - ("cmip/cmip:latest") Container Image identifier. 

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

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

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

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

43 

44 

45 Examples: 

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

47 

48 from biobb_cmip.cmip.prepare_structure import prepare_structure 

49 prop = { } 

50 prepare_structure(input_pdb_path='/path/to/myStructure.pdb', 

51 output_cmip_pdb_path='/path/to/newStructure.pdb', 

52 properties=prop) 

53 

54 Info: 

55 * wrapped_software: 

56 * name: CMIP cmip 

57 * version: 2.7.0 

58 * license: Apache-2.0 

59 * ontology: 

60 * name: EDAM 

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

62 """ 

63 

64 def __init__(self, input_pdb_path: str, output_cmip_pdb_path: str, input_topology_path: Optional[str] = None, properties: Optional[dict] = None, **kwargs) -> None: 

65 properties = properties or {} 

66 

67 # Call parent class constructor 

68 super().__init__(properties) 

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

70 

71 # Input/Output files 

72 self.io_dict = { 

73 "in": {"input_pdb_path": input_pdb_path, "input_topology_path": input_topology_path}, 

74 "out": {"output_cmip_pdb_path": output_cmip_pdb_path} 

75 } 

76 

77 # Check the properties 

78 self.check_properties(properties) 

79 self.check_arguments() 

80 

81 @launchlogger 

82 def launch(self) -> int: 

83 """Execute the :class:`Cmip <cmip.cmip.PrepareStructure>` object.""" 

84 # Setup Biobb 

85 if self.check_restart(): 

86 return 0 

87 

88 # Dani's method 

89 if self.io_dict['in']['input_topology_path']: 

90 top_file = self.io_dict['in']['input_topology_path'] 

91 if self.io_dict['in']['input_topology_path'].lower().endswith(".zip"): 

92 # Unzip topology to topology_out 

93 top_file = fu.unzip_top(zip_file=self.io_dict['in']['input_topology_path'], out_log=self.out_log) 

94 top_dir = str(Path(top_file).parent) 

95 self.tmp_files.append(top_dir) 

96 

97 with warnings.catch_warnings(): 

98 warnings.filterwarnings("ignore", category=UserWarning) 

99 fu.log(f'Reading: {top_file} to extract charges', self.out_log, self.global_log) 

100 charges_list = get_topology_charges(top_file) 

101 fu.log(f'Reading: {top_file} to extract elements', self.out_log, self.global_log) 

102 elements_list = get_topology_cmip_elements_canonical(top_file) 

103 two_letter_elements = {"CL": "Cl", "NA": "Na", "ZN": "Zn", "MG": "Mg"} 

104 elements_list = [two_letter_elements.get(element, element) for element in elements_list] 

105 

106 # JLG's method 

107 else: 

108 charges_list = get_pdb_charges(self.io_dict['in']['input_pdb_path']) 

109 elements_list = get_pdb_cmip_elements_canonical(self.io_dict['in']['input_pdb_path']) 

110 

111 write_cmip_pdb(self.io_dict['in']['input_pdb_path'], 

112 self.io_dict['out']['output_cmip_pdb_path'], 

113 charges_list, 

114 elements_list) 

115 

116 ################################### 

117 

118 # remove temporary folder(s) 

119 self.remove_tmp_files() 

120 

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

122 

123 return 0 

124 

125 

126def cmip_prepare_structure(input_pdb_path: str, output_cmip_pdb_path: str, input_topology_path: Optional[str] = None, 

127 properties: Optional[dict] = None, **kwargs) -> int: 

128 """Create :class:`Cmip <cmip.cmip.PrepareStructure>` class and 

129 execute the :meth:`launch() <cmip.cmip.PrepareStructure.launch>` method.""" 

130 

131 return CmipPrepareStructure(input_pdb_path=input_pdb_path, output_cmip_pdb_path=output_cmip_pdb_path, 

132 input_topology_path=input_topology_path, properties=properties, 

133 **kwargs).launch() 

134 

135 cmip_prepare_structure.__doc__ = CmipPrepareStructure.__doc__ 

136 

137 

138def main(): 

139 parser = argparse.ArgumentParser(description="Wrapper of the cmip prepare_structure module.", 

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

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

142 

143 # Specific args of each building block 

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

145 required_args.add_argument('--input_pdb_path', required=True) 

146 required_args.add_argument('--output_cmip_pdb_path', required=True) 

147 parser.add_argument('--input_topology_path', required=False) 

148 

149 args = parser.parse_args() 

150 config = args.config if args.config else None 

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

152 

153 # Specific call of each building block 

154 cmip_prepare_structure(input_pdb_path=args.input_pdb_path, 

155 output_cmip_pdb_path=args.output_cmip_pdb_path, 

156 input_topology_path=args.input_topology_path, 

157 properties=properties) 

158 

159 

160if __name__ == '__main__': 

161 main()