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 

8from membrane_curvature.curvature import mean_curvature, gaussian_curvature 

9import numpy as np 

10from numpy.testing import assert_almost_equal 

11import MDAnalysis as mda 

12from membrane_curvature.tests.datafiles import (GRO_PO4_SMALL, XTC_PO4_SMALL) 

13from membrane_curvature.base import MembraneCurvature 

14 

15# Reference data from datafile 

16MEMBRANE_CURVATURE_DATA = { 

17 

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

19 15.5227999, 15.40030259, 15.47866627, 15.5402739, 15.58982381], 

20 [15.7210999, 15.66186774, 15.66852082, 15.5650629, 15.59180416, 

21 15.52540419, 15.43453586, 15.31625871, 15.53287837, 15.72669662], 

22 [15.65202988, 15.87587967, 15.80443607, 15.2156001, 15.9012679, 

23 15.61628637, 15.54388155, 15.51714352, 15.56670715, 15.67794791], 

24 [15.79848438, 15.86021965, 15.91864504, 15.69624091, 16.07622673, 

25 15.55569959, 15.33016631, 15.51812384, 15.57359306, 15.74745874], 

26 [15.99946331, 15.80777305, 15.93547516, 16.06895507, 16.49331617, 

27 16.47925099, 15.74151387, 15.63836954, 15.72500532, 15.91917461], 

28 [16.00306618, 15.44807954, 14.91708903, 15.62196315, 15.63327226, 

29 16.56862831, 16.11996038, 15.89331185, 15.83679604, 15.98079948], 

30 [15.76326987, 15.64245421, 15.52017543, 15.47039083, 14.88002689, 

31 15.53698847, 15.80894958, 15.80674416, 15.7546208, 15.88995425], 

32 [15.70029967, 15.61600719, 15.53771198, 15.47668145, 15.19293903, 

33 15.41956353, 15.66099601, 15.71207747, 15.80128901, 15.71542822], 

34 [15.68171964, 15.63995413, 15.53009812, 15.21636634, 15.27028742, 

35 15.38000841, 15.51385563, 15.64464232, 15.79420718, 15.77794963], 

