Coverage for test/test_lineshapes.py: 99%

151 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-09-14 14:49 -0400

1from pathlib import Path 

2from unittest.mock import Mock 

3 

4import pytest 

5import pandas as pd 

6import numpy as np 

7from numpy.testing import assert_almost_equal 

8 

9from peakipy.io import Peaklist, PeaklistFormat 

10from peakipy.constants import tiny 

11from peakipy.lineshapes import ( 

12 gaussian, 

13 gaussian_lorentzian, 

14 pv_g, 

15 pv_l, 

16 voigt2d, 

17 pvoigt2d, 

18 pv_pv, 

19 get_lineshape_function, 

20 Lineshape, 

21 calculate_height_for_voigt_lineshape, 

22 calculate_fwhm_for_voigt_lineshape, 

23 calculate_fwhm_for_pseudo_voigt_lineshape, 

24 calculate_height_for_pseudo_voigt_lineshape, 

25 calculate_height_for_gaussian_lineshape, 

26 calculate_height_for_lorentzian_lineshape, 

27 calculate_height_for_pv_pv_lineshape, 

28 calculate_lineshape_specific_height_and_fwhm, 

29 calculate_peak_linewidths_in_hz, 

30 calculate_peak_centers_in_ppm, 

31) 

32 

33 

34def test_gaussian_typical_values(): 

35 x = np.array([0, 1, 2]) 

36 center = 0.0 

37 sigma = 1.0 

38 expected = (1.0 / (np.sqrt(2 * np.pi) * sigma)) * np.exp( 

39 -((x - center) ** 2) / (2 * sigma**2) 

40 ) 

41 result = gaussian(x, center, sigma) 

42 assert_almost_equal(result, expected, decimal=7) 

43 

44 

45def test_gaussian_center_nonzero(): 

46 x = np.array([0, 1, 2]) 

47 center = 1.0 

48 sigma = 1.0 

49 expected = (1.0 / (np.sqrt(2 * np.pi) * sigma)) * np.exp( 

50 -((x - center) ** 2) / (2 * sigma**2) 

51 ) 

52 result = gaussian(x, center, sigma) 

53 assert_almost_equal(result, expected, decimal=7) 

54 

55 

56def test_gaussian_sigma_nonzero(): 

57 x = np.array([0, 1, 2]) 

58 center = 0.0 

59 sigma = 2.0 

60 expected = (1.0 / (np.sqrt(2 * np.pi) * sigma)) * np.exp( 

61 -((x - center) ** 2) / (2 * sigma**2) 

62 ) 

63 result = gaussian(x, center, sigma) 

64 assert_almost_equal(result, expected, decimal=7) 

65 

66 

67def test_gaussian_zero_center(): 

68 x = np.array([0, 1, 2]) 

69 center = 0.0 

70 sigma = 1.0 

71 expected = (1.0 / (np.sqrt(2 * np.pi) * sigma)) * np.exp( 

72 -((x - center) ** 2) / (2 * sigma**2) 

73 ) 

74 result = gaussian(x, center, sigma) 

75 assert_almost_equal(result, expected, decimal=7) 

76 

77 

78def test_calculate_height_for_voigt_lineshape(): 

79 data = { 

80 "sigma_x": [1.0, 2.0], 

81 "sigma_y": [1.0, 2.0], 

82 "gamma_x": [1.0, 2.0], 

83 "gamma_y": [1.0, 2.0], 

84 "amp": [10.0, 20.0], 

85 "amp_err": [1.0, 2.0], 

86 } 

87 df = pd.DataFrame(data) 

88 result_df = calculate_height_for_voigt_lineshape(df) 

89 

90 assert np.allclose(result_df["height"], [0.435596, 0.217798]) 

91 assert np.allclose(result_df["height_err"], [0.04356, 0.02178]) 

92 

93 

94def test_calculate_fwhm_for_voigt_lineshape(): 

95 data = { 

96 "sigma_x": [1.0, 2.0], 

97 "sigma_y": [1.0, 2.0], 

98 "gamma_x": [1.0, 2.0], 

99 "gamma_y": [1.0, 2.0], 

100 "amp": [10.0, 20.0], 

101 "amp_err": [1.0, 2.0], 

102 } 

