Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1""" 

2Unit and regression test for the membrane_curvature package. 

3""" 

4 

5 

6import pytest 

7from membrane_curvature.surface import (normalized_grid, derive_surface, get_z_surface, 

8 surface_interpolation) 

9from membrane_curvature.curvature import mean_curvature, gaussian_curvature 

10import numpy as np 

11from numpy.testing import assert_almost_equal, assert_allclose 

12import MDAnalysis as mda 

13from membrane_curvature.tests.datafiles import (GRO_PO4_SMALL) 

14from membrane_curvature.base import MembraneCurvature 

15 

16# Reference data from datafile 

17MEMBRANE_CURVATURE_DATA = { 

18 

19 'z_avg_coords': np.array([[15.52998744, 15.68577027, 15.54460264, 15.42630775, 15.41610875, 

20 15.5227999, 15.40030259, 15.47866627, 15.5402739, 15.58982381], 

21 [15.7210999, 15.66186774, 15.66852082, 15.5650629, 15.59180416, 

22 15.52540419, 15.43453586, 15.31625871, 15.53287837, 15.72669662], 

23 [15.65202988, 15.87587967, 15.80443607, 15.2156001, 15.9012679, 

24 15.61628637, 15.54388155, 15.51714352, 15.56670715, 15.67794791], 

25 [15.79848438, 15.86021965, 15.91864504, 15.69624091, 16.07622673, 

26 15.55569959, 15.33016631, 15.51812384, 15.57359306, 15.74745874], 

27 [15.99946331, 15.80777305, 15.93547516, 16.06895507, 16.49331617, 

28 16.47925099, 15.74151387, 15.63836954, 15.72500532, 15.91917461], 

29 [16.00306618, 15.44807954, 14.91708903, 15.62196315, 15.63327226, 

30 16.56862831, 16.11996038, 15.89331185, 15.83679604, 15.98079948], 

31 [15.76326987, 15.64245421, 15.52017543, 15.47039083, 14.88002689, 

32 15.53698847, 15.80894958, 15.80674416, 15.7546208, 15.88995425], 

33 [15.70029967, 15.61600719, 15.53771198, 15.47668145, 15.19293903, 

34 15.41956353, 15.66099601, 15.71207747, 15.80128901, 15.71542822], 

35 [15.68171964, 15.63995413, 15.53009812, 15.21636634, 15.27028742, 

36 15.38000841, 15.51385563, 15.64464232, 15.79420718, 15.77794963], 

37 [11.9375362, 15.67473274, 15.56693593, 15.28816211, 15.26380259, 

38 15.34311786, 15.50101777, 15.5245863, 13.5766693, 15.69553947]]), 

39 

40 'z_ref': { 

41 'small': np.array([[10., 11., 12.], [15., 20, 25], [15., 40, 50]]), 

42 'all': np.array([[15.96339989, 16.36299992, 16.57025003, 16.30183315, 16.14233398, 

43 15.94885731, 15.99250078, 16.17940025, 16.08424997, 15.93374944], 

44 [15.9995718, 16.48649979, 16.59700012, 16.3276666, 16.26959991, 

45 15.77983316, 15.67449999, 15.59950042, 16.05650028, 16.11733341], 

46 [15.9301672, 16.04720001, 16.24383338, 16.38975, 16.05666653, 

47 15.71950006, 15.7414999, 15.65285724, 15.71783352, 15.91666635], 

48 [15.87350019, 16.0994997, 16.45200014, 16.38366667, 15.91100025, 

49 15.44099998, 15.55220013, 15.74933386, 15.7957499, 15.93225002], 

50 [15.89100003, 16.01559982, 16.45950031, 16.68450022, 16.34674978, 

51 16.27950001, 15.97475028, 16.0142498, 16.07933331, 15.96724939], 

52 [15.81012511, 15.84583362, 16.09700036, 15.98525, 15.49299908, 

53 16.36499977, 16.20639992, 15.8682003, 15.82559967, 15.87400055], 

54 [15.73475003, 15.67866707, 15.85220013, 15.60228566, 15.12299967, 

55 15.70033328, 15.87920036, 15.80550003, 15.60928576, 15.8010006], 

56 [15.79039974, 15.91499996, 15.97549987, 15.80860004, 15.73637486, 

57 15.51133362, 15.80240021, 15.78233337, 15.65516663, 15.72000027], 

58 [15.8411665, 16.13249969, 16.48759995, 16.25674987, 15.78233369, 

59 15.71450011, 15.33062541, 15.99500027, 15.83737516, 15.74500052], 

60 [15.82900023, 16.06166649, 16.2973334, 16.43733342, 16.12957178, 

61 16.09366608, 15.95349979, 16.22599983, 16.17750025, 16.00225067]])}, 

62 

63 'gaussian_curvature': { 

64 'small': np.array([[-2.19478738e-02, -2.32254318e-03, -5.47176909e-04], 

65 [-1.38453218e-01, -1.21945074e-03, -1.35208221e-04], 

66 [-9.72884280e-04, -3.94840040e-04, -1.32808172e-04]]), 

67 

68 'all': np.array([[-0.00189129, 0.04934495, 0.04660196, -0.00351411, -0.01943406, 

69 -0.03893078, -0.0246221, -0.03280081, -0.12642188, -0.03525892], 

70 [-0.00693942, 0.03182844, 0.00120618, -0.00352255, 0.00342091, 

71 -0.00142247, 0.02465936, 0.04605395, -0.0106348, -0.00313678], 

72 [-0.01649198, 0.00168855, -0.02731173, -0.01564413, -0.00973393, 

73 0.02368517, -0.00604347, 0.0169452, 0.0113627, -0.00027235], 

74 [0.00088378, -0.00464509, 0.0075489, 0.02877688, -0.00328288, 

75 0.07988983, 0.02487373, -0.00071568, -0.0050775, -0.02188734], 

76 [-0.013283, -0.01107469, 0.02580236, 0.0847512, -0.07205011, 

77 -0.05251712, -0.03977956, -0.03174133, 0.0151017, 0.00278634], 

78 [-0.00688401, -0.01030927, -0.03964658, -0.01066038, 0.01942349, 

79 0.01216024, 0.05635031, -0.0138591, -0.00547026, -0.02372161], 

80 [0.00552771, 0.00111084, -0.0688243, 0.0081551, 0.14126933, 

81 -0.01476609, -0.00715425, -0.0059002, 0.02781192, 0.00485525], 

82 [-0.02954713, -0.01709626, -0.01171343, -0.00766876, -0.01780511, 

83 -0.04009694, -0.00779307, -0.04735893, 0.00799721, -0.00961057], 

84 [-0.0033638, 0.009781, 0.06724205, 0.00795326, 0.00034145, 

85 0.02682387, 0.10108879, -0.01423631, -0.01802192, -0.00922448], 

86 [-0.00313899, -0.00418259, 0.03487913, -0.04456535, -0.00768992, 

87 -0.00642677, 0.0254065, -0.01830984, -0.00904487, -0.01182518]])}, 

88 

89 'mean_curvature': { 

90 'small': np.array([[0.16037507, 0.04033506, 0.02057139], 

91 [0.99647932, 0.14502529, 0.04590719], 

92 [0.05019947, 0.26763173, 0.16841648]]), 

93 

94 'all': np.array([[0.06396822, 0.2254189, 0.22399141, 0.02498465, 0.05090628, 

95 -0.09999741, -0.10476551, -0.05358351, 0.12631834, 0.09827992], 

96 [0.09151143, 0.19973338, 0.13808081, 0.04574428, 0.10289627, 

97 -0.04137634, -0.18304112, -0.2249239, 0.04760685, 0.16729716], 

98 [-0.01779114, -0.04597901, -0.00778294, 0.09933345, -0.03402726, 

99 -0.16382893, -0.09622266, -0.15120851, -0.13753756, -0.04029748], 

100 [-0.0369991, 0.00233226, 0.16181129, 0.18932471, -0.01349983, 

101 -0.28269057, -0.16712506, 0.01942325, -0.03927295, -0.03811465], 

102 [-0.06309625, -0.00820666, 0.16715942, 0.29301601, 0.21669994, 

103 0.07393958, -0.0129063, 0.04319332, 0.14495082, 0.07021294], 

104 [-0.05875299, -0.04393517, 0.0837562, -0.05789939, -0.19497179, 

105 0.25517884, 0.25387131, -0.03625653, -0.03502722, -0.01136375], 

106 [-0.08988405, -0.10299823, -0.04910499, -0.21748747, -0.41463502, 

107 -0.03913769, 0.1765791, -0.03554145, -0.1677006, -0.10516181], 

108 [0.0095539, 0.0364163, 0.00168944, -0.06394463, -0.04456537, 

109 -0.25037463, -0.03814847, -0.02531541, -0.11902046, -0.10177806], 

110 [0.00184591, 0.12102329, 0.28902913, 0.0966804, -0.03156109, 

111 -0.16964647, -0.336664, 0.03280685, 0.03212416, -0.08340905], 

112 [0.01478105, 0.08136444, 0.23413597, 0.1472945, -0.06672947, 

113 -0.09468121, -0.21140388, 0.03506431, 0.03308529, -0.01943328]])}, 

114 

115 'grid': {'small': 

116 {'upper': np.array([[15., 15., np.nan], [15., np.nan, np.nan], [15., np.nan, np.nan]]), 

117 'lower': np.array([[np.nan, np.nan, 12.], [np.nan, 12., 12.], [np.nan, 12., 12.]])}}, 

118 

119 'beads': {'small': 

120 {'upper': {'POPC': [0, 1, 2, 3]}, 

121 'lower': {'POPC': [4, 5, 6, 7, 8]}}} 

122 

123} 