36 [11.9375362, 15.67473274, 15.56693593, 15.28816211, 15.26380259, 

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

38 

39 'z_ref': { 

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

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

42 15.94885731, 15.99250078, 16.17940025, 16.08424997, 15.93374944], 

43 [15.9995718, 16.48649979, 16.59700012, 16.3276666, 16.26959991, 

44 15.77983316, 15.67449999, 15.59950042, 16.05650028, 16.11733341], 

45 [15.9301672, 16.04720001, 16.24383338, 16.38975, 16.05666653, 

46 15.71950006, 15.7414999, 15.65285724, 15.71783352, 15.91666635], 

47 [15.87350019, 16.0994997, 16.45200014, 16.38366667, 15.91100025, 

48 15.44099998, 15.55220013, 15.74933386, 15.7957499, 15.93225002], 

49 [15.89100003, 16.01559982, 16.45950031, 16.68450022, 16.34674978, 

50 16.27950001, 15.97475028, 16.0142498, 16.07933331, 15.96724939], 

51 [15.81012511, 15.84583362, 16.09700036, 15.98525, 15.49299908, 

52 16.36499977, 16.20639992, 15.8682003, 15.82559967, 15.87400055], 

53 [15.73475003, 15.67866707, 15.85220013, 15.60228566, 15.12299967, 

54 15.70033328, 15.87920036, 15.80550003, 15.60928576, 15.8010006], 

55 [15.79039974, 15.91499996, 15.97549987, 15.80860004, 15.73637486, 

56 15.51133362, 15.80240021, 15.78233337, 15.65516663, 15.72000027], 

57 [15.8411665, 16.13249969, 16.48759995, 16.25674987, 15.78233369, 

58 15.71450011, 15.33062541, 15.99500027, 15.83737516, 15.74500052], 

59 [15.82900023, 16.06166649, 16.2973334, 16.43733342, 16.12957178, 

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

61 

62 'gaussian_curvature': { 

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

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

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

66 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

87 

88 'mean_curvature': { 

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

90 [-0.99647932, -0.14502529, -0.04590719], 

91 [-0.05019947, -0.26763173, -0.16841648]]), 

92 

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

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

95 [-0.09151143, -0.19973338, -0.13808081, -0.04574428, -0.10289627, 

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

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

98 0.16382893, 0.09622266, 0.15120851, 0.13753756, 0.04029748], 

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

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

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

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

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

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

105 [0.08988405, 0.10299823, 0.04910499, 0.21748747, 0.41463502, 

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

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

108 0.25037463, 0.03814847, 0.02531541, 0.11902046, 0.10177806], 

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

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

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

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

113 

114 'grid': {'small': 

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

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

117 

118 'beads': {'small': 

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

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

121 

122} 

123 

124 

125@pytest.fixture 

126def small_grofile(): 

127 u = mda.Universe(GRO_PO4_SMALL) 

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

129 return sel 

130 

131 

132def test_gaussian_curvature_small(): 

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

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

135 assert_almost_equal(k, k_test) 

136 

137 

138def test_mean_curvature_small(): 

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

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

141 assert_almost_equal(h, h_test) 

142 

143 

144def test_gaussian_curvature_all(): 

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

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

147 assert_almost_equal(k, k_test) 

148 

149 

150def test_mean_curvature_all(): 

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

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

153 assert_almost_equal(h, h_test) 

154 

155 

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

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

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

159]) 

160def test_normalized_grid_identity_other_values(n_cells, grid_z_coords): 

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

162 z_avg = normalized_grid(grid_z_coords, unit) 

163 assert_almost_equal(z_avg, grid_z_coords) 

164 

165 

166def test_normalized_grid_more_beads(): 

167 # sum of z coordinate in grid, 

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

169 # grid number of beads per unit 

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

171 # avg z coordinate in grid 

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

173 average_surface = normalized_grid(grid_z_coords, norm_grid) 

174 assert_almost_equal(average_surface, expected_normalized_surface) 

175 

176 

177def test_derive_surface(small_grofile): 

178 n_cells, max_width = 3, 30 

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

180 max_width_x = max_width_y = max_width 

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

182 assert_almost_equal(surface, expected_surface) 

183 

184 

185def test_derive_surface_from_numpy(): 

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

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

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

189 x_bin = y_bin = 3 

190 x_range = y_range = (0, 300) 

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

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

193 assert_almost_equal(surface, expected_surface) 

194 

195 

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

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

198 [np.nan, 150., 150.], 

199 [150., 150., 150.]))), 

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

201 [np.nan, 150., 150., np.nan], 

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

203]) 

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

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

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

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

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

209 assert_almost_equal(surface, expected_surface) 

210 

211 

212class TestMembraneCurvature(object): 

213 @pytest.fixture() 

214 def universe(self): 

215 return mda.Universe(GRO_PO4_SMALL) 

216 

217 @pytest.fixture() 

218 def universe_dummy(self): 

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

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

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

222 

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

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

225 

226 return u 

227 

228 @pytest.fixture() 

229 def universe_dummy_full(self): 

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

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

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

233 

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

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

236 

237 return u 

238 

239 @pytest.fixture() 

240 def universe_dummy_wrap(self): 

241 # Atoms out of bounds in x 

242 # +-----------+ 

243 # | | 8 | 9 | 7 

244 # +-----------+ 

245 # 6 | 4 | 5 | | 

246 # +-----------+ 

247 # | | 2 | 3 | 1 

248 # +-----------+ 

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

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

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

252 

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

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

255 return u 

256 

257 # Equivalent to universe_dummy_wrap when wrapping is applied. 

258 # Atoms out of bounds in x and y 

259 @pytest.fixture() 

260 def universe_dummy_wrap_xy(self): 

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

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

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

264 

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

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

267 

268 return u 

269 

270 @pytest.fixture() 

271 def dummy_surface(self): 

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

273 [150., 150., 150.], 

274 [150., 150., 150.]]) 

275 return surface 

276 

277 @pytest.fixture() 