103 df = pd.DataFrame(data) 

104 result_df = calculate_fwhm_for_voigt_lineshape(df) 

105 

106 assert np.allclose(result_df["fwhm_l_x"], [2.0, 4.0]) 

107 assert np.allclose(result_df["fwhm_l_y"], [2.0, 4.0]) 

108 assert np.allclose(result_df["fwhm_g_x"], [2.35482, 4.70964]) 

109 assert np.allclose(result_df["fwhm_g_y"], [2.35482, 4.70964]) 

110 assert np.allclose(result_df["fwhm_x"], [3.601309, 7.202619]) 

111 assert np.allclose(result_df["fwhm_y"], [3.601309, 7.202619]) 

112 

113 

114def test_calculate_height_for_pseudo_voigt_lineshape(): 

115 data = { 

116 "sigma_x": [1.0, 2.0], 

117 "sigma_y": [1.0, 2.0], 

118 "gamma_x": [1.0, 2.0], 

119 "gamma_y": [1.0, 2.0], 

120 "amp": [10.0, 20.0], 

121 "amp_err": [1.0, 2.0], 

122 "fraction": [0.5, 0.5], 

123 } 

124 df = pd.DataFrame(data) 

125 result_df = calculate_height_for_pseudo_voigt_lineshape(df) 

126 

127 assert np.allclose(result_df["height"], [1.552472, 0.776236]) 

128 assert np.allclose(result_df["height_err"], [0.155247, 0.077624]) 

129 

130 

131def test_calculate_fwhm_for_pseudo_voigt_lineshape(): 

132 data = { 

133 "sigma_x": [1.0, 2.0], 

134 "sigma_y": [1.0, 2.0], 

135 "gamma_x": [1.0, 2.0], 

136 "gamma_y": [1.0, 2.0], 

137 "amp": [10.0, 20.0], 

138 "amp_err": [1.0, 2.0], 

139 "fraction": [0.5, 0.5], 

140 } 

141 df = pd.DataFrame(data) 

142 result_df = calculate_fwhm_for_pseudo_voigt_lineshape(df) 

143 

144 assert np.allclose(result_df["fwhm_x"], [2.0, 4.0]) 

145 assert np.allclose(result_df["fwhm_y"], [2.0, 4.0]) 

146 

147 

148def test_calculate_height_for_gaussian_lineshape(): 

149 data = { 

150 "sigma_x": [1.0, 2.0], 

151 "sigma_y": [1.0, 2.0], 

152 "gamma_x": [1.0, 2.0], 

153 "gamma_y": [1.0, 2.0], 

154 "amp": [10.0, 20.0], 

155 "amp_err": [1.0, 2.0], 

156 "fraction": [0.5, 0.5], 

157 } 

158 df = pd.DataFrame(data) 

159 result_df = calculate_height_for_gaussian_lineshape(df) 

160 

161 assert np.allclose(result_df["height"], [2.206356, 1.103178]) 

162 assert np.allclose(result_df["height_err"], [0.220636, 0.110318]) 

163 

164 

165def test_calculate_height_for_lorentzian_lineshape(): 

166 data = { 

167 "sigma_x": [1.0, 2.0], 

168 "sigma_y": [1.0, 2.0], 

169 "gamma_x": [1.0, 2.0], 

170 "gamma_y": [1.0, 2.0], 

171 "amp": [10.0, 20.0], 

172 "amp_err": [1.0, 2.0], 

173 "fraction": [0.5, 0.5], 

174 } 

175 df = pd.DataFrame(data) 

176 result_df = calculate_height_for_lorentzian_lineshape(df) 

177 

178 assert np.allclose(result_df["height"], [1.013212, 0.506606]) 

179 assert np.allclose(result_df["height_err"], [0.101321, 0.050661]) 

180 

181 

182def test_calculate_height_for_pv_pv_lineshape(): 