124 

125 

126@pytest.fixture 

127def small_grofile(): 

128 u = mda.Universe(GRO_PO4_SMALL) 

129 sel = u.select_atoms('name PO4') 

130 return sel 

131 

132 

133def test_gaussian_curvature_small(): 

134 K_test = gaussian_curvature(MEMBRANE_CURVATURE_DATA['z_ref']['small']) 

135 for k, k_test in zip(MEMBRANE_CURVATURE_DATA['gaussian_curvature']['small'], K_test): 

136 assert_allclose(k, k_test) 

137 

138 

139def test_mean_curvature_small(): 

140 H_test = mean_curvature(MEMBRANE_CURVATURE_DATA['z_ref']['small']) 

141 for h, h_test in zip(MEMBRANE_CURVATURE_DATA['mean_curvature']['small'], H_test): 

142 assert_allclose(h, h_test) 

143 

144 

145def test_gaussian_curvature_all(): 

146 K_test = gaussian_curvature(MEMBRANE_CURVATURE_DATA['z_ref']['all']) 

147 for k, k_test in zip(MEMBRANE_CURVATURE_DATA['gaussian_curvature']['all'], K_test): 

148 assert_allclose(k, k_test, rtol=1e-4) 

149 

150 

151def test_mean_curvature_all(): 

