Coverage for biobb_flexdyn/flexdyn/nolb_nma.py: 80%

59 statements  

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

1#!/usr/bin/env python3 

2 

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

4import argparse 

5from typing import Optional 

6import shutil 

7from pathlib import Path 

8from biobb_common.generic.biobb_object import BiobbObject 

9from biobb_common.configuration import settings 

10from biobb_common.tools.file_utils import launchlogger 

11 

12 

13class Nolb_nma(BiobbObject): 

14 """ 

15 | biobb_flexdyn Nolb_nma 

16 | Wrapper of the NOLB tool 

17 | Generate an ensemble of structures using the NOLB (NOn-Linear rigid Block) NMA tool. 

18 

19 Args: 

20 input_pdb_path (str): Input PDB file. File type: input. `Sample file <https://github.com/bioexcel/biobb_flexdyn/raw/master/biobb_flexdyn/test/data/flexdyn/structure.pdb>`_. Accepted formats: pdb (edam:format_1476). 

21 output_pdb_path (str): Output multi-model PDB file with the generated ensemble. File type: output. `Sample file <https://github.com/bioexcel/biobb_flexdyn/raw/master/biobb_flexdyn/test/reference/flexdyn/nolb_output.pdb>`_. Accepted formats: pdb (edam:format_1476). 

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

23 * **num_structs** (*int*) - (500) Number of structures to be generated 

24 * **cutoff** (*float*) - (5.0) This options specifies the interaction cutoff distance for the elastic network models (in angstroms), 5 by default. The Hessian matrix is constructed according to this interaction distance. Some artifacts should be expected for too short distances (< 5 Å). 

25 * **rmsd** (*float*) - (1.0) Maximum RMSd for decoy generation. 

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

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

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

29 

30 Examples: 

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

32 

33 from biobb_flexdyn.flexdyn.nolb_nma import nolb_nma 

34 prop = { 

35 'num_structs' : 20 

36 } 

37 nolb_nma( input_pdb_path='/path/to/structure.pdb', 

38 output_pdb_path='/path/to/output.pdb', 

39 properties=prop) 

40 

41 Info: 

42 * wrapped_software: 

43 * name: NOLB 

44 * version: >=1.9 

45 * license: other 

46 * ontology: 

47 * name: EDAM 

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

49 

50 """ 

51 

52 def __init__(self, input_pdb_path: str, output_pdb_path: str, 

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

54 

55 properties = properties or {} 

56 

57 # Call parent class constructor 

58 super().__init__(properties) 

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

60 

61 # Input/Output files 

62 self.io_dict = { 

63 'in': {'input_pdb_path': input_pdb_path}, 

64 'out': {'output_pdb_path': output_pdb_path} 

65 } 

66 

67 # Properties specific for BB 

68 self.properties = properties 

69 self.binary_path = properties.get('binary_path', 'NOLB') 

70 

71 self.num_structs = properties.get('num_structs', 500) 

72 # self.num_modes = properties.get('num_modes', 10) 

73 self.cutoff = properties.get('cutoff', 5.0) 

74 self.rmsd = properties.get('rmsd', 1.0) 

75 

76 # Check the properties 

77 self.check_properties(properties) 

78 self.check_arguments() 

79 

80 @launchlogger 

81 def launch(self): 

82 """Launches the execution of the FlexDyn NOLB module.""" 

83 

84 # Setup Biobb 

85 if self.check_restart(): 

86 return 0 

87 self.stage_files() 

88 

89 # Output temporary file 

90 out_file_prefix = Path(self.stage_io_dict.get("unique_dir", "")).joinpath("nolb_ensemble") 

91 out_file = Path(self.stage_io_dict.get("unique_dir", "")).joinpath("nolb_ensemble_nlb_decoys.pdb") 

92 

93 # Command line 

94 # ./NOLB 1ake_monomer.pdb -s 100 --rmsd 5 -m -o patata # Output: patata_nlb_decoys.pdb 

95 self.cmd = [self.binary_path, 

96 str(Path(self.stage_io_dict["in"]["input_pdb_path"]).relative_to(Path.cwd())), 

97 "-o", str(out_file_prefix), 

98 "-m" # Minimizing the generated structures by default 

99 ] 

100 

101 # Properties 

102 if self.num_structs: 

103 self.cmd.append('-s') 

104 self.cmd.append(str(self.num_structs)) 

105 

106 # Num modes is deactivated for the decoys generation. CHECK! 

107 # * **num_modes** (*int*) - (10) Number of non-trivial modes to compute, 10 by default. If this number exceeds the size of the Hessian matrix, it will be adapted accordingly. 

108 # if self.num_modes: 

109 # self.cmd.append('-n') 

110 # self.cmd.append(str(self.num_modes)) 

111 

112 if self.cutoff: 

113 self.cmd.append('-c') 

114 self.cmd.append(str(self.cutoff)) 

115 

116 if self.rmsd: 

117 self.cmd.append('--rmsd') 

118 self.cmd.append(str(self.rmsd)) 

119 

120 # --dist 1 -m --nSteps 5000 --tol 0.001 

121 self.cmd.append("--dist 1 --nSteps 5000 --tol 0.001") 

122 

123 # Run Biobb block 

124 self.run_biobb() 

125 

126 # Copying generated output file to the final (user-given) file name 

127 shutil.copy2(out_file, self.stage_io_dict["out"]["output_pdb_path"]) 

128 

129 # Copy files to host 

130 self.copy_to_host() 

131 

132 # remove temporary folder(s) 

133 # self.tmp_files.extend([ 

134 # self.stage_io_dict.get("unique_dir", "") 

135 # ]) 

136 self.remove_tmp_files() 

137 

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

139 

140 return self.return_code 

141 

142 

143def nolb_nma(input_pdb_path: str, output_pdb_path: str, 

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

145 """Create :class:`Nolb_nma <flexdyn.nolb_nma.Nolb_nma>`flexdyn.nolb_nma.Nolb_nma class and 

146 execute :meth:`launch() <flexdyn.nolb_nma.Nolb_nma.launch>` method""" 

147 

148 return Nolb_nma(input_pdb_path=input_pdb_path, 

149 output_pdb_path=output_pdb_path, 

150 properties=properties).launch() 

151 

152 nolb_nma.__doc__ = Nolb_nma.__doc__ 

153 

154 

155def main(): 

156 parser = argparse.ArgumentParser(description='Generate an ensemble of structures using the NOLB (NOn-Linear rigid Block) NMA tool.', formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, width=99999)) 

157 parser.add_argument('--config', required=False, help='Configuration file') 

158 

159 # Specific args 

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

161 required_args.add_argument('--input_pdb_path', required=True, help='Input structure file. Accepted formats: pdb') 

162 required_args.add_argument('--output_pdb_path', required=True, help='Output pdb file. Accepted formats: pdb.') 

163 

164 args = parser.parse_args() 

165 args.config = args.config or "{}" 

166 properties = settings.ConfReader(config=args.config).get_prop_dic() 

167 

168 # Specific call 

169 nolb_nma(input_pdb_path=args.input_pdb_path, 

170 output_pdb_path=args.output_pdb_path, 

171 properties=properties) 

172 

173 

174if __name__ == '__main__': 

175 main()