183 data = { 

184 "sigma_x": [1.0, 2.0], 

185 "sigma_y": [1.0, 2.0], 

186 "gamma_x": [1.0, 2.0], 

187 "gamma_y": [1.0, 2.0], 

188 "amp": [10.0, 20.0], 

189 "amp_err": [1.0, 2.0], 

190 "fraction_x": [0.5, 0.5], 

191 "fraction_y": [0.5, 0.5], 

192 } 

193 df = pd.DataFrame(data) 

194 result_df = calculate_height_for_pv_pv_lineshape(df) 

195 

196 assert np.allclose(result_df["height"], [1.552472, 0.776236]) 

197 assert np.allclose(result_df["height_err"], [0.155247, 0.077624]) 

198 

199 

200def test_calculate_height_for_pv_pv_lineshape_fraction_y(): 

201 data = { 

202 "sigma_x": [1.0, 2.0], 

203 "sigma_y": [1.0, 2.0], 

204 "gamma_x": [1.0, 2.0], 

205 "gamma_y": [1.0, 2.0], 

206 "amp": [10.0, 20.0], 

207 "amp_err": [1.0, 2.0], 

208 "fraction_x": [0.5, 0.5], 

209 "fraction_y": [1.0, 1.0], 

210 } 

211 df = pd.DataFrame(data) 

212 result_df = calculate_height_for_pv_pv_lineshape(df) 

213 

214 assert np.allclose(result_df["height"], [1.254186, 0.627093]) 

215 assert np.allclose(result_df["height_err"], [0.125419, 0.062709]) 

216 

217 

218def test_calculate_lineshape_specific_height_and_fwhm(): 

219 data = { 

220 "sigma_x": [1.0, 2.0], 

221 "sigma_y": [1.0, 2.0], 

222 "gamma_x": [1.0, 2.0], 

223 "gamma_y": [1.0, 2.0], 

224 "amp": [10.0, 20.0], 

225 "amp_err": [1.0, 2.0], 

226 "fraction": [0.5, 0.5], 

227 "fraction_x": [0.5, 0.5], 

228 "fraction_y": [0.5, 0.5], 

229 } 

230 df = pd.DataFrame(data) 

231 calculate_lineshape_specific_height_and_fwhm(Lineshape.G, df) 

232 calculate_lineshape_specific_height_and_fwhm(Lineshape.L, df) 

233 calculate_lineshape_specific_height_and_fwhm(Lineshape.V, df) 

234 calculate_lineshape_specific_height_and_fwhm(Lineshape.PV, df) 

235 calculate_lineshape_specific_height_and_fwhm(Lineshape.PV_PV, df) 

236 calculate_lineshape_specific_height_and_fwhm(Lineshape.PV_G, df) 

237 calculate_lineshape_specific_height_and_fwhm(Lineshape.PV_L, df) 

238 

239 

240def test_get_lineshape_function(): 

241 assert get_lineshape_function(Lineshape.PV) == pvoigt2d 

242 assert get_lineshape_function(Lineshape.L) == pvoigt2d 

243 assert get_lineshape_function(Lineshape.G) == pvoigt2d 

244 assert get_lineshape_function(Lineshape.G_L) == gaussian_lorentzian 

245 assert get_lineshape_function(Lineshape.PV_G) == pv_g 

246 assert get_lineshape_function(Lineshape.PV_L) == pv_l 

247 assert get_lineshape_function(Lineshape.PV_PV) == pv_pv 

248 assert get_lineshape_function(Lineshape.V) == voigt2d 

249 

250 

251def test_get_lineshape_function_exception(): 

252 with pytest.raises(Exception): 

253 get_lineshape_function("bla") 

254 

255 

256@pytest.fixture 

257def peakipy_data(): 

258 test_data_path = Path("./test/test_protein_L/") 

259 return Peaklist( 

260 test_data_path / "test.tab", test_data_path / "test1.ft2", PeaklistFormat.pipe 

261 ) 

262 

263 

264def test_calculate_peak_linewidths_in_hz(): 

265 # Sample data for testing 