152 H_test = mean_curvature(MEMBRANE_CURVATURE_DATA['z_ref']['all']) 

153 for h, h_test in zip(MEMBRANE_CURVATURE_DATA['mean_curvature']['all'], H_test): 

154 assert_almost_equal(h, h_test) 

155 

156 

157@pytest.mark.parametrize('n_cells, grid_z_coords', [ 

158 (3, np.full((3, 3), 10.)), 

159 (3, np.array([[10., 20., 30.], [10., 20., 30.], [10., 20., 30.]], dtype=float)) 

160]) 

161def test_normalized_grid_identity_other_values(n_cells, grid_z_coords): 

162 unit = np.ones([n_cells, n_cells]) 

163 z_avg = normalized_grid(grid_z_coords, unit) 

164 assert_allclose(z_avg, grid_z_coords) 

165 

166 

167def test_normalized_grid_more_beads(): 

168 # sum of z coordinate in grid, 

169 grid_z_coords = np.full((3, 3), 10.) 

170 # grid number of beads per unit 

171 norm_grid = np.array([[2., 1., 1.], [1., 2., 1.], [1., 1., 2.]]) 

172 # avg z coordinate in grid 

173 expected_normalized_surface = np.array([[5., 10., 10.], [10., 5., 10.], [10., 10., 5.]]) 

174 average_surface = normalized_grid(grid_z_coords, norm_grid) 

175 assert_allclose(average_surface, expected_normalized_surface) 

176 

177 

178def test_derive_surface(small_grofile): 

179 n_cells, max_width = 3, 30 

180 expected_surface = np.array(([150., 150., 120.], [150., 120., 120.], [150., 120., 120.])) 

181 max_width_x = max_width_y = max_width 

182 surface = derive_surface(small_grofile, n_cells, n_cells, max_width_x, max_width_y) 

183 assert_allclose(surface, expected_surface) 

184 

185 

186def test_derive_surface_from_numpy(): 

187 dummy_array = np.array([[0., 0., 150.], [100., 0., 150.], [200., 0., 150.], 

188 [0., 100., 150.], [100., 100., 120.], [200., 100., 120.], 

189 [0., 200., 120.], [100., 200., 120.], [200., 200., 120.]]) 

190 x_bin = y_bin = 3 

191 x_range = y_range = (0, 300) 

192 expected_surface = np.array(([150., 150., 120.], [150., 120., 120.], [150., 120., 120.])) 

193 surface = get_z_surface(dummy_array, x_bin, y_bin, x_range, y_range) 

194 assert_allclose(surface, expected_surface) 

195 

196 

197@pytest.mark.parametrize('x_bin, y_bin, x_range, y_range, expected_surface', [ 

198 (3, 3, (0, 300), (0, 300), np.array(([150., np.nan, 150.], 

199 [np.nan, 150., 150.], 

200 [150., 150., 150.]))), 

201 (3, 4, (0, 300), (0, 400), np.array([[150., np.nan, 150., np.nan], 

202 [np.nan, 150., 150., np.nan], 

203 [150., 150., 150., np.nan]])) 

204]) 