278 def curvature_unwrapped_universe(self, universe_dummy_wrap): 

279 return MembraneCurvature(universe_dummy_wrap, 

280 n_x_bins=3, 

281 n_y_bins=3).run() 

282 

283 @pytest.fixture() 

284 def curvature_unwrapped_universe_xy(self, universe_dummy_wrap_xy): 

285 return MembraneCurvature(universe_dummy_wrap_xy, 

286 n_x_bins=3, 

287 n_y_bins=3).run() 

288 

289 def test_invalid_selection(self, universe): 

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

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

292 

293 def test_grid_bigger_than_simulation_box_x_dim(self, universe): 

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

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

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

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

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

299 

300 def test_grid_bigger_than_simulation_box_y_dim(self, universe): 

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

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

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

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

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

306 

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

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

309 [np.nan, 150., 150.], 

310 [150., 150., 150.]))), 

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

312 [np.nan, 150., 150., np.nan], 

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

314 ]) 

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

316 u = universe_dummy 

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

318 n_x_bins=x_bin, 

319 n_y_bins=y_bin, 

320 x_range=x_range, 

321 y_range=y_range).run() 

322 

323 avg_surface = mc.results.average_z_surface 

324 assert_almost_equal(avg_surface, expected_surface) 

325 

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

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

328 (3, 3, 

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

330 [150., 120., 120.], 

331 [150., 120., 120.]])), 

332 (4, 4, 

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

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

335 [150., 120., 120., 120.], 

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

337 (5, 5, 

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

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

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

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

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

343 ]) 

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

345 mc = MembraneCurvature(universe, 

346 select='name PO4', 

347 n_x_bins=x_bin, 

348 n_y_bins=y_bin).run() 

349 avg_surface = mc.results.average_z_surface 

350 assert_almost_equal(avg_surface, expected_surface) 

351 

352 # test using wrap=True with test grofile 

353 def test_analysis_mean_wrap(self, universe): 

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

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

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

357 mc = MembraneCurvature(universe, 

358 select='name PO4', 

359 n_x_bins=3, 

360 n_y_bins=3).run() 

361 avg_mean = mc.results.average_mean 

362 assert_almost_equal(avg_mean, expected_mean) 

363 

364 # test using wrap=False with test grofile 

365 def test_analysis_mean_no_wrap(self, universe): 

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

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

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

369 mc = MembraneCurvature(universe, 

370 select='name PO4', 

371 n_x_bins=3, 

372 n_y_bins=3, 

373 wrap=False).run() 

374 avg_mean = mc.results.average_mean 

375 assert_almost_equal(avg_mean, expected_mean) 

376 

377 # test using dummy Universe with atoms out of boounds 

378 # with wrap=True (default) 

379 # +-----------+ +-----------+ 

380 # | | 8 | 9 | 7 | 7 | 8 | 9 | 

381 # +-----------+ +-----------+ 

382 # 6 | 4 | 5 | | ---> | 4 | 5 | 6 | 

383 # +-----------+ +-----------+ 

384 # | | 2 | 3 | 1 | 1 | 2 | 3 | 

385 # +-----------+ +-----------+ 

386 # 

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

388 def test_analysis_get_z_surface_wrap(self, curvature_unwrapped_universe, dummy_surface): 

389 avg_surface = curvature_unwrapped_universe.results.average_z_surface 

390 assert_almost_equal(avg_surface, dummy_surface) 

391 

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

393 def test_analysis_get_z_surface_wrap_xy(self, universe_dummy_wrap_xy, dummy_surface): 

394 x_bin = y_bin = 3 

395 mc = MembraneCurvature(universe_dummy_wrap_xy, 

396 n_x_bins=x_bin, 

397 n_y_bins=y_bin).run() 

398 avg_surface = mc.results.average_z_surface 

399 assert_almost_equal(avg_surface, dummy_surface) 

400 

401 # test mean curvature 

402 def test_analysis_mean_wrap(self, curvature_unwrapped_universe, dummy_surface): 

403 avg_mean = curvature_unwrapped_universe.results.average_mean 

404 expected_mean = mean_curvature(dummy_surface) 

