Coverage for biobb_dna/stiffness/basepair_stiffness.py: 80%

83 statements  

« prev     ^ index     » next       coverage.py v7.5.1, created at 2024-05-07 09:06 +0000

1#!/usr/bin/env python3 

2 

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

4import argparse 

5from pathlib import Path 

6 

7import pandas as pd 

8import numpy as np 

9import matplotlib.pyplot as plt 

10 

11from biobb_common.generic.biobb_object import BiobbObject 

12from biobb_common.configuration import settings 

13from biobb_common.tools import file_utils as fu 

14from biobb_common.tools.file_utils import launchlogger 

15from biobb_dna.utils.loader import load_data 

16 

17 

18class BPStiffness(BiobbObject): 

19 """ 

20 | biobb_dna BPStiffness 

21 | Calculate stiffness constants matrix between all six helical parameters for a single base pair step. 

22 

23 Args: 

24 input_filename_shift (str): Path to csv file with data for helical parameter 'shift'. File type: input. `Sample file <https://raw.githubusercontent.com/bioexcel/biobb_dna/master/biobb_dna/test/data/stiffness/series_shift_AA.csv>`_. Accepted formats: csv (edam:format_3752) 

25 input_filename_slide (str): Path to csv file with data for helical parameter 'slide'. File type: input. `Sample file <https://raw.githubusercontent.com/bioexcel/biobb_dna/master/biobb_dna/test/data/stiffness/series_slide_AA.csv>`_. Accepted formats: csv (edam:format_3752) 

26 input_filename_rise (str): Path to csv file with data for helical parameter 'rise'. File type: input. `Sample file <https://raw.githubusercontent.com/bioexcel/biobb_dna/master/biobb_dna/test/data/stiffness/series_rise_AA.csv>`_. Accepted formats: csv (edam:format_3752) 

27 input_filename_tilt (str): Path to csv file with data for helical parameter 'tilt'. File type: input. `Sample file <https://raw.githubusercontent.com/bioexcel/biobb_dna/master/biobb_dna/test/data/stiffness/series_tilt_AA.csv>`_. Accepted formats: csv (edam:format_3752) 

28 input_filename_roll (str): Path to csv file with data for helical parameter 'roll'. File type: input. `Sample file <https://raw.githubusercontent.com/bioexcel/biobb_dna/master/biobb_dna/test/data/stiffness/series_roll_AA.csv>`_. Accepted formats: csv (edam:format_3752) 

29 input_filename_twist (str): Path to csv file with data for helical parameter 'twist'. File type: input. `Sample file <https://raw.githubusercontent.com/bioexcel/biobb_dna/master/biobb_dna/test/data/stiffness/series_twist_AA.csv>`_. Accepted formats: csv (edam:format_3752) 

30 output_csv_path (str): Path to directory where stiffness matrix file is saved as a csv file. File type: output. `Sample file <https://raw.githubusercontent.com/bioexcel/biobb_dna/master/biobb_dna/test/reference/stiffness/stiffbp_ref.csv>`_. Accepted formats: csv (edam:format_3752) 

31 output_jpg_path (str): Path to directory where stiffness heatmap image is saved as a jpg file. File type: output. `Sample file <https://raw.githubusercontent.com/bioexcel/biobb_dna/master/biobb_dna/test/reference/stiffness/stiffbp_ref.jpg>`_. Accepted formats: jpg (edam:format_3579) 

32 properties (dict): 

33 * **KT** (*float*) - (0.592186827) Value of Boltzmann temperature factor. 

34 * **scaling** (*list*) - ([1, 1, 1, 10.6, 10.6, 10.6]) Values by which to scale stiffness. Positions correspond to helical parameters in the order: shift, slide, rise, tilt, roll, twist. 

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

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

37 

38 Examples: 

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

40 

41 from biobb_dna.stiffness.basepair_stiffness import basepair_stiffness 

42 

43 prop = { 

44 'KT': 0.592186827, 

45 'scaling': [1, 1, 1, 10.6, 10.6, 10.6] 

46 } 

47 basepair_stiffness( 

48 input_filename_shift='path/to/basepair/shift.csv', 

49 input_filename_slide='path/to/basepair/slide.csv', 

50 input_filename_rise='path/to/basepair/rise.csv', 

51 input_filename_tilt='path/to/basepair/tilt.csv', 

52 input_filename_roll='path/to/basepair/roll.csv', 

53 input_filename_twist='path/to/basepair/twist.csv', 

54 output_csv_path='path/to/output/file.csv', 

55 output_jpg_path='path/to/output/plot.jpg', 

56 properties=prop) 

57 Info: 

58 * wrapped_software: 

59 * name: In house 

60 * license: Apache-2.0 

61 * ontology: 

62 * name: EDAM 

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

64 

65 """ 