205def test_get_z_surface(x_bin, y_bin, x_range, y_range, expected_surface): 

206 dummy_array = np.array([[0., 0., 150.], [0., 0., 150.], [200., 0., 150.], 

207 [0., 0., 150.], [100., 100., 150.], [200., 100., 150.], 

208 [0., 200., 150.], [100., 200., 150.], [200., 200., 150.]]) 

209 surface = get_z_surface(dummy_array, x_bin, y_bin, x_range, y_range) 

210 assert_allclose(surface, expected_surface) 

211 

212 

213@pytest.mark.parametrize('dummy_surface, expected_interpolated_surface', [ 

214 # array 3x3 with all 150 and one nan 

215 (np.array(([150., 150., 150.], 

216 [150., np.nan, 150.], 

217 [150., 150., 150.])), 

218 np.full((3, 3), 150.)), 

219 # array 3x4 with all 150 and two nans 

220 (np.array([[150., 150, 150., 150.], 

221 [150., np.nan, np.nan, 150.], 

222 [150., 150., 150., 150.]]), 

223 np.full((3, 4), 150.)), 

224 # array 4x4 with all 150 and two nans 

225 (np.array([[150., 150, 150., 150.], 

226 [150., np.nan, np.nan, 150.], 

227 [150., 130., 140., 150.], 

228 [150., 150., 150., 150.]]), 

229 np.array([[150., 150, 150., 150.], 

230 [150., 140., 145., 150.], 

231 [150., 130., 140., 150.], 

232 [150., 150., 150., 150.]])), 

233 # array 3x3 with lots of nans 

234 (np.array([[np.nan, np.nan, 150.], 

235 [150, np.nan, 150.], 

236 [np.nan, 150., np.nan]]), 

237 np.full((3, 3), 150.)) 

238]) 

239def test_surface_interpolation(dummy_surface, expected_interpolated_surface): 

240 surface = surface_interpolation(dummy_surface) 

241 assert_allclose(surface, expected_interpolated_surface) 

242 

243 

244class TestMembraneCurvature(object): 

245 @pytest.fixture() 

246 def universe(self): 

247 return mda.Universe(GRO_PO4_SMALL) 

248 

249 @pytest.fixture() 

250 def universe_dummy(self): 

251 a = np.array([[0., 0., 150.], [0., 0., 150.], [200., 0., 150.], 

252 [0., 0., 150.], [100., 100., 150.], [200., 100., 150.], 

253 [0., 200., 150.], [100., 200., 150.], [200., 200., 150.]]) 

254 

255 u = mda.Universe(a, n_atoms=9) 

256 u.dimensions = [300, 300, 300, 90., 90., 90.] 

257 

258 return u 

259 

260 @pytest.fixture() 

261 def universe_dummy_full(self): 

262 a = np.array([[0., 0., 150.], [100., 0., 150.], [200., 0., 150.], 

263 [0., 200., 150.], [100., 200., 120.], [200., 200., 120.], 

264 [0., 100., 120.], [100., 100., 120.], [200., 100., 120.]]) 

265 

266 u = mda.Universe(a, n_atoms=9) 

267 u.dimensions = [300, 300, 300, 90., 90., 90.] 

268 

269 return u 

270 

271 @pytest.fixture() 

272 def universe_dummy_wrap(self): 

273 # Atoms out of bounds in x 

274 # +-----------+ 

275 # | | 8 | 9 | 7 

276 # +-----------+ 

277 # 6 | 4 | 5 | | 

278 # +-----------+ 

279 # | | 2 | 3 | 1 

280 # +-----------+ 

281 a = np.array([[300., 0., 110.], [100., 0., 150.], [200., 0., 150.], 

282 [0., 100., 150.], [100., 100., 150.], [-100., 100., 150.], 

283 [300., 200., 110.], [100., 200., 150.], [200., 200., 150.]]) 

284 

285 u = mda.Universe(a, n_atoms=9) 

286 u.dimensions = [300, 300, 300, 90., 90., 90.] 

287 return u 

288 

289 # Equivalent to universe_dummy_wrap when wrapping is applied. 

290 # Atoms out of bounds in x and y 

291 @pytest.fixture() 

292 def universe_dummy_wrap_xy(self): 

293 a = np.array([[300., 0., 110.], [100., 0., 150.], [200., 0., 150.], 

294 [0., -200., 150.], [100., -200., 150.], [-100., 100., 150.], 

295 [300., 200., 110.], [100., 200., 150.], [200., 200., 150.]]) 

296 

297 u = mda.Universe(a, n_atoms=9) 

