Coverage for biobb_structure_utils/utils/remove_ligand.py: 80%

54 statements  

« prev     ^ index     » next       coverage.py v7.5.3, created at 2024-06-14 19:03 +0000

1#!/usr/bin/env python3 

2 

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

4import argparse 

5from pathlib import Path 

6from biobb_common.configuration import settings 

7from biobb_common.generic.biobb_object import BiobbObject 

8from biobb_common.tools import file_utils as fu 

9from biobb_common.tools.file_utils import launchlogger 

10from biobb_structure_utils.gro_lib.gro import Gro 

11 

12 

13class RemoveLigand(BiobbObject): 

14 """ 

15 | biobb_structure_utils RemoveLigand 

16 | Class to remove the selected ligand atoms from a 3D structure. 

17 | Remove the selected ligand atoms from a 3D structure. 

18 

19 Args: 

20 input_structure_path (str): Input structure file path. File type: input. `Sample file <https://github.com/bioexcel/biobb_structure_utils/raw/master/biobb_structure_utils/test/data/utils/WT_aq4_md_1.pdb>`_. Accepted formats: pdb (edam:format_1476), gro (edam:format_2033). 

21 output_structure_path (str): Output structure file path. File type: output. `Sample file <https://github.com/bioexcel/biobb_structure_utils/raw/master/biobb_structure_utils/test/reference/utils/WT_apo_md_1.pdb>`_. Accepted formats: pdb (edam:format_1476), gro (edam:format_2033). 

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

23 * **ligand** (*str*) - ("AQ4") Residue code of the ligand to be removed. 

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

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

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

27 

28 Examples: 

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

30 

31 from biobb_structure_utils.utils.remove_ligand import remove_ligand 

32 prop = { 

33 'ligand': 'AQ4' 

34 } 

35 remove_ligand(input_structure_path='/path/to/myStructure.pdb', 

36 output_structure_path='/path/to/newStructure.pdb', 

37 properties=prop) 

38 

39 Info: 

40 * wrapped_software: 

41 * name: In house 

42 * license: Apache-2.0 

43 * ontology: 

44 * name: EDAM 

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

46 

47 """ 

48 

49 def __init__(self, input_structure_path, output_structure_path, properties=None, **kwargs) -> None: 

50 properties = properties or {} 

51 

52 # Call parent class constructor 

53 super().__init__(properties) 

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

55 

56 # Input/Output files 

57 self.io_dict = { 

58 "in": {"input_structure_path": input_structure_path}, 

59 "out": {"output_structure_path": output_structure_path} 

60 } 

61 

62 # Properties specific for BB 

63 self.ligand = properties.get('ligand', 'AQ4') 

64 

65 # Check the properties 

66 self.check_properties(properties) 

67 self.check_arguments() 

68 

69 @launchlogger 

70 def launch(self) -> int: 

71 """Execute the :class:`RemoveLigand <utils.remove_ligand.RemoveLigand>` utils.remove_ligand.RemoveLigand object.""" 

72 

73 # Setup Biobb 

74 if self.check_restart(): 

75 return 0 

76 self.stage_files() 

77 

78 # Business code 

79 extension = Path(self.stage_io_dict['in']['input_structure_path']).suffix.lower() 

80 if extension.lower() == '.gro': 

81 fu.log('GRO format detected, removing all atoms from residues named %s' % self.ligand, self.out_log) 

82 gro_st = Gro() 

83 gro_st.read_gro_file(self.stage_io_dict['in']['input_structure_path']) 

84 gro_st.remove_residues([self.ligand]) 

85 gro_st.write_gro_file(self.stage_io_dict['out']['output_structure_path']) 

86 

87 else: 

88 fu.log('PDB format detected, removing all atoms from residues named %s' % self.ligand, self.out_log) 

89 # Direct aproach solution implemented to avoid the issues 

90 # presented in commit message (c92aab9604a6a31d13f4170ff47b231df0a588ef) 

91 # with the Biopython library 

92 with open(self.stage_io_dict['in']['input_structure_path'], "r") as input_pdb, open(self.stage_io_dict['out']['output_structure_path'], "w") as output_pdb: 

93 for line in input_pdb: 

94 if len(line) > 19 and self.ligand.lower() in line[17:20].lower(): 

95 continue 

96 output_pdb.write(line) 

97 

98 self.return_code = 0 

99 ########## 

100 

101 # Copy files to host 

102 self.copy_to_host() 

103 

104 # Remove temporal files 

105 self.tmp_files.append(self.stage_io_dict.get("unique_dir")) 

106 self.remove_tmp_files() 

107 

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

109 

110 return self.return_code 

111 

112 

113def remove_ligand(input_structure_path: str, output_structure_path: str, properties: dict = None, **kwargs) -> int: 

114 """Execute the :class:`RemoveLigand <utils.remove_ligand.RemoveLigand>` class and 

115 execute the :meth:`launch() <utils.remove_ligand.RemoveLigand.launch>` method.""" 

116 

117 return RemoveLigand(input_structure_path=input_structure_path, 

118 output_structure_path=output_structure_path, 

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

120 

121 

122def main(): 

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

124 parser = argparse.ArgumentParser(description="Remove the selected ligand atoms from a 3D structure.", formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, width=99999)) 

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

126 

127 # Specific args of each building block 

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

129 required_args.add_argument('-i', '--input_structure_path', required=True, help="Input structure file name") 

130 required_args.add_argument('-o', '--output_structure_path', required=True, help="Output structure file name") 

131 

132 args = parser.parse_args() 

133 config = args.config if args.config else None 

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

135 

136 # Specific call of each building block 

137 remove_ligand(input_structure_path=args.input_structure_path, 

138 output_structure_path=args.output_structure_path, 

139 properties=properties) 

140 

141 

142if __name__ == '__main__': 

143 main()