405 assert_almost_equal(avg_mean, expected_mean) 

406 

407 def test_analysis_mean_wrap_xy(self, curvature_unwrapped_universe, dummy_surface): 

408 avg_mean = curvature_unwrapped_universe.results.average_mean 

409 expected_mean = mean_curvature(dummy_surface) 

410 assert_almost_equal(avg_mean, expected_mean) 

411 

412 # test gaussian 

413 def test_analysis_gaussian_wrap(self, curvature_unwrapped_universe, dummy_surface): 

414 avg_gaussian = curvature_unwrapped_universe.results.average_gaussian 

415 expected_gaussian = gaussian_curvature(dummy_surface) 

416 assert_almost_equal(avg_gaussian, expected_gaussian) 

417 

418 def test_analysis_mean_gaussian_wrap_xy(self, curvature_unwrapped_universe, dummy_surface): 

419 avg_gaussian = curvature_unwrapped_universe.results.average_gaussian 

420 expected_gaussian = gaussian_curvature(dummy_surface) 

421 assert_almost_equal(avg_gaussian, expected_gaussian) 

422 

423 # test using dummy Universe with atoms out of boounds 

424 # with wrap=False 

425 # +-----------+ 

426 # | | 8 | 9 | 7 

427 # +-----------+ 

428 # 6 | 4 | 5 | | 

429 # +-----------+ 

430 # | | 2 | 3 | 1 

431 # +-----------+ 

432 # test surface 

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

434 def test_analysis_get_z_surface_no_wrap(self, universe_dummy_wrap): 

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

436 [150., 150., 150.], 

437 [150., np.nan, 150.]] 

438 x_bin = y_bin = 3 

439 mc = MembraneCurvature(universe_dummy_wrap, 

440 n_x_bins=x_bin, 

441 n_y_bins=y_bin, 

442 wrap=False).run() 

443 avg_surface = mc.results.average_z_surface 

444 assert_almost_equal(avg_surface, expected_surface) 

445 

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

447 def test_analysis_get_z_surface_no_wrap_xy(self, universe_dummy_wrap_xy): 

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

449 [150., np.nan, 150.], 

450 [150., np.nan, 150.]] 

451 x_bin = y_bin = 3 

452 mc = MembraneCurvature(universe_dummy_wrap_xy, 

453 n_x_bins=x_bin, 

454 n_y_bins=y_bin, 

455 wrap=False).run() 

456 avg_surface = mc.results.average_z_surface 

457 assert_almost_equal(avg_surface, expected_surface) 

458 

459 # test mean 

460 def test_analysis_mean_no_wrap(self, universe_dummy_wrap): 

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

462 x_bin = y_bin = 3 

463 mc = MembraneCurvature(universe_dummy_wrap, 

464 n_x_bins=x_bin, 

465 n_y_bins=y_bin, 

466 wrap=False).run() 

467 avg_mean = mc.results.average_mean 

468 assert_almost_equal(avg_mean, expected_mean) 

469 

470 def test_analysis_mean_no_wrap(self, universe_dummy_wrap_xy): 

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

472 x_bin = y_bin = 3 

473 mc = MembraneCurvature(universe_dummy_wrap_xy, 

474 n_x_bins=x_bin, 

475 n_y_bins=y_bin, 

476 wrap=False).run() 

477 avg_mean = mc.results.average_mean 

478 assert_almost_equal(avg_mean, expected_mean) 

479 

480 # test gaussian 

481 def test_analysis_gaussian_no_wrap(self, universe_dummy_wrap): 

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

483 x_bin = y_bin = 3 

484 mc = MembraneCurvature(universe_dummy_wrap, 

485 n_x_bins=x_bin, 

486 n_y_bins=y_bin, 

487 wrap=False).run() 

488 avg_gaussian = mc.results.average_gaussian 

489 assert_almost_equal(avg_gaussian, expected_gaussian) 

490 

491 def test_analysis_gaussian_no_wrap(self, universe_dummy_wrap_xy): 

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

493 x_bin = y_bin = 3 