298 u.dimensions = [300, 300, 300, 90., 90., 90.] 

299 

300 return u 

301 

302 @pytest.fixture() 

303 def dummy_surface(self): 

304 surface = np.array([[110., 150., 110.], 

305 [150., 150., 150.], 

306 [150., 150., 150.]]) 

307 return surface 

308 

309 @pytest.fixture() 

310 def curvature_unwrapped_universe(self, universe_dummy_wrap): 

311 return MembraneCurvature(universe_dummy_wrap, 

312 n_x_bins=3, 

313 n_y_bins=3).run() 

314 

315 @pytest.fixture() 

316 def curvature_unwrapped_universe_xy(self, universe_dummy_wrap_xy): 

317 return MembraneCurvature(universe_dummy_wrap_xy, 

318 n_x_bins=3, 

319 n_y_bins=3).run() 

320 

321 def test_invalid_selection(self, universe): 

322 with pytest.raises(ValueError, match=r'Invalid selection'): 

323 MembraneCurvature(universe, select='name P') 

324 

325 def test_grid_bigger_than_simulation_box_x_dim(self, universe): 

326 regex = (r"Grid range in x does not cover entire " 

327 r"dimensions of simulation box.\n Minimum dimensions " 

328 r"must be equal to simulation box.") 

329 with pytest.warns(UserWarning, match=regex): 

330 MembraneCurvature(universe, select='name PO4', x_range=(0, 10)) 

331 

332 def test_grid_bigger_than_simulation_box_y_dim(self, universe): 

333 regex = (r"Grid range in y does not cover entire " 

334 r"dimensions of simulation box.\n Minimum dimensions " 

335 r"must be equal to simulation box.") 

336 with pytest.warns(UserWarning, match=regex): 

337 MembraneCurvature(universe, select='name PO4', y_range=(0, 10)) 

338 

339 @pytest.mark.parametrize('x_bin, y_bin, x_range, y_range, expected_surface', [ 

340 (3, 3, (0, 300), (0, 300), np.array(([150., np.nan, 150.], 

341 [np.nan, 150., 150.], 

342 [150., 150., 150.]))), 

343 (3, 4, (0, 300), (0, 400), np.array([[150., np.nan, 150., np.nan], 

344 [np.nan, 150., 150., np.nan], 

345 [150., 150., 150., np.nan]])) 

346 ]) 

347 def test_analysis_get_z_surface_dummy(self, universe_dummy, x_bin, y_bin, x_range, y_range, expected_surface): 

348 u = universe_dummy 

349 mc = MembraneCurvature(u, select='all', 

350 n_x_bins=x_bin, 

351 n_y_bins=y_bin, 

352 x_range=x_range, 

353 y_range=y_range).run() 

354 

355 avg_surface = mc.results.average_z_surface 

356 assert_allclose(avg_surface, expected_surface) 

357 

358 @pytest.mark.xfail(reason="Wrapping coordinates not applied.") 

359 @pytest.mark.parametrize('x_bin, y_bin, expected_surface', [ 

360 (3, 3, 

361 np.array([[150., 150., 120.], 

362 [150., 120., 120.], 

363 [150., 120., 120.]])), 

364 (4, 4, 

365 np.array([[150., 150., 135., 120.], 

366 [150., 120., 120., np.nan], 

367 [150., 120., 120., 120.], 

368 [150., np.nan, 120., 120.]])), 

369 (5, 5, 

370 np.array([[150., 150., 150., 120., 120.], 

371 [150., 120., np.nan, 120., np.nan], 

372 [150., np.nan, 120., np.nan, 120.], 

373 [150., 120., np.nan, 120., np.nan], 

374 [150., np.nan, 120., np.nan, 120.]])) 

375 ]) 

376 def test_analysis_get_z_surface(self, universe, x_bin, y_bin, expected_surface): 

377 mc = MembraneCurvature(universe, 

378 select='name PO4', 

379 n_x_bins=x_bin, 

380 n_y_bins=y_bin).run() 

381 avg_surface = mc.results.average_z_surface 

382 assert_allclose(avg_surface, expected_surface) 

383 

384 # test using wrap=True with test grofile 

385 def test_analysis_mean_wrap(self, universe): 

386 expected_mean = np.array([[7.50000000e+00, 1.33985392e-01, 2.77315457e-04], 

387 [-2.77315457e-04, -3.53944270e-01, -7.50000000e+00], 

388 [-2.77315457e-04, -5.01100068e-01, -7.50000000e+00]]) 

389 mc = MembraneCurvature(universe, 

390 select='name PO4', 

391 n_x_bins=3, 

392 n_y_bins=3).run() 

393 avg_mean = mc.results.average_mean 