66 

67 def __init__(self, input_filename_shift, input_filename_slide, 

68 input_filename_rise, input_filename_tilt, 

69 input_filename_roll, input_filename_twist, 

70 output_csv_path, output_jpg_path, properties=None, **kwargs) -> None: 

71 properties = properties or {} 

72 

73 # Call parent class constructor 

74 super().__init__(properties) 

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

76 

77 # Input/Output files 

78 self.io_dict = { 

79 'in': { 

80 'input_filename_shift': input_filename_shift, 

81 'input_filename_slide': input_filename_slide, 

82 'input_filename_rise': input_filename_rise, 

83 'input_filename_tilt': input_filename_tilt, 

84 'input_filename_roll': input_filename_roll, 

85 'input_filename_twist': input_filename_twist 

86 }, 

87 'out': { 

88 'output_csv_path': output_csv_path, 

89 'output_jpg_path': output_jpg_path 

90 } 

91 } 

92 

93 self.properties = properties 

94 self.KT = properties.get( 

95 "KT", 0.592186827) 

96 self.scaling = properties.get( 

97 "scaling", [1, 1, 1, 10.6, 10.6, 10.6]) 

98 

99 # Check the properties 

100 self.check_properties(properties) 

101 self.check_arguments() 

102 

103 @launchlogger 

104 def launch(self) -> int: 

105 """Execute the :class:`BPStiffness <stiffness.basepair_stiffness.BPStiffness>` object.""" 

106 

107 # Setup Biobb 

108 if self.check_restart(): 

109 return 0 

110 self.stage_files() 

111 

112 # Creating temporary folder 

113 self.tmp_folder = fu.create_unique_dir(prefix="bp_stiffness_") 

114 fu.log('Creating %s temporary folder' % self.tmp_folder, self.out_log) 

115 

116 # read input 

117 shift = load_data( 

118 self.io_dict["in"]["input_filename_shift"]) 

119 slide = load_data( 

120 self.io_dict["in"]["input_filename_slide"]) 

121 rise = load_data( 

122 self.io_dict["in"]["input_filename_rise"]) 

123 tilt = load_data( 

124 self.io_dict["in"]["input_filename_tilt"]) 

125 roll = load_data( 

126 self.io_dict["in"]["input_filename_roll"]) 

127 twist = load_data( 

128 self.io_dict["in"]["input_filename_twist"]) 

129 

130 # build matrix cols_arr from helpar input data files 

131 coordinates = ["shift", "slide", "rise", "tilt", "roll", "twist"] 

132 basepairname = shift.columns[0] 

133 helpar_matrix = pd.concat( 

134 [shift, slide, rise, tilt, roll, twist], axis=1) 

135 helpar_matrix.columns = coordinates 

136 # covariance 

137 cov_df = helpar_matrix.cov() 

138 # stiffness 

139 stiff = np.linalg.inv(cov_df) * self.KT 

140 stiff_diag = stiff * np.array(self.scaling) 

141 stiff_df = pd.DataFrame( 

142 stiff_diag, 

143 columns=cov_df.columns, 

144 index=cov_df.index) 

145 stiff_df.index.name = basepairname 

146 

147 # save csv data 

148 stiff_df.to_csv(Path(self.io_dict["out"]["output_csv_path"])) 

149 

150 # create heatmap 

151 fig, axs = plt.subplots(1, 1, dpi=300, tight_layout=True) 

152 axs.pcolor(stiff_df) 

153 # Loop over data dimensions and create text annotations. 

154 for i in range(len(stiff_df)): 

155 for j in range(len(stiff_df)): 

156 axs.text( 

157 j+.5, 

158 i+.5, 

159 f"{stiff_df[coordinates[j]].loc[coordinates[i]]:.2f}", 

160 ha="center", 

161 va="center", 

162 color="w") 