494 mc = MembraneCurvature(universe_dummy_wrap_xy, 

495 n_x_bins=x_bin, 

496 n_y_bins=y_bin, 

497 wrap=False).run() 

498 avg_gaussian = mc.results.average_gaussian 

499 assert_almost_equal(avg_gaussian, expected_gaussian) 

500 

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

502 (3, 3, 

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

504 [150., 120., 120.], 

505 [150., 120., 120.]])), 

506 (4, 4, 

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

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

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

510 [np.nan, np.nan, np.nan, np.nan]])), 

511 (5, 5, 

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

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

514 [np.nan, np.nan, np.nan, np.nan, np.nan], 

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

516 [np.nan, np.nan, np.nan, np.nan, np.nan]])) 

517 

518 ]) 

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

520 mc = MembraneCurvature(universe_dummy_full, 

521 n_x_bins=x_bin, 

522 n_y_bins=y_bin).run() 

523 avg_surface = mc.results.average_z_surface 

524 assert_almost_equal(avg_surface, expected_surface) 

525 

526 def test_analysis_mean(self, universe_dummy_full): 

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

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

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

530 mc = MembraneCurvature(universe_dummy_full, 

531 n_x_bins=3, 

532 n_y_bins=3).run() 

533 avg_mean = mc.results.average_mean 

534 assert_almost_equal(avg_mean, expected_mean) 

535 

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

537 # test with negative z coordinates with 3 bins 

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

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

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

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

542 [150., 120., 120.], 

543 [150., 120., 120.]])), 

544 # test with negative z coordinates with 4 bins 

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

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

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

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

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

550 [150., 120., 120., 150.], 

551 [150., 120., 120., 150.], 

552 [150., 150., 150., 150.]])) 

553 ]) 

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

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

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

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

558 # Check with wrapped coords in base 

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

560 n_x_bins=x_bin, 

561 n_y_bins=y_bin, 

562 x_range=x_range, 

563 y_range=y_range).run() 

564 avg_surface = mc.results.average_z_surface 

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

566 assert_almost_equal(avg_surface, expected_surface) 

567 

568 def test_test_analysis_no_wrapping(self, universe): 

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

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

571 MembraneCurvature(universe, wrap=False) 

572 

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

574 # test too large x coordinates 2 bins 

575 (2, 2, 200, np.array([[0., 0., 150.], [200., 0., 150.], 

576 [0., 100., 150.], [100., 100., 120.]])), 

577 # test too large y coordinates 2 bins 

578 (2, 2, 200, np.array([[0., 0., 150.], [100., 0., 150.], 

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

580 # test too large y coordinates with 3 bins 

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

582 [0., 300., 150.], [100., 100., 120.], [200., 100., 120.], 

583 [0., 350., 120.], [100., 200., 120.], [200., 200., 120.]])) 

584 ]) 

585 def test_positive_coordinates_exceed_grid(self, x_bin, y_bin, box_dim, dummy_array): 

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

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

588 regex = (r"exceed boundaries | size of grid") 

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

590 MembraneCurvature(u, select='all', 

591 n_x_bins=x_bin, 

592 n_y_bins=y_bin, 

593 wrap=False).run() 

594 

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

596 # test negative x coordinates 2 bins 

597 (2, 2, 200, np.array([[-150., 0., 150.], [100., 0., 150.], 

598 [0., 100., 150.], [100., 100., 150.]])), 

599 # test negative y coordinates 2 bins 

600 (2, 2, 200, np.array([[0., 0., 150.], [200., 0., 150.], 

601 [0., -150., 150.], [100., 100., 120.]])), 

602 # test negative x coordinates with 3 bins 

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

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

605 [0., 200., 120.], [100., 200., 120.], [300., 200., 120.]])) 

606 ]) 

607 def test_negative_coordinates_exceed_grid(self, x_bin, y_bin, box_dim, dummy_array): 

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

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

610 regex = (r"exceed boundaries | coordinates falls") 

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

612 MembraneCurvature(u, select='all', 

613 n_x_bins=x_bin, 

614 n_y_bins=y_bin, 

615 wrap=False).run()