394 assert_allclose(avg_mean, expected_mean) 

395 

396 # test using wrap=False with test grofile 

397 def test_analysis_mean_no_wrap(self, universe): 

398 expected_mean = np.array([[7.50000000e+00, 1.33985392e-01, 2.77315457e-04], 

399 [-2.77315457e-04, -3.53944270e-01, -7.50000000e+00], 

400 [-2.77315457e-04, -5.01100068e-01, -7.50000000e+00]]) 

401 mc = MembraneCurvature(universe, 

402 select='name PO4', 

403 n_x_bins=3, 

404 n_y_bins=3, 

405 wrap=False).run() 

406 avg_mean = mc.results.average_mean 

407 assert_allclose(avg_mean, expected_mean) 

408 

409 # test using dummy Universe with atoms out of boounds 

410 # with wrap=True (default) 

411 # +-----------+ +-----------+ 

412 # | | 8 | 9 | 7 | 7 | 8 | 9 | 

413 # +-----------+ +-----------+ 

414 # 6 | 4 | 5 | | ---> | 4 | 5 | 6 | 

415 # +-----------+ +-----------+ 

416 # | | 2 | 3 | 1 | 1 | 2 | 3 | 

417 # +-----------+ +-----------+ 

418 # 

419 # test surface in universe with atoms out of bounds in x 

420 def test_analysis_get_z_surface_wrap(self, curvature_unwrapped_universe, dummy_surface): 

421 avg_surface = curvature_unwrapped_universe.results.average_z_surface 

422 assert_allclose(avg_surface, dummy_surface) 

423 

424 # test surface in universe with atoms out of bounds in x and y 

425 def test_analysis_get_z_surface_wrap_xy(self, universe_dummy_wrap_xy, dummy_surface): 

426 x_bin = y_bin = 3 

427 mc = MembraneCurvature(universe_dummy_wrap_xy, 

428 n_x_bins=x_bin, 

429 n_y_bins=y_bin).run() 

430 avg_surface = mc.results.average_z_surface 

431 assert_allclose(avg_surface, dummy_surface) 

432 

433 # test mean curvature 

434 def test_analysis_mean_wrap(self, curvature_unwrapped_universe, dummy_surface): 

435 avg_mean = curvature_unwrapped_universe.results.average_mean 

436 expected_mean = mean_curvature(dummy_surface) 

437 assert_allclose(avg_mean, expected_mean) 

438 

439 def test_analysis_mean_wrap_xy(self, curvature_unwrapped_universe, dummy_surface): 

440 avg_mean = curvature_unwrapped_universe.results.average_mean 

441 expected_mean = mean_curvature(dummy_surface) 

442 assert_allclose(avg_mean, expected_mean) 

443 

444 # test gaussian 

445 def test_analysis_gaussian_wrap(self, curvature_unwrapped_universe, dummy_surface): 

446 avg_gaussian = curvature_unwrapped_universe.results.average_gaussian 

447 expected_gaussian = gaussian_curvature(dummy_surface) 

448 assert_allclose(avg_gaussian, expected_gaussian) 

449 

450 def test_analysis_mean_gaussian_wrap_xy(self, curvature_unwrapped_universe, dummy_surface): 

451 avg_gaussian = curvature_unwrapped_universe.results.average_gaussian 

452 expected_gaussian = gaussian_curvature(dummy_surface) 

453 assert_allclose(avg_gaussian, expected_gaussian) 

454 

455 # test using dummy Universe with atoms out of boounds 

456 # with wrap=False 

457 # +-----------+ 

458 # | | 8 | 9 | 7 

459 # +-----------+ 

460 # 6 | 4 | 5 | | 

461 # +-----------+ 

462 # | | 2 | 3 | 1 

463 # +-----------+ 

464 # test surface 

465 # with wrap=False in universe with atoms out of bounds in x 

466 def test_analysis_get_z_surface_no_wrap(self, universe_dummy_wrap): 

467 expected_surface = [[np.nan, 150., np.nan], 

468 [150., 150., 150.], 

469 [150., np.nan, 150.]] 

470 x_bin = y_bin = 3 

471 mc = MembraneCurvature(universe_dummy_wrap, 

472 n_x_bins=x_bin, 

473 n_y_bins=y_bin, 

474 wrap=False).run() 

475 avg_surface = mc.results.average_z_surface 

476 assert_allclose(avg_surface, expected_surface) 

477 

478 # test surface in universe with atoms out of bounds in x and y 

479 def test_analysis_get_z_surface_no_wrap_xy(self, universe_dummy_wrap_xy): 

480 expected_surface = [[np.nan, np.nan, np.nan], 

481 [150., np.nan, 150.], 

482 [150., np.nan, 150.]] 

