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

65 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2025-12-15 18:49 +0000

1#!/usr/bin/env python3 

2 

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

4 

5from pathlib import Path 

6from typing import Optional 

7 

8import matplotlib.pyplot as plt 

9import numpy as np 

10import pandas as pd 

11from biobb_common.generic.biobb_object import BiobbObject 

12from biobb_common.tools.file_utils import launchlogger 

13 

14from biobb_dna.utils.common import _from_string_to_list 

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 | Calculate stiffness constants matrix between all six helical parameters for a single base pair step. 

23 

24 Args: 

25 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) 

26 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) 

27 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) 

28 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) 

29 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) 

30 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) 

31 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) 

32 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) 

33 properties (dict): 

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

35 * **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. 

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

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

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

39 

40 Examples: 

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

42 

43 from biobb_dna.stiffness.basepair_stiffness import basepair_stiffness 

44 

45 prop = { 

46 'KT': 0.592186827, 

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

48 } 

49 basepair_stiffness( 

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

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

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

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

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

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

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

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

58 properties=prop) 

59 Info: 

60 * wrapped_software: 

61 * name: In house 

62 * license: Apache-2.0 

63 * ontology: 

64 * name: EDAM 

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

66 

67 """ 

68 

69 def __init__( 

70 self, 

71 input_filename_shift, 

72 input_filename_slide, 

73 input_filename_rise, 

74 input_filename_tilt, 

75 input_filename_roll, 

76 input_filename_twist, 

77 output_csv_path, 

78 output_jpg_path, 

79 properties=None, 

80 **kwargs, 

81 ) -> None: 

82 properties = properties or {} 

83 

84 # Call parent class constructor 

85 super().__init__(properties) 

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

87 

88 # Input/Output files 

89 self.io_dict = { 

90 "in": { 

91 "input_filename_shift": input_filename_shift, 

92 "input_filename_slide": input_filename_slide, 

93 "input_filename_rise": input_filename_rise, 

94 "input_filename_tilt": input_filename_tilt, 

95 "input_filename_roll": input_filename_roll, 

96 "input_filename_twist": input_filename_twist, 

97 }, 

98 "out": { 

99 "output_csv_path": output_csv_path, 

100 "output_jpg_path": output_jpg_path, 

101 }, 

102 } 

103 

104 self.properties = properties 

105 self.KT = properties.get("KT", 0.592186827) 

106 self.scaling = [ 

107 int(elem) 

108 for elem in _from_string_to_list( 

109 properties.get("scaling", [1, 1, 1, 10.6, 10.6, 10.6]) 

110 ) 

111 ] 

112 

113 # Check the properties 

114 self.check_properties(properties) 

115 self.check_arguments() 

116 

117 @launchlogger 

118 def launch(self) -> int: 

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

120 

121 # Setup Biobb 

122 if self.check_restart(): 

123 return 0 

124 self.stage_files() 

125 

126 # read input 

127 shift = load_data(self.stage_io_dict["in"]["input_filename_shift"]) 

128 slide = load_data(self.stage_io_dict["in"]["input_filename_slide"]) 

129 rise = load_data(self.stage_io_dict["in"]["input_filename_rise"]) 

130 tilt = load_data(self.stage_io_dict["in"]["input_filename_tilt"]) 

131 roll = load_data(self.stage_io_dict["in"]["input_filename_roll"]) 

132 twist = load_data(self.stage_io_dict["in"]["input_filename_twist"]) 

133 

134 # build matrix cols_arr from helpar input data files 

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

136 basepairname = shift.columns[0] 

137 helpar_matrix = pd.concat([shift, slide, rise, tilt, roll, twist], axis=1) 

138 helpar_matrix.columns = coordinates 

139 # covariance 

140 cov_df = helpar_matrix.cov() 

141 # stiffness 

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

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

144 stiff_df = pd.DataFrame(stiff_diag, columns=cov_df.columns, index=cov_df.index) 

145 stiff_df.index.name = basepairname 

146 

147 # save csv data 

148 stiff_df.to_csv(Path(self.stage_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 + 0.5, 

158 i + 0.5, 

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

160 ha="center", 

161 va="center", 

162 color="w", 

163 ) 

164 axs.text( 

165 0, 

166 -1.35, 

167 "Units:\n" 

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

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

170 fontsize=6, 

171 ) 

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

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

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

175 axs.set_yticklabels(stiff_df.index) 

176 axs.set_title(f"Stiffness Constants for Base Pair Step '{basepairname}'") 

177 fig.tight_layout() 

178 fig.savefig(self.stage_io_dict["out"]["output_jpg_path"], format="jpg") 

179 plt.close() 

180 

181 # Copy files to host 

182 self.copy_to_host() 

183 

184 # Remove temporary file(s) 

185 self.remove_tmp_files() 

186 

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

188 

189 return 0 

190 

191 

192def basepair_stiffness( 

193 input_filename_shift: str, 

194 input_filename_slide: str, 

195 input_filename_rise: str, 

196 input_filename_tilt: str, 

197 input_filename_roll: str, 

198 input_filename_twist: str, 

199 output_csv_path: str, 

200 output_jpg_path: str, 

201 properties: Optional[dict] = None, 

202 **kwargs, 

203) -> int: 

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

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

206 return BPStiffness(**dict(locals())).launch() 

207 

208 

209basepair_stiffness.__doc__ = BPStiffness.__doc__ 

210main = BPStiffness.get_main(basepair_stiffness, "Calculate stiffness constants matrix between all six helical parameters for a single base pair step.") 

211 

212if __name__ == '__main__': 

213 main()