Skip to content

Commit 654cdb8

Browse files
nawtreyorbeckst
authored andcommitted
DensityAnalysis and RMSF start/stop/step Issue Fix (#111)
* Fix #108 * Corrected start/stop/step issue in DensityAnalysis and RMSF * Changes: - Added self.n_frames to parallel.py - Updated DensityAnalysis conclude() to read self.n_frames instead of trajectory length - Updated RMSF to read self.n_frames in _conclude() - Added test_n_frames() to both DensityAnalysis and RMSF tests - Added test_accuracy() to test_rmsf.py to verify subselecting trajectories doesn't affect accuracy - Added new datafiles to test_density.py to use for testing timestep sub-selections - Consolidated two tests in test_density.py into one test that verifies both the array values and the sum of their values * Fixed commented out metadata in conclude() * PEP8 fix
1 parent 2055b8e commit 654cdb8

File tree

5 files changed

+79
-57
lines changed

5 files changed

+79
-57
lines changed

pmda/density.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,6 @@ def __init__(self, atomgroup, delta=1.0, atomselection=None,
251251
self._ydim = ydim
252252
self._zdim = zdim
253253
self._trajectory = u.trajectory
254-
self._n_frames = u.trajectory.n_frames
255254
if updating and atomselection is None:
256255
raise ValueError("updating=True requires a atomselection string")
257256
elif not updating and atomselection is not None:
@@ -300,12 +299,12 @@ def _single_frame(self, ts, atomgroups):
300299

301300
def _conclude(self):
302301
self._grid = self._results[:].sum(axis=0)
303-
self._grid /= float(self._n_frames)
302+
self._grid /= float(self.n_frames)
304303
metadata = self._metadata if self._metadata is not None else {}
305304
metadata['psf'] = self._atomgroup.universe.filename
306305
metadata['dcd'] = self._trajectory.filename
307306
metadata['atomselection'] = self._atomselection
308-
metadata['n_frames'] = self._n_frames
307+
metadata['n_frames'] = self.n_frames
309308
metadata['totaltime'] = self._atomgroup.universe.trajectory.totaltime
310309
metadata['dt'] = self._trajectory.dt
311310
metadata['time_unit'] = mda.core.flags['time_unit']

pmda/parallel.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,8 @@ def run(self,
352352
stop, step)
353353
n_frames = len(range(start, stop, step))
354354

355+
self.n_frames = n_frames
356+
355357
if n_frames == 0:
356358
warnings.warn("run() analyses no frames: check start/stop/step")
357359
if n_frames < n_blocks:

pmda/rms/rmsf.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,10 +193,9 @@ def _conclude(self):
193193
# serial case
194194
if n_blocks == 1:
195195
# get length of trajectory slice
196-
k = len(self._blocks[0])
197196
self.mean = self._results[0, 0]
198197
self.sumsquares = self._results[0, 1]
199-
self.rmsf = np.sqrt(self.sumsquares.sum(axis=1) / k)
198+
self.rmsf = np.sqrt(self.sumsquares.sum(axis=1) / self.n_frames)
200199
# parallel case
201200
else:
202201
mean = self._results[:, 0]
@@ -207,10 +206,9 @@ def _conclude(self):
207206
vals.append((len(self._blocks[i]), mean[i], sos[i]))
208207
# combine block results using fold method
209208
results = fold_second_order_moments(vals)
210-
self.totalts = results[0]
211209
self.mean = results[1]
212210
self.sumsquares = results[2]
213-
self.rmsf = np.sqrt(self.sumsquares.sum(axis=1) / self.totalts)
211+
self.rmsf = np.sqrt(self.sumsquares.sum(axis=1) / self.n_frames)
214212
self._negative_rmsf(self.rmsf)
215213

216214
@staticmethod

pmda/test/test_density.py

Lines changed: 50 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,77 @@
11
import pytest
22
import MDAnalysis as mda
33
import numpy as np
4-
import pmda.density
4+
from pmda.density import DensityAnalysis
55
from MDAnalysis.analysis.density import density_from_Universe
66
from numpy.testing import assert_almost_equal
77
from MDAnalysisTests.datafiles import GRO_MEMPROT, XTC_MEMPROT
8+
from MDAnalysisTests.datafiles import PSF_TRICLINIC, DCD_TRICLINIC
89

910

1011
@pytest.fixture(scope='module')
11-
def u():
12+
def u1():
1213
return mda.Universe(GRO_MEMPROT, XTC_MEMPROT)
1314

1415

15-
def test_density_sum(u):
16-
pdensity = pmda.density.DensityAnalysis(u.atoms, atomselection='name OD1',
17-
updating=True)
18-
core_number = 2
19-
pdensity.run(n_blocks=core_number, n_jobs=core_number)
20-
dens = mda.analysis.density.density_from_Universe(u,
21-
atomselection='name OD1',
22-
update_selection=True)
23-
assert np.sum(dens.grid) == np.sum(pdensity.density.grid)
16+
@pytest.fixture(scope='module')
17+
def u2():
18+
return mda.Universe(PSF_TRICLINIC, DCD_TRICLINIC)
2419

2520

26-
@pytest.mark.parametrize("n_blocks", [1, 2, 3, 4])
27-
def test_density_grid(u, n_blocks):
28-
pdensity = pmda.density.DensityAnalysis(u.atoms, atomselection='name OD1',
29-
updating=True)
30-
core_number = n_blocks
31-
pdensity.run(n_blocks=core_number, n_jobs=core_number)
32-
dens = mda.analysis.density.density_from_Universe(u,
33-
atomselection='name OD1',
34-
update_selection=True)
35-
assert_almost_equal(dens.grid, pdensity.density.grid)
21+
@pytest.mark.parametrize("n_blocks", [1, 2])
22+
@pytest.mark.parametrize("stop", [4, 5])
23+
@pytest.mark.parametrize("step", [1, 2])
24+
def test_density_values(u1, n_blocks, stop, step):
25+
parallel = DensityAnalysis(u1.atoms, atomselection='name OD1',
26+
updating=True)
27+
parallel.run(n_blocks=n_blocks, n_jobs=n_blocks, start=0, stop=stop,
28+
step=step)
29+
serial = density_from_Universe(u1, atomselection='name OD1',
30+
update_selection=True, start=0, stop=stop,
31+
step=step)
32+
assert np.sum(serial.grid) == np.sum(parallel.density.grid)
33+
assert_almost_equal(serial.grid, parallel.density.grid, decimal=17)
3634

3735

38-
def test_updating(u):
36+
def test_updating(u1):
3937
with pytest.raises(ValueError):
40-
pdensity = pmda.density.DensityAnalysis(u.atoms,
41-
updating=True)
38+
pdensity = DensityAnalysis(u1.atoms, updating=True)
4239

4340

44-
def test_atomselection(u):
41+
def test_atomselection(u1):
4542
with pytest.raises(ValueError):
46-
pdensity = pmda.density.DensityAnalysis(u.atoms,
47-
atomselection='name OD1')
43+
pdensity = DensityAnalysis(u1.atoms, atomselection='name OD1')
4844

4945

50-
def test_gridcenter(u):
51-
aselect = 'name OD1'
46+
def test_gridcenter(u1):
5247
gridcenter = np.array([10, 10, 10])
5348
xdim = 190
5449
ydim = 200
5550
zdim = 210
56-
dens = mda.analysis.density.density_from_Universe(u,
57-
atomselection=aselect,
58-
update_selection=True,
59-
gridcenter=gridcenter,
60-
xdim=xdim,
61-
ydim=ydim,
62-
zdim=zdim)
63-
pdens = pmda.density.DensityAnalysis(u.atoms,
64-
atomselection=aselect,
65-
updating=True,
66-
gridcenter=gridcenter,
67-
xdim=xdim,
68-
ydim=ydim,
69-
zdim=zdim)
51+
serial = density_from_Universe(u1, atomselection='name OD1',
52+
update_selection=True,
53+
gridcenter=gridcenter,
54+
xdim=xdim,
55+
ydim=ydim,
56+
zdim=zdim)
57+
parallel = DensityAnalysis(u1.atoms, atomselection='name OD1',
58+
updating=True,
59+
gridcenter=gridcenter,
60+
xdim=xdim,
61+
ydim=ydim,
62+
zdim=zdim)
7063
core_number = 4
71-
pdens.run(n_blocks=core_number, n_jobs=core_number)
72-
assert_almost_equal(dens.grid, pdens.density.grid)
73-
assert_almost_equal(pdens._gridcenter, gridcenter)
74-
assert len(pdens.density.edges[0]) == xdim + 1
75-
assert len(pdens.density.edges[1]) == ydim + 1
76-
assert len(pdens.density.edges[2]) == zdim + 1
64+
parallel.run(n_blocks=core_number, n_jobs=core_number)
65+
assert_almost_equal(serial.grid, parallel.density.grid)
66+
assert_almost_equal(parallel._gridcenter, gridcenter)
67+
assert len(parallel.density.edges[0]) == xdim + 1
68+
assert len(parallel.density.edges[1]) == ydim + 1
69+
assert len(parallel.density.edges[2]) == zdim + 1
70+
71+
72+
@pytest.mark.parametrize("start", [0, 1])
73+
@pytest.mark.parametrize("stop", [5, 7, 10])
74+
@pytest.mark.parametrize("step", [1, 2, 3])
75+
def test_n_frames(u2, start, stop, step):
76+
pdensity = DensityAnalysis(u2.atoms).run(start, stop, step)
77+
assert pdensity.n_frames == len(range(start, stop, step))

pmda/test/test_rmsf.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,22 @@ def u():
2323
return mda.Universe(PSF, DCD)
2424

2525

26+
@pytest.mark.parametrize('n_blocks', (2, 3, 4))
27+
@pytest.mark.parametrize('decimal', (7, 10, 11))
28+
@pytest.mark.parametrize("step", [1, 2, 3, 5])
29+
def test_rmsf_accuracy(u, n_blocks, decimal, step):
30+
PMDA_vals = RMSF(u.atoms).run(step=step,
31+
n_blocks=n_blocks,
32+
n_jobs=n_blocks)
33+
MDA_vals = mda.analysis.rms.RMSF(u.atoms).run(step=step)
34+
assert_almost_equal(MDA_vals.mean, PMDA_vals.mean, decimal=decimal)
35+
assert_almost_equal(MDA_vals.sumsquares, PMDA_vals.sumsquares,
36+
decimal=decimal)
37+
assert_almost_equal(MDA_vals.rmsf, PMDA_vals.rmsf, decimal=decimal)
38+
39+
2640
@pytest.mark.parametrize('n_blocks', (1, 2, 3, 4, 5, 10))
27-
@pytest.mark.parametrize('n_frames', (10, 50, 100))
41+
@pytest.mark.parametrize('n_frames', (10, 45, 90))
2842
def test_RMSF_values(u, n_blocks, n_frames):
2943
PMDA_vals = RMSF(u.atoms).run(stop=n_frames,
3044
n_blocks=n_blocks,
@@ -49,3 +63,11 @@ def test_RMSF_n_jobs(u, n_blocks):
4963
def test_negative_RMSF_raises_ValueError():
5064
with pytest.raises(ValueError):
5165
RMSF._negative_rmsf(np.array([-1, -1, -1]))
66+
67+
68+
@pytest.mark.parametrize("stop", [10, 33, 45, 90])
69+
@pytest.mark.parametrize("step", [1, 2, 3, 5])
70+
def test_n_frames(u, stop, step):
71+
F = RMSF(u.atoms)
72+
F.run(stop=stop, step=step)
73+
assert F.n_frames == len(range(0, stop, step))

0 commit comments

Comments
 (0)