diff --git a/package/CHANGELOG b/package/CHANGELOG index 90eaec16105..431b4ba2394 100644 --- a/package/CHANGELOG +++ b/package/CHANGELOG @@ -18,7 +18,7 @@ The rules for this file: calcraven,xiki-tempula, mieczyslaw, manuel.nuno.melo, PicoCentauri, hanatok, rmeli, aditya-kamath, tirkarthi, LeonardoBarneschi, hejamu, biogen98, orioncohen, z3y50n, hp115, ojeda-e, thadanipaarth, HenryKobin, - 1ut, sulays, PicoCentauri, ahy3nz + 1ut, sulays, ahy3nz * 2.0.0 @@ -174,6 +174,9 @@ Enhancements checking if it can be used in parallel analysis. (Issue #2996, PR #2950) Changes + * `DensityAnalysis` now uses the `results.density` attribute for storing + data. The `DensityAnalysis.density` attribute is now deprecated + (Issue #3261) * Deprecated analysis.hbonds.hbond_analysis has been removed in favour of analysis.hydrogenbonds.hbond_analysis (Issues #2739, #2746) * `GNMAnalysis`, `LinearDensity`, `PersistenceLength` and @@ -222,6 +225,9 @@ Changes * Added OpenMM coordinate and topology converters (Issue #2863, PR #2917) Deprecations + * The `density` attribute of `analysis.density.DensityAnalysis` is now + deprecated in favour of `results.density`. It will be removed in 3.0.0 + (Issue #3261) * The analysis.hbonds.hbond_autocorrel code has been moved to analysis.hydrogenbonds.hbond_autocorrel and will be removed from analysis.hbonds in 3.0.0 (PR #3258) diff --git a/package/MDAnalysis/analysis/density.py b/package/MDAnalysis/analysis/density.py index 2895fde798c..dda724726d9 100644 --- a/package/MDAnalysis/analysis/density.py +++ b/package/MDAnalysis/analysis/density.py @@ -74,8 +74,8 @@ ow = u.select_atoms("name OW") D = DensityAnalysis(ow, delta=1.0) D.run() - D.density.convert_density('TIP4P') - D.density.export("water.dx", type="double") + D.results.density.convert_density('TIP4P') + D.results.density.export("water.dx", type="double") The positions of all water oxygens (the :class:`AtomGroup` `ow`) are histogrammed on a grid with spacing *delta* = 1 Å. Initially the density is @@ -87,9 +87,9 @@ can be read in VMD_, Chimera_, or PyMOL_. The :class:`Density` object is accessible as the -:attr:`DensityAnalysis.density` attribute. In particular, the data for the -density is stored as a NumPy array in :attr:`Density.grid`, which can be -processed in any manner. +:attr:`DensityAnalysis.results.density` attribute. In particular, the data +for the density is stored as a NumPy array in :attr:`Density.grid`, which can +be processed in any manner. Creating densities @@ -102,10 +102,12 @@ :members: :inherited-members: run - .. attribute:: density + .. attribute:: results.density - After the analysis (see the :meth:`~DensityAnalysis.run` method), the resulting density is - stored in the :attr:`density` attribute as a :class:`Density` instance. + After the analysis (see the :meth:`~DensityAnalysis.run` method), the + resulting density is stored in the :attr:`results.density` attribute as + a :class:`Density` instance. Note: this replaces the now deprecated + :attr:`density` attribute. .. automethod:: _set_user_grid @@ -166,7 +168,8 @@ import MDAnalysis from MDAnalysis.core import groups -from MDAnalysis.lib.util import fixedwidth_bins, iterable, asiterable +from MDAnalysis.lib.util import (fixedwidth_bins, iterable, asiterable, + deprecate,) from MDAnalysis.lib import NeighborSearch as NS from MDAnalysis import NoDataError, MissingDataWarning from .. import units @@ -208,12 +211,19 @@ class DensityAnalysis(AnalysisBase): zdim : float (optional) User defined z dimension box edge in ångström. - Returns - ------- - :class:`Density` + Attributes + ---------- + results.density : :class:`Density` A :class:`Density` instance containing a physical density of units :math:`Angstrom^{-3}`. + density : :class:`Density` + Alias to the :attr:`results.density`. + + .. deprecated:: 2.0.0 + Will be removed in MDAnalysis 3.0.0. Please use + :attr:`results.density` instead. + Raises ------ ValueError @@ -282,11 +292,11 @@ class DensityAnalysis(AnalysisBase): ow = u.select_atoms("name OW") D = density.DensityAnalysis(ow, delta=1.0) D.run() - D.density.convert_density('TIP4P') + D.results.density.convert_density('TIP4P') The positions of all water oxygens are histogrammed on a grid with spacing *delta* = 1 Å and stored as a :class:`Density` object in the attribute - :attr:`DensityAnalysis.density`. + :attr:`DensityAnalysis.results.density`. .. rubric:: Working with a density @@ -304,7 +314,7 @@ class DensityAnalysis(AnalysisBase): density in units of Å\ :sup:`-3`. If you are interested in recovering the underlying **probability density**, simply divide by the sum:: - probability_density = D.density.grid / D.density.grid.sum() + probability_density = D.results.density.grid / D.results.density.grid.sum() Similarly, if you would like to recover a grid containing a **histogram of atom counts**, simply multiply by the volume `dV` of each bin (or voxel); @@ -314,10 +324,10 @@ class DensityAnalysis(AnalysisBase): import numpy as np # ensure that the density is A^{-3} - D.density.convert_density("A^{-3}") + D.results.density.convert_density("A^{-3}") - dV = np.prod(D.density.delta) - atom_count_histogram = D.density.grid * dV + dV = np.prod(D.results.density.delta) + atom_count_histogram = D.results.density.grid * dV .. rubric:: Writing the density to a file @@ -330,7 +340,7 @@ class DensityAnalysis(AnalysisBase): `_ ``water.dx`` that can be read with VMD, PyMOL, or Chimera:: - D.density.export("water.dx", type="double") + D.results.density.export("water.dx", type="double") .. rubric:: Example: Water density in the whole simulation @@ -384,6 +394,8 @@ class DensityAnalysis(AnalysisBase): .. versionadded:: 1.0.0 .. versionchanged:: 2.0.0 :func:`_set_user_grid` is now a method of :class:`DensityAnalysis`. + :class:`Density` results are now stored in a + :class:`MDAnalysis.analysis.base.Results` instance. """ def __init__(self, atomgroup, delta=1.0, @@ -457,7 +469,6 @@ def _prepare(self): self._edges = edges self._arange = arange self._bins = bins - self.density = None def _single_frame(self): h, _ = np.histogramdd(self._atomgroup.positions, @@ -476,7 +487,15 @@ def _conclude(self): units={'length': "Angstrom"}, parameters={'isDensity': False}) density.make_density() - self.density = density + self.results.density = density + + @property + def density(self): + wmsg = ("The `density` attribute was deprecated in MDAnalysis 2.0.0 " + "and will be removed in MDAnalysis 3.0.0. Please use " + "`results.density` instead") + warnings.warn(wmsg, DeprecationWarning) + return self.results.density @staticmethod def _set_user_grid(gridcenter, xdim, ydim, zdim, smin, smax): diff --git a/testsuite/MDAnalysisTests/analysis/test_density.py b/testsuite/MDAnalysisTests/analysis/test_density.py index 81242bb5f59..bd76449a921 100644 --- a/testsuite/MDAnalysisTests/analysis/test_density.py +++ b/testsuite/MDAnalysisTests/analysis/test_density.py @@ -156,13 +156,15 @@ def check_DensityAnalysis(self, ag, ref_meandensity, runargs = runargs if runargs else {} with tmpdir.as_cwd(): D = density.DensityAnalysis(ag, delta=self.delta, **kwargs).run(**runargs) - assert_almost_equal(D.density.grid.mean(), ref_meandensity, + assert_almost_equal(D.results.density.grid.mean(), ref_meandensity, err_msg="mean density does not match") - D.density.export(self.outfile) + D.results.density.export(self.outfile) D2 = density.Density(self.outfile) - assert_almost_equal(D.density.grid, D2.grid, decimal=self.precision, - err_msg="DX export failed: different grid sizes") + assert_almost_equal( + D.results.density.grid, D2.grid, decimal=self.precision, + err_msg="DX export failed: different grid sizes" + ) @pytest.mark.parametrize("mode", ("static", "dynamic")) def test_run(self, mode, universe, tmpdir): @@ -211,7 +213,7 @@ def test_userdefn_boxshape(self, universe): universe.select_atoms(self.selections['static']), delta=1.0, xdim=8.0, ydim=12.0, zdim=17.0, gridcenter=self.gridcenters['static_defined']).run() - assert D.density.grid.shape == (8, 12, 17) + assert D.results.density.grid.shape == (8, 12, 17) def test_warn_userdefn_padding(self, universe): regex = (r"Box padding \(currently set at 1\.0\) is not used " @@ -294,6 +296,15 @@ def test_ValueError_noatomgroup(self, universe): D = density.DensityAnalysis( universe.select_atoms(self.selections['none'])).run(step=5) + def test_warn_results_deprecated(self, universe): + D = density.DensityAnalysis( + universe.select_atoms(self.selections['static'])) + D.run(stop=1) + wmsg = "The `density` attribute was deprecated in MDAnalysis 2.0.0" + with pytest.warns(DeprecationWarning, match=wmsg): + assert_equal(D.density.grid, D.results.density.grid) + + class TestGridImport(object): @block_import('gridData')