From 3eeadcc2b474a82faf13fd4ec3b785d3f159a8a1 Mon Sep 17 00:00:00 2001 From: IAlibay Date: Thu, 6 May 2021 16:42:49 +0100 Subject: [PATCH 1/4] Moves msd results to use the Results class --- package/CHANGELOG | 3 ++ package/MDAnalysis/analysis/msd.py | 53 +++++++++++++++---- .../MDAnalysisTests/analysis/test_msd.py | 43 ++++++++++----- 3 files changed, 74 insertions(+), 25 deletions(-) diff --git a/package/CHANGELOG b/package/CHANGELOG index 560ff6430de..1d0dd6084e8 100644 --- a/package/CHANGELOG +++ b/package/CHANGELOG @@ -174,6 +174,9 @@ Enhancements checking if it can be used in parallel analysis. (Issue #2996, PR #2950) Changes + * `msd.EinsteinMSD` now uses the `analysis.base.Results` class to store + analysis results. The `EinsteinMSD.timeseries` and + `EinsteinMSD.msds_by_particle` attributes are now deprecated. * `GNMAnalysis`, `LinearDensity`, `PersistenceLength` and `AnalysisFromFunction` use the `results` attribute. * Fixed inaccurate docstring inside the RMSD class (Issue #2796, PR #3134) diff --git a/package/MDAnalysis/analysis/msd.py b/package/MDAnalysis/analysis/msd.py index f04859fa445..b24ec13f24a 100644 --- a/package/MDAnalysis/analysis/msd.py +++ b/package/MDAnalysis/analysis/msd.py @@ -90,7 +90,7 @@ .. code-block:: python - msd = MSD.timeseries + msd = MSD.results.timeseries Visual inspection of the MSD is important, so let's take a look at it with a simple plot. @@ -220,6 +220,7 @@ """ import numpy as np +import warnings import logging from ..due import due, Doi from .base import AnalysisBase @@ -261,16 +262,29 @@ class EinsteinMSD(AnalysisBase): ---------- dim_fac : int Dimensionality :math:`d` of the MSD. - timeseries : :class:`numpy.ndarray` + results.timeseries : :class:`numpy.ndarray` The averaged MSD over all the particles with respect to lag-time. - msds_by_particle : :class:`numpy.ndarray` + timeseries : :class:`numpy.ndarray` + Deprecated alias to the :attr:`results.timeseries` attribute. Will + be removed in MDAnalysis 3.0.0. + results.msds_by_particle : :class:`numpy.ndarray` The MSD of each individual particle with respect to lag-time. + msds_by_particle : :class:`numpy.ndarray` + Deprecated alias to the :attr:`results.msds_by_particle` attribute. + Will be removed in MDAnalysis 3.0.0 ag : :class:`AtomGroup` The :class:`AtomGroup` resulting from your selection n_frames : int Number of frames included in the analysis. n_particles : int Number of particles MSD was calculated over. + + + .. deprecated:: 2.0.0 + The attributes :attr:`timeseries` and :attr:`msds_by_particle` are + deprecated in favour of :attr:`results.timeseries` and + :attr:`results.msds_by_particle` respectively. The deprecated + attributes will be removed in MDAnalysis 3.0.0. """ def __init__(self, u, select='all', msd_type='xyz', fft=True, **kwargs): @@ -307,16 +321,17 @@ def __init__(self, u, select='all', msd_type='xyz', fft=True, **kwargs): self._position_array = None # result - self.msds_by_particle = None - self.timeseries = None + self.results.msds_by_particle = None + self.results.timeseries = None def _prepare(self): # self.n_frames only available here # these need to be zeroed prior to each run() call - self.msds_by_particle = np.zeros((self.n_frames, self.n_particles)) + self.results.msds_by_particle = np.zeros((self.n_frames, + self.n_particles)) self._position_array = np.zeros( (self.n_frames, self.n_particles, self.dim_fac)) - # self.timeseries not set here + # self.results.timeseries not set here def _parse_msd_type(self): r""" Sets up the desired dimensionality of the MSD. @@ -360,8 +375,8 @@ def _conclude_simple(self): for lag in lagtimes: disp = positions[:-lag, :, :] - positions[lag:, :, :] sqdist = np.square(disp).sum(axis=-1) - self.msds_by_particle[lag, :] = np.mean(sqdist, axis=0) - self.timeseries = self.msds_by_particle.mean(axis=1) + self.results.msds_by_particle[lag, :] = np.mean(sqdist, axis=0) + self.results.timeseries = self.results.msds_by_particle.mean(axis=1) def _conclude_fft(self): # with FFT, np.float64 bit prescision required. r""" Calculates the MSD via the FCA fast correlation algorithm. @@ -382,6 +397,22 @@ def _conclude_fft(self): # with FFT, np.float64 bit prescision required. positions = self._position_array.astype(np.float64) for n in range(self.n_particles): - self.msds_by_particle[:, n] = tidynamics.msd( + self.results.msds_by_particle[:, n] = tidynamics.msd( positions[:, n, :]) - self.timeseries = self.msds_by_particle.mean(axis=1) + self.results.timeseries = self.results.msds_by_particle.mean(axis=1) + + @property + def timeseries(self): + wmsg = ("The `timeseries` attribute was deprecated in MDAnalysis " + "2.0.0 and will be removed in MDAnalysis 3.0.0. Please use " + "`results.timeseries` instead.") + warnings.warn(wmsg, DeprecationWarning) + return self.results.timeseries + + @property + def msds_by_particle(self): + wmsg = ("The `msds_by_particle` attribute was deprecated in " + "MDAnalysis 2.0.0 and will be removed in MDAnalysis 3.0.0. " + "Please use `results.msds_by_particle` instead.") + warnings.warn(wmsg, DeprecationWarning) + return self.results.msds_by_particle diff --git a/testsuite/MDAnalysisTests/analysis/test_msd.py b/testsuite/MDAnalysisTests/analysis/test_msd.py index 46fc017dbff..022cb56d4a4 100644 --- a/testsuite/MDAnalysisTests/analysis/test_msd.py +++ b/testsuite/MDAnalysisTests/analysis/test_msd.py @@ -123,7 +123,7 @@ def test_simple_step_traj_all_dims(self, step_traj, NSTEP, dim, m_simple = MSD(step_traj, 'all', msd_type=dim, fft=False) m_simple.run() poly = characteristic_poly(NSTEP, dim_factor) - assert_almost_equal(m_simple.timeseries, poly, decimal=4) + assert_almost_equal(m_simple.results.timeseries, poly, decimal=4) @pytest.mark.parametrize("dim, dim_factor", [ ('xyz', 3), ('xy', 2), ('xz', 2), ('yz', 2), ('x', 1), ('y', 1), @@ -137,16 +137,30 @@ def test_simple_start_stop_step_all_dims(self, step_traj, NSTEP, dim, m_simple.run(start=10, stop=1000, step=10) poly = characteristic_poly(NSTEP, dim_factor) # polynomial must take offset start into account - assert_almost_equal(m_simple.timeseries, poly[0:990:10], decimal=4) + assert_almost_equal(m_simple.results.timeseries, poly[0:990:10], + decimal=4) def test_random_walk_u_simple(self, random_walk_u): # regress against random_walk test data msd_rw = MSD(random_walk_u, 'all', msd_type='xyz', fft=False) msd_rw.run() - norm = np.linalg.norm(msd_rw.timeseries) + norm = np.linalg.norm(msd_rw.results.timeseries) val = 3932.39927487146 assert_almost_equal(norm, val, decimal=5) + def test_deprecated_attributes(self, random_walk_u): + msd_rw = MSD(random_walk_u, 'all', msd_type='xyz', fft=False) + msd_rw.run(stop=2) + + wmsg = "The `timeseries` attribute was deprecated in MDAnalysis" + with pytest.warns(DeprecationWarning, match=wmsg): + assert_equal(msd_rw.timeseries, msd_rw.results.timeseries) + + wmsg = "The `msds_by_particle` attribute was deprecated in MDAnalysis" + with pytest.warns(DeprecationWarning, match=wmsg): + assert_equal(msd_rw.msds_by_particle, + msd_rw.results.msds_by_particle) + @pytest.mark.skipif(import_not_available("tidynamics"), reason="Test skipped because tidynamics not found") @@ -161,14 +175,14 @@ def msd_fft(self, u, SELECTION): def test_fft_vs_simple_default(self, msd, msd_fft): # testing on the PSF, DCD trajectory - timeseries_simple = msd.timeseries - timeseries_fft = msd_fft.timeseries + timeseries_simple = msd.results.timeseries + timeseries_fft = msd_fft.results.timeseries assert_almost_equal(timeseries_simple, timeseries_fft, decimal=4) def test_fft_vs_simple_default_per_particle(self, msd, msd_fft): # check fft and simple give same result per particle - per_particle_simple = msd.msds_by_particle - per_particle_fft = msd_fft.msds_by_particle + per_particle_simple = msd.results.msds_by_particle + per_particle_fft = msd_fft.results.msds_by_particle assert_almost_equal(per_particle_simple, per_particle_fft, decimal=4) @pytest.mark.parametrize("dim", ['xyz', 'xy', 'xz', 'yz', 'x', 'y', 'z']) @@ -176,10 +190,10 @@ def test_fft_vs_simple_all_dims(self, u, SELECTION, dim): # check fft and simple give same result for each dimensionality m_simple = MSD(u, SELECTION, msd_type=dim, fft=False) m_simple.run() - timeseries_simple = m_simple.timeseries + timeseries_simple = m_simple.results.timeseries m_fft = MSD(u, SELECTION, msd_type=dim, fft=True) m_fft.run() - timeseries_fft = m_fft.timeseries + timeseries_fft = m_fft.results.timeseries assert_almost_equal(timeseries_simple, timeseries_fft, decimal=4) @pytest.mark.parametrize("dim", ['xyz', 'xy', 'xz', 'yz', 'x', 'y', 'z']) @@ -188,10 +202,10 @@ def test_fft_vs_simple_all_dims_per_particle(self, u, SELECTION, dim): # dimension m_simple = MSD(u, SELECTION, msd_type=dim, fft=False) m_simple.run() - per_particle_simple = m_simple.msds_by_particle + per_particle_simple = m_simple.results.msds_by_particle m_fft = MSD(u, SELECTION, msd_type=dim, fft=True) m_fft.run() - per_particle_fft = m_fft.msds_by_particle + per_particle_fft = m_fft.results.msds_by_particle assert_almost_equal(per_particle_simple, per_particle_fft, decimal=4) @pytest.mark.parametrize("dim, dim_factor", [ @@ -208,7 +222,7 @@ def test_fft_step_traj_all_dims(self, step_traj, NSTEP, dim, dim_factor): m_simple.run() poly = characteristic_poly(NSTEP, dim_factor) # this was relaxed from decimal=4 for numpy=1.13 test - assert_almost_equal(m_simple.timeseries, poly, decimal=3) + assert_almost_equal(m_simple.results.timeseries, poly, decimal=3) @pytest.mark.parametrize("dim, dim_factor", [( 'xyz', 3), ('xy', 2), ('xz', 2), ('yz', 2), ('x', 1), ('y', 1), @@ -222,12 +236,13 @@ def test_fft_start_stop_step_all_dims(self, step_traj, NSTEP, dim, m_simple.run(start=10, stop=1000, step=10) poly = characteristic_poly(NSTEP, dim_factor) # polynomial must take offset start into account - assert_almost_equal(m_simple.timeseries, poly[0:990:10], decimal=3) + assert_almost_equal(m_simple.results.timeseries, poly[0:990:10], + decimal=3) def test_random_walk_u_fft(self, random_walk_u): # regress against random_walk test data msd_rw = MSD(random_walk_u, 'all', msd_type='xyz', fft=True) msd_rw.run() - norm = np.linalg.norm(msd_rw.timeseries) + norm = np.linalg.norm(msd_rw.results.timeseries) val = 3932.39927487146 assert_almost_equal(norm, val, decimal=5) From 6310ace1e4334a9b2bb00f04ebca05bc8a520c12 Mon Sep 17 00:00:00 2001 From: IAlibay Date: Thu, 6 May 2021 16:49:57 +0100 Subject: [PATCH 2/4] update changelog --- package/CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/CHANGELOG b/package/CHANGELOG index 1d0dd6084e8..8d41f2315e3 100644 --- a/package/CHANGELOG +++ b/package/CHANGELOG @@ -176,7 +176,7 @@ Enhancements Changes * `msd.EinsteinMSD` now uses the `analysis.base.Results` class to store analysis results. The `EinsteinMSD.timeseries` and - `EinsteinMSD.msds_by_particle` attributes are now deprecated. + `EinsteinMSD.msds_by_particle` attributes are now deprecated (Issue #3261) * `GNMAnalysis`, `LinearDensity`, `PersistenceLength` and `AnalysisFromFunction` use the `results` attribute. * Fixed inaccurate docstring inside the RMSD class (Issue #2796, PR #3134) From 5a2317c3caf560592b5408cfce469392b343fa9a Mon Sep 17 00:00:00 2001 From: IAlibay Date: Thu, 6 May 2021 18:54:46 +0100 Subject: [PATCH 3/4] msd was added in 2.0.0, deprecation is unecessary --- package/CHANGELOG | 3 +- package/MDAnalysis/analysis/msd.py | 28 +------------------ .../MDAnalysisTests/analysis/test_msd.py | 13 --------- 3 files changed, 2 insertions(+), 42 deletions(-) diff --git a/package/CHANGELOG b/package/CHANGELOG index 8d41f2315e3..7d2ec5d0859 100644 --- a/package/CHANGELOG +++ b/package/CHANGELOG @@ -175,8 +175,7 @@ Enhancements Changes * `msd.EinsteinMSD` now uses the `analysis.base.Results` class to store - analysis results. The `EinsteinMSD.timeseries` and - `EinsteinMSD.msds_by_particle` attributes are now deprecated (Issue #3261) + analysis results (Issue #3261) * `GNMAnalysis`, `LinearDensity`, `PersistenceLength` and `AnalysisFromFunction` use the `results` attribute. * Fixed inaccurate docstring inside the RMSD class (Issue #2796, PR #3134) diff --git a/package/MDAnalysis/analysis/msd.py b/package/MDAnalysis/analysis/msd.py index b24ec13f24a..3a843651b3f 100644 --- a/package/MDAnalysis/analysis/msd.py +++ b/package/MDAnalysis/analysis/msd.py @@ -264,14 +264,8 @@ class EinsteinMSD(AnalysisBase): Dimensionality :math:`d` of the MSD. results.timeseries : :class:`numpy.ndarray` The averaged MSD over all the particles with respect to lag-time. - timeseries : :class:`numpy.ndarray` - Deprecated alias to the :attr:`results.timeseries` attribute. Will - be removed in MDAnalysis 3.0.0. results.msds_by_particle : :class:`numpy.ndarray` The MSD of each individual particle with respect to lag-time. - msds_by_particle : :class:`numpy.ndarray` - Deprecated alias to the :attr:`results.msds_by_particle` attribute. - Will be removed in MDAnalysis 3.0.0 ag : :class:`AtomGroup` The :class:`AtomGroup` resulting from your selection n_frames : int @@ -280,11 +274,7 @@ class EinsteinMSD(AnalysisBase): Number of particles MSD was calculated over. - .. deprecated:: 2.0.0 - The attributes :attr:`timeseries` and :attr:`msds_by_particle` are - deprecated in favour of :attr:`results.timeseries` and - :attr:`results.msds_by_particle` respectively. The deprecated - attributes will be removed in MDAnalysis 3.0.0. + .. versionadded:: 2.0.0 """ def __init__(self, u, select='all', msd_type='xyz', fft=True, **kwargs): @@ -400,19 +390,3 @@ def _conclude_fft(self): # with FFT, np.float64 bit prescision required. self.results.msds_by_particle[:, n] = tidynamics.msd( positions[:, n, :]) self.results.timeseries = self.results.msds_by_particle.mean(axis=1) - - @property - def timeseries(self): - wmsg = ("The `timeseries` attribute was deprecated in MDAnalysis " - "2.0.0 and will be removed in MDAnalysis 3.0.0. Please use " - "`results.timeseries` instead.") - warnings.warn(wmsg, DeprecationWarning) - return self.results.timeseries - - @property - def msds_by_particle(self): - wmsg = ("The `msds_by_particle` attribute was deprecated in " - "MDAnalysis 2.0.0 and will be removed in MDAnalysis 3.0.0. " - "Please use `results.msds_by_particle` instead.") - warnings.warn(wmsg, DeprecationWarning) - return self.results.msds_by_particle diff --git a/testsuite/MDAnalysisTests/analysis/test_msd.py b/testsuite/MDAnalysisTests/analysis/test_msd.py index 022cb56d4a4..0a1af15ff58 100644 --- a/testsuite/MDAnalysisTests/analysis/test_msd.py +++ b/testsuite/MDAnalysisTests/analysis/test_msd.py @@ -148,19 +148,6 @@ def test_random_walk_u_simple(self, random_walk_u): val = 3932.39927487146 assert_almost_equal(norm, val, decimal=5) - def test_deprecated_attributes(self, random_walk_u): - msd_rw = MSD(random_walk_u, 'all', msd_type='xyz', fft=False) - msd_rw.run(stop=2) - - wmsg = "The `timeseries` attribute was deprecated in MDAnalysis" - with pytest.warns(DeprecationWarning, match=wmsg): - assert_equal(msd_rw.timeseries, msd_rw.results.timeseries) - - wmsg = "The `msds_by_particle` attribute was deprecated in MDAnalysis" - with pytest.warns(DeprecationWarning, match=wmsg): - assert_equal(msd_rw.msds_by_particle, - msd_rw.results.msds_by_particle) - @pytest.mark.skipif(import_not_available("tidynamics"), reason="Test skipped because tidynamics not found") From 59e00cee8bccb9c4e394aabcfdced3105a4c6ee9 Mon Sep 17 00:00:00 2001 From: IAlibay Date: Thu, 6 May 2021 18:56:45 +0100 Subject: [PATCH 4/4] Remove unecessary import --- package/MDAnalysis/analysis/msd.py | 1 - 1 file changed, 1 deletion(-) diff --git a/package/MDAnalysis/analysis/msd.py b/package/MDAnalysis/analysis/msd.py index 3a843651b3f..436943566b9 100644 --- a/package/MDAnalysis/analysis/msd.py +++ b/package/MDAnalysis/analysis/msd.py @@ -220,7 +220,6 @@ """ import numpy as np -import warnings import logging from ..due import due, Doi from .base import AnalysisBase