483 x_bin = y_bin = 3 

484 mc = MembraneCurvature(universe_dummy_wrap_xy, 

485 n_x_bins=x_bin, 

486 n_y_bins=y_bin, 

487 wrap=False).run() 

488 avg_surface = mc.results.average_z_surface 

489 assert_allclose(avg_surface, expected_surface) 

490 

491 # test mean 

492 def test_analysis_mean_no_wrap(self, universe_dummy_wrap): 

493 expected_mean = np.array(np.full((3, 3), np.nan)) 

494 x_bin = y_bin = 3 

495 mc = MembraneCurvature(universe_dummy_wrap, 

496 n_x_bins=x_bin, 

497 n_y_bins=y_bin, 

498 wrap=False).run() 

499 avg_mean = mc.results.average_mean 

500 assert_allclose(avg_mean, expected_mean) 

501 

502 def test_analysis_mean_no_wrap(self, universe_dummy_wrap_xy): 

503 expected_mean = np.array(np.full((3, 3), np.nan)) 

504 x_bin = y_bin = 3 

505 mc = MembraneCurvature(universe_dummy_wrap_xy, 

506 n_x_bins=x_bin, 

507 n_y_bins=y_bin, 

508 wrap=False).run() 

509 avg_mean = mc.results.average_mean 

510 assert_allclose(avg_mean, expected_mean) 

511 

512 # test gaussian 

513 def test_analysis_gaussian_no_wrap(self, universe_dummy_wrap): 

514 expected_gaussian = np.array(np.full((3, 3), np.nan)) 

515 x_bin = y_bin = 3 

516 mc = MembraneCurvature(universe_dummy_wrap, 

517 n_x_bins=x_bin, 

518 n_y_bins=y_bin, 

519 wrap=False).run() 

520 avg_gaussian = mc.results.average_gaussian 

521 assert_allclose(avg_gaussian, expected_gaussian) 

522 

523 def test_analysis_gaussian_no_wrap(self, universe_dummy_wrap_xy): 

524 expected_gaussian = np.array(np.full((3, 3), np.nan)) 

525 x_bin = y_bin = 3 

526 mc = MembraneCurvature(universe_dummy_wrap_xy, 

527 n_x_bins=x_bin, 

528 n_y_bins=y_bin, 

529 wrap=False).run() 

530 avg_gaussian = mc.results.average_gaussian 

531 assert_allclose(avg_gaussian, expected_gaussian) 

532 

533 @pytest.mark.parametrize('x_bin, y_bin, expected_surface', [ 

534 (3, 3, 

535 np.array([[150., 120., 150.], 

536 [150., 120., 120.], 

537 [150., 120., 120.]])), 

538 (4, 4, 

539 np.array([[150., 120., 150., np.nan], 

540 [150., 120., 120., np.nan], 

541 [150., 120., 120., np.nan], 

542 [np.nan, np.nan, np.nan, np.nan]])), 

543 (5, 5, 

544 np.array([[150., 120., np.nan, 150., np.nan], 

545 [150., 120., np.nan, 120., np.nan], 

546 [np.nan, np.nan, np.nan, np.nan, np.nan], 

547 [150., 120., np.nan, 120., np.nan], 

548 [np.nan, np.nan, np.nan, np.nan, np.nan]])) 

549 

550 ]) 

551 def test_analysis_get_z_surface(self, universe_dummy_full, x_bin, y_bin, expected_surface): 

552 mc = MembraneCurvature(universe_dummy_full, 

553 n_x_bins=x_bin, 

554 n_y_bins=y_bin).run() 

555 avg_surface = mc.results.average_z_surface 

556 assert_allclose(avg_surface, expected_surface) 

557 

558 def test_analysis_mean(self, universe_dummy_full): 

559 expected_mean = np.array([[-5.54630914e-04, - 1.50000000e+01, 8.80203593e-02], 

560 [-2.77315457e-04, - 2.20748929e-03, - 5.01100068e-01], 

561 [-2.77315457e-04, - 2.20748929e-03, - 1.50000000e+01]]) 

562 mc = MembraneCurvature(universe_dummy_full, 

563 n_x_bins=3, 

564 n_y_bins=3).run() 

565 avg_mean = mc.results.average_mean 

566 assert_allclose(avg_mean, expected_mean) 

567 