163 axs.text( 

164 0, -1.35, 

165 "Units:\n" 

166 "Diagonal Shift/Slide/Rise in kcal/(mol*Ų), Diagonal Tilt/Roll/Twist in kcal/(mol*degree²)\n" 

167 "Out of Diagonal: Shift/Slide/Rise in kcal/(mol*Å), Out of Diagonal Tilt/Roll/Twist in kcal/(mol*degree)", 

168 fontsize=6) 

169 axs.set_xticks([i + 0.5 for i in range(len(stiff_df))]) 

170 axs.set_xticklabels(stiff_df.columns, rotation=90) 

171 axs.set_yticks([i+0.5 for i in range(len(stiff_df))]) 

172 axs.set_yticklabels(stiff_df.index) 

173 axs.set_title( 

174 f"Stiffness Constants for Base Pair Step \'{basepairname}\'") 

175 fig.tight_layout() 

176 fig.savefig( 

177 self.io_dict['out']['output_jpg_path'], 

178 format="jpg") 

179 plt.close() 

180 

181 # Remove temporary file(s) 

182 self.tmp_files.extend([ 

183 self.stage_io_dict.get("unique_dir"), 

184 self.tmp_folder 

185 ]) 

186 self.remove_tmp_files() 

187 

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

189 

190 return 0 

191 

192 

193def basepair_stiffness( 

194 input_filename_shift: str, input_filename_slide: str, 

195 input_filename_rise: str, input_filename_tilt: str, 

196 input_filename_roll: str, input_filename_twist: str, 

197 output_csv_path: str, output_jpg_path: str, properties: dict = None, **kwargs) -> int: 

198 """Create :class:`BPStiffness <stiffness.basepair_stiffness.BPStiffness>` class and 

199 execute the :meth:`launch() <stiffness.basepair_stiffness.BPStiffness.BPStiffness.launch>` method.""" 

200 

201 return BPStiffness( 

202 input_filename_shift=input_filename_shift, 

203 input_filename_slide=input_filename_slide, 

204 input_filename_rise=input_filename_rise, 

205 input_filename_tilt=input_filename_tilt, 

206 input_filename_roll=input_filename_roll, 

207 input_filename_twist=input_filename_twist, 

208 output_csv_path=output_csv_path, 

209 output_jpg_path=output_jpg_path, 

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

211 

212 

213def main(): 

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

215 parser = argparse.ArgumentParser(description='Calculate stiffness constants matrix between all six helical parameters for a single base pair step.', 

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

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

218 

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

220 required_args.add_argument('--input_filename_shift', required=True, 

221 help='Path to csv file with shift inputs. Accepted formats: csv.') 

222 required_args.add_argument('--input_filename_slide', required=True, 

223 help='Path to csv file with slide inputs. Accepted formats: csv.') 

224 required_args.add_argument('--input_filename_rise', required=True, 

225 help='Path to csv file with rise inputs. Accepted formats: csv.') 

226 required_args.add_argument('--input_filename_tilt', required=True, 

227 help='Path to csv file with tilt inputs. Accepted formats: csv.') 

228 required_args.add_argument('--input_filename_roll', required=True, 

229 help='Path to csv file with roll inputs. Accepted formats: csv.') 

230 required_args.add_argument('--input_filename_twist', required=True, 

231 help='Path to csv file with twist inputs. Accepted formats: csv.') 

232 required_args.add_argument('--output_csv_path', required=True, 

233 help='Path to output covariance data file. Accepted formats: csv.') 

234 required_args.add_argument('--output_jpg_path', required=True, 

235 help='Path to output covariance data file. Accepted formats: csv.') 

236 

237 args = parser.parse_args() 

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

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

240 

241 basepair_stiffness( 

242 input_filename_shift=args.input_filename_shift, 

243 input_filename_slide=args.input_filename_slide, 

244 input_filename_rise=args.input_filename_rise, 

245 input_filename_tilt=args.input_filename_tilt, 

246 input_filename_roll=args.input_filename_roll, 

247 input_filename_twist=args.input_filename_twist, 

248 output_csv_path=args.output_csv_path, 

249 output_jpg_path=args.output_jpg_path, 

250 properties=properties) 

251 

252 

253if __name__ == '__main__': 

254 main()