266 data = { 

267 "sigma_x": [1.0, 2.0, 3.0], 

268 "sigma_y": [1.5, 2.5, 3.5], 

269 "fwhm_x": [0.5, 1.5, 2.5], 

270 "fwhm_y": [0.7, 1.7, 2.7], 

271 } 

272 df = pd.DataFrame(data) 

273 

274 # Mock peakipy_data object 

275 peakipy_data = Mock() 

276 peakipy_data.ppm_per_pt_f2 = 0.01 

277 peakipy_data.ppm_per_pt_f1 = 0.02 

278 peakipy_data.hz_per_pt_f2 = 10.0 

279 peakipy_data.hz_per_pt_f1 = 20.0 

280 

281 # Expected results 

282 expected_sigma_x_ppm = [0.01, 0.02, 0.03] 

283 expected_sigma_y_ppm = [0.03, 0.05, 0.07] 

284 expected_fwhm_x_ppm = [0.005, 0.015, 0.025] 

285 expected_fwhm_y_ppm = [0.014, 0.034, 0.054] 

286 expected_fwhm_x_hz = [5.0, 15.0, 25.0] 

287 expected_fwhm_y_hz = [14.0, 34.0, 54.0] 

288 

289 # Run the function 

290 result_df = calculate_peak_linewidths_in_hz(df, peakipy_data) 

291 

292 # Assertions 

293 pd.testing.assert_series_equal( 

294 result_df["sigma_x_ppm"], pd.Series(expected_sigma_x_ppm), check_names=False 

295 ) 

296 pd.testing.assert_series_equal( 

297 result_df["sigma_y_ppm"], pd.Series(expected_sigma_y_ppm), check_names=False 

298 ) 

299 pd.testing.assert_series_equal( 

300 result_df["fwhm_x_ppm"], pd.Series(expected_fwhm_x_ppm), check_names=False 

301 ) 

302 pd.testing.assert_series_equal( 

303 result_df["fwhm_y_ppm"], pd.Series(expected_fwhm_y_ppm), check_names=False 

304 ) 

305 pd.testing.assert_series_equal( 

306 result_df["fwhm_x_hz"], pd.Series(expected_fwhm_x_hz), check_names=False 

307 ) 

308 pd.testing.assert_series_equal( 

309 result_df["fwhm_y_hz"], pd.Series(expected_fwhm_y_hz), check_names=False 

310 ) 

311 

312 

313def test_calculate_peak_centers_in_ppm(): 

314 # Sample data for testing 

315 data = { 

316 "center_x": [10, 20, 30], 

317 "center_y": [15, 25, 35], 

318 "init_center_x": [12, 22, 32], 

319 "init_center_y": [18, 28, 38], 

320 } 

321 df = pd.DataFrame(data) 

322 

323 # Mock peakipy_data object 

324 peakipy_data = Mock() 

325 peakipy_data.uc_f2.ppm = Mock(side_effect=lambda x: x * 0.1) 

326 peakipy_data.uc_f1.ppm = Mock(side_effect=lambda x: x * 0.2) 

327 

328 # Expected results 

329 expected_center_x_ppm = [1.0, 2.0, 3.0] 

330 expected_center_y_ppm = [3.0, 5.0, 7.0] 

331 expected_init_center_x_ppm = [1.2, 2.2, 3.2] 

332 expected_init_center_y_ppm = [3.6, 5.6, 7.6] 

333 

334 # Run the function 

335 result_df = calculate_peak_centers_in_ppm(df, peakipy_data) 

336 

337 # Assertions 

338 pd.testing.assert_series_equal( 

339 result_df["center_x_ppm"], pd.Series(expected_center_x_ppm), check_names=False 

340 ) 

341 pd.testing.assert_series_equal( 

342 result_df["center_y_ppm"], pd.Series(expected_center_y_ppm), check_names=False 

343 ) 

344 pd.testing.assert_series_equal( 

345 result_df["init_center_x_ppm"], 

346 pd.Series(expected_init_center_x_ppm), 

347 check_names=False, 

348 ) 

349 pd.testing.assert_series_equal( 

350 result_df["init_center_y_ppm"], 

351 pd.Series(expected_init_center_y_ppm), 

352 check_names=False, 

353 )