568 @pytest.mark.parametrize('x_bin, y_bin, box_dim, dummy_array, expected_surface', [ 

569 # test with negative z coordinates with 3 bins 

570 (3, 3, 300, np.array([[0., 0., -150.], [100., 0., -150.], [200., 0., -150.], 

571 [0., 100., -150.], [100., 100., 120.], [200., 100., 120.], 

572 [0., 200., 120.], [100., 200., 120.], [200., 200., 120.]]), 

573 np.array([[150., 150., 120.], 

574 [150., 120., 120.], 

575 [150., 120., 120.]])), 

576 # test with negative z coordinates with 4 bins 

577 (4, 4, 400, np.array([[0., 0., -150.], [100., 0., -150.], [200., 0., -150.], [300., 0., -150.], 

578 [0., 100., -150.], [100., 100., 120.], [200., 100., 120.], [300., 100., -150.], 

579 [0., 200., 120.], [100., 200., 120.], [200., 200., 120.], [300., 200., -150.], 

580 [0., 300., -150.], [100., 300., -150.], [200., 300., -150.], [300., 300., -150.]]), 

581 np.array([[150., 150., 120., 150.], 

582 [150., 120., 120., 150.], 

583 [150., 120., 120., 150.], 

584 [150., 150., 150., 150.]])) 

585 ]) 

586 def test_analysis_wrapping_coordinates(self, x_bin, y_bin, box_dim, dummy_array, expected_surface): 

587 x_range, y_range = (0, box_dim), (0, box_dim) 

588 u = mda.Universe(dummy_array, n_atoms=len(dummy_array)) 

589 u.dimensions = [box_dim, box_dim, 300, 90., 90., 90.] 

590 # Check with wrapped coords in base 

591 mc = MembraneCurvature(u, select='all', 

592 n_x_bins=x_bin, 

593 n_y_bins=y_bin, 

594 x_range=x_range, 

595 y_range=y_range).run() 

596 avg_surface = mc.results.average_z_surface 

597 # assert if default values of wrapped coords in z_surface returns correctly 

598 assert_allclose(avg_surface, expected_surface) 

599 

600 def test_test_analysis_no_wrapping(self, universe): 

601 regex = (r"`wrap == False` may result in inaccurate calculation") 

602 with pytest.warns(UserWarning, match=regex): 

603 MembraneCurvature(universe, wrap=False) 

604 

605 # test curvature with interpolated surface 

606 @pytest.mark.parametrize('dim_x, dim_y, x_bins, y_bins, dummy_array, expected_interp_surf', [ 

607 # array 3x3 with all 150 and one nan 

608 (300, 300, 3, 3, np.array([[0., 0., 150.], [100., 0., 150.], [200., 0., 150.], 

609 [0., 100., 150.], [100., 100., np.nan], [200., 100., 150.], 

610 [0., 200., 150.], [100., 200., 150.], [200., 200., 150.]]), 

611 np.full((1, 3, 3), 150.)), 

612 # array 3x3 with all 150 and one nan 

613 (300, 300, 3, 3, np.array([[0., 0., 150.], [100., 0., 150.], [200., 0., 150.], 

614 [0., 100., 150.], [100., 100., np.nan], [200., 100., 150.], 

615 [0., 200., np.nan], [100., 200., 150.], [200., 200., 150.]]), 

616 np.full((1, 3, 3), 150.)), 

617 # array 3x4 with all 150 and three nans 

618 (300, 400, 3, 4, np.array([[0., 0., 150.], [100., 0., 150.], [200., 0., 150.], 

619 [0., 100., 150.], [100., 100., np.nan], [200., 100., 150.], 

620 [0., 200., 150], [100., 200., np.nan], [200., 200., np.nan], 

621 [0., 300., 150.], [100., 300., 150.], [200., 300., 150.]]), 

622 np.full((1, 3, 4), 150.)), 

623 # array 4x4 with all 120 and many nans 

624 (400, 400, 4, 4, np.array([[0., 0., np.nan], [100., 0., 120.], [200., 0., 120.], [300., 0., np.nan], 

625 [0., 100., 120.], [100., 100., np.nan], [200., 100., 120.], [300., 100., 120.], 

626 [0., 200., 120], [100., 200., np.nan], [200., 200., np.nan], [300., 200., 120.], 

627 [0., 300., np.nan], [100., 300., 120.], [200., 300., 120.], [300., 300., np.nan]]), 

628 np.full((1, 4, 4), 120.)) 

629 ]) 

630 def test_analysis_interpolates_surface(self, dim_x, dim_y, x_bins, y_bins, dummy_array, expected_interp_surf): 

631 u = mda.Universe(dummy_array, n_atoms=len(dummy_array)) 

632 u.dimensions = [dim_x, dim_y, 300, 90., 90., 90.] 

633 mc = MembraneCurvature(u, 

634 n_x_bins=x_bins, 

635 n_y_bins=y_bins, 

636 wrap=True, 

637 interpolation=True).run() 

638 surface = mc.results.interpolated_z_surface 

639 assert_allclose(surface, expected_interp_surf)