diff --git a/package/CHANGELOG b/package/CHANGELOG index 2e37adca064..03315098bcf 100644 --- a/package/CHANGELOG +++ b/package/CHANGELOG @@ -79,6 +79,8 @@ Enhancements convert between a parmed.Structure and MDAnalysis Universe (PR #2404) Changes + * Removes `save()` function from contacts, diffusionmap, hole, LinearDensity, + and rms (Issue #1745). * Removes; `save_table()` from :class:`HydrogenBondAnalysis`, `save_results()` from :class:`HydrogenBondAutoCorrel`, and `save_results()`/`filename`/`store` from :class:`PSAnalysis`. Also sets diff --git a/package/MDAnalysis/analysis/contacts.py b/package/MDAnalysis/analysis/contacts.py index 9c156db7ed9..e794fb9da40 100644 --- a/package/MDAnalysis/analysis/contacts.py +++ b/package/MDAnalysis/analysis/contacts.py @@ -216,7 +216,7 @@ def is_any_closer(r, r0, dist=2.5): import MDAnalysis import MDAnalysis.lib.distances -from MDAnalysis.lib.util import openany, deprecate +from MDAnalysis.lib.util import openany from MDAnalysis.analysis.distances import distance_array from MDAnalysis.core.groups import AtomGroup from .base import AnalysisBase @@ -370,6 +370,10 @@ class Contacts(AnalysisBase): timeseries : list list containing *Q* for all refgroup pairs and analyzed frames + .. versionchanged:: 1.0.0 + ``save()`` method has been removed. Use ``np.savetxt()`` on + :attr:`Contacts.timeseries` instead. + """ def __init__(self, u, selection, refgroup, method="hard_cut", radius=4.5, kwargs=None, **basekwargs): @@ -447,20 +451,6 @@ def _single_frame(self): self.timeseries[self._frame_index][i] = q - @deprecate(release="0.19.0", remove="1.0.0") - def save(self, outfile): - """save contacts timeseries - - Parameters - ---------- - outfile : str - file to save contacts - - """ - np.savetxt(outfile, self.timeseries, - header="# q1 analysis\n", comments='') - - def _new_selections(u_orig, selections, frame): """create stand alone AGs from selections at frame""" u = MDAnalysis.Universe(u_orig.filename, u_orig.trajectory.filename) diff --git a/package/MDAnalysis/analysis/diffusionmap.py b/package/MDAnalysis/analysis/diffusionmap.py index 7da82eb8521..407e0244c58 100644 --- a/package/MDAnalysis/analysis/diffusionmap.py +++ b/package/MDAnalysis/analysis/diffusionmap.py @@ -176,7 +176,6 @@ from MDAnalysis.core.universe import Universe from .rms import rmsd from .base import AnalysisBase -from MDAnalysis.lib.util import deprecate logger = logging.getLogger("MDAnalysis.analysis.diffusionmap") @@ -197,6 +196,10 @@ class DistanceMatrix(AnalysisBase): Array of all possible ij metric distances between frames in trajectory. This matrix is symmetric with zeros on the diagonal. + .. versionchanged:: 1.0.0 + ``save()`` method has been removed. You can use ``np.save()`` on + :attr:`DistanceMatrix.dist_matrix` instead. + """ def __init__(self, u, select='all', metric=rmsd, cutoff=1E0-5, weights=None, **kwargs): @@ -264,20 +267,6 @@ def _single_frame(self): def _conclude(self): self._calculated = True - @deprecate(release="0.19.0", remove="1.0.0", - message="Use ``np.save(filename, DistanceMatrix.dist_matrix)`` instead.") - def save(self, filename): - """save squared distance matrix - - Parameters - ---------- - outfile : str - file to save distance matrix - - """ - np.save(filename, self.dist_matrix) - logger.info("Wrote the distance-squared matrix to file %r", filename) - class DiffusionMap(object): """Non-linear dimension reduction method diff --git a/package/MDAnalysis/analysis/hole.py b/package/MDAnalysis/analysis/hole.py index baca0f723eb..a8b509e415b 100644 --- a/package/MDAnalysis/analysis/hole.py +++ b/package/MDAnalysis/analysis/hole.py @@ -277,7 +277,7 @@ from MDAnalysis import Universe from MDAnalysis.exceptions import ApplicationError from MDAnalysis.lib.util import (which, realpath, asiterable, - FORTRANReader, deprecate) + FORTRANReader) from ..due import due, Doi @@ -387,23 +387,13 @@ def seq2str(v): class BaseHOLE(object): - """Baseclass for HOLE analysis, providing plotting and utility functions""" + """Baseclass for HOLE analysis, providing plotting and utility functions - @deprecate(release="0.19.0", remove="1.0.0", - message="You can instead use " - "``cPickle.dump(HOLE.profiles, open(filename, 'wb'))``.") - def save(self, filename="hole.pickle"): - """Save :attr:`profiles` as a Python pickle file *filename*. + .. versionchanged:: 1.0.0 + ``save()`` method was removed. You can use ``cPickle.dump()`` on + :attr:`BaseHOLE.profiles` instead. - Load profiles dictionary with :: - - import cPickle - profiles = cPickle.load(open(filename)) - - - """ - - cPickle.dump(self.profiles, open(filename, "wb"), cPickle.HIGHEST_PROTOCOL) + """ def _process_plot_kwargs(self, kwargs): kw = {} diff --git a/package/MDAnalysis/analysis/lineardensity.py b/package/MDAnalysis/analysis/lineardensity.py index 6f773cb7300..064323cae89 100644 --- a/package/MDAnalysis/analysis/lineardensity.py +++ b/package/MDAnalysis/analysis/lineardensity.py @@ -35,7 +35,6 @@ import numpy as np from MDAnalysis.analysis.base import AnalysisBase -from MDAnalysis.lib.util import deprecate class LinearDensity(AnalysisBase): """Linear density profile @@ -80,6 +79,11 @@ class LinearDensity(AnalysisBase): .. versionadded:: 0.14.0 + .. versionchanged:: 1.0.0 + ``save()`` method was removed, you can use ``np.savetxt()`` or + ``np.save()`` on the :attr:`LinearDensity.results` dictionary contents + instead. + """ def __init__(self, selection, grouping='atoms', binsize=0.25, **kwargs): @@ -192,87 +196,6 @@ def _conclude(self): self.results[dim]['pos_std'] /= self.results[dim]['slice volume'] * k self.results[dim]['char_std'] /= self.results[dim]['slice volume'] * k - @deprecate(release="0.19.0", remove="1.0.0", - message="Instead save the :attr:`results` dictionary directly in " - "your favorite format (pickle, json, hdf5, ...).") - def save(self, description='', form='txt'): - """Save density profile to file - - Allows to save the density profile to either a ASCII txt file or a - binary numpy npz file. Output file has extension 'ldens' and begins - with the name of the trajectory file. - - Parameters - ---------- - description : str - An arbitrary description added to the output filename. Can be useful - form : str {'txt', 'npz'} - Format of the output. 'txt' will generate an ASCII text file while - 'npz' will produce a numpy binary file. - - Example - ------- - After initializing and running a `LinearDensity` object, results can be - written to file as follows:: - - ldens.save(description='mydensprof', form='txt') - - which will output the linear density profiles in a file named - `.mydensprof_.ldens`. - - - """ - # Take root of trajectory filename for output file naming - trajname = path.splitext(path.basename( - self._universe.trajectory.filename))[0] - # additional string for naming the output file - description = description + "_" + str(self.grouping) - filename = trajname + "." + description + ".ldens" - - if form == 'txt': - self._savetxt(filename) - elif form == 'npz': - self._savez(filename) - else: - raise ValueError('form argument must be either txt or npz') - - def _savetxt(self, filename): - # DEPRECATED: remove in 1.0.0 - bins = np.linspace(0.0, max(self.dimensions), num=self.nbins) - - # Create list of results which will be output - output = [bins] - - for dim in ['x', 'y', 'z']: - output.append(self.results[dim]['pos']) - output.append(self.results[dim]['pos_std']) - - for dim in ['x', 'y', 'z']: - output.append(self.results[dim]['char']) - output.append(self.results[dim]['char_std']) - - density = self.totalmass / self.volume - header = ("1 coord [Ang] 2-7 mass density (x,sx,y,sz,z,sz) [g/cm^3]" - "8-13 charge density (x,sx,y,sz,z,sz) [e/A^3]\n Average " - "density: {} g/cm3".format(density)) - np.savetxt(filename, - np.column_stack(output), - fmt='%10.5f', - header=header) - - def _savez(self, filename): - # DEPRECATED: remove in 1.0.0 - bins = np.linspace(0.0, max(self.dimensions), num=self.nbins) - dictionary = {'bins': bins} - - for dim in self.results: - self.results[dim].pop('dim') - self.results[dim].pop('slice volume') - for key in self.results[dim]: - dictionary[dim + "_" + key] = self.results[dim][key] - - np.savez(filename, **dictionary) - def _add_other_results(self, other): # For parallel analysis results = self.results diff --git a/package/MDAnalysis/analysis/rms.py b/package/MDAnalysis/analysis/rms.py index 049f242a08a..9419c523350 100644 --- a/package/MDAnalysis/analysis/rms.py +++ b/package/MDAnalysis/analysis/rms.py @@ -87,8 +87,7 @@ select="backbone", # superimpose on whole backbone of the whole protein groupselections=["backbone and (resid 1-29 or resid 60-121 or resid 160-214)", # CORE "backbone and resid 122-159", # LID - "backbone and resid 30-59"], # NMP - filename="rmsd_all_CORE_LID_NMP.dat") + "backbone and resid 30-59"]) # NMP R.run() import matplotlib.pyplot as plt @@ -147,7 +146,7 @@ from MDAnalysis.analysis.base import AnalysisBase from MDAnalysis.exceptions import SelectionError, NoDataError from MDAnalysis.lib.log import ProgressMeter -from MDAnalysis.lib.util import asiterable, iterable, get_weights, deprecate +from MDAnalysis.lib.util import asiterable, iterable, get_weights logger = logging.getLogger('MDAnalysis.analysis.rmsd') @@ -331,11 +330,14 @@ class RMSD(AnalysisBase): Run the analysis with :meth:`RMSD.run`, which stores the results in the array :attr:`RMSD.rmsd`. + .. versionchanged:: 1.0.0 + ``save()`` method was removed, use ``np.savetxt()`` on + :attr:`RMSD.rmsd` instead. + """ def __init__(self, atomgroup, reference=None, select='all', - groupselections=None, filename="rmsd.dat", - weights=None, tol_mass=0.1, ref_frame=0, **kwargs): - # DEPRECATION: remove filename kwarg in 1.0 + groupselections=None, weights=None, tol_mass=0.1, + ref_frame=0, **kwargs): r"""Parameters ---------- atomgroup : AtomGroup or Universe @@ -379,12 +381,6 @@ def __init__(self, atomgroup, reference=None, select='all', .. Note:: Experimental feature. Only limited error checking implemented. - filename : str (optional) - write RMSD into file with :meth:`RMSD.save` - - .. deprecated:; 0.19.0 - `filename` will be removed together with :meth:`save` in 1.0. - weights : {"mass", ``None``} or array_like (optional) choose weights. With ``"mass"`` uses masses as weights; with ``None`` weigh each atom equally. If a float array of the same length as @@ -466,8 +462,8 @@ def __init__(self, atomgroup, reference=None, select='all', .. versionchanged:: 0.17.0 removed deprecated `mass_weighted` keyword; `groupselections` are *not* rotationally superimposed any more. - .. deprecated:: 0.19.0 - `filename` will be removed in 1.0 + .. versionchanged:: 1.0.0 + `filename` keyword was removed. """ super(RMSD, self).__init__(atomgroup.universe.trajectory, @@ -481,7 +477,6 @@ def __init__(self, atomgroup, reference=None, select='all', self.weights = weights self.tol_mass = tol_mass self.ref_frame = ref_frame - self.filename = filename # DEPRECATED in 0.19.0, remove in 1.0.0 self.ref_atoms = self.reference.select_atoms(*select['reference']) self.mobile_atoms = self.atomgroup.select_atoms(*select['mobile']) @@ -556,10 +551,6 @@ def __init__(self, atomgroup, reference=None, select='all', "weights=None or weights='mass', not a weight " "array.") - # initialized to note for testing the save function - self.rmsd = None - - def _prepare(self): self._n_atoms = self.mobile_atoms.n_atoms @@ -653,27 +644,6 @@ def _single_frame(self): self._pm.rmsd = self.rmsd[self._frame_index, 2] - @deprecate(release="0.19.0", remove="1.0.0", - message="You can instead use " - "``np.savetxt(filename, RMSD.rmsd)``.") - def save(self, filename=None): - """Save RMSD from :attr:`RMSD.rmsd` to text file *filename*. - - Parameters - ---------- - filename : str (optional) - if no filename is given the default provided to the constructor is - used. - - """ - filename = filename or self.filename - if filename is not None: - if self.rmsd is None: - raise NoDataError("rmsd has not been calculated yet") - np.savetxt(filename, self.rmsd) - logger.info("Wrote RMSD timeseries to file %r", filename) - return filename - class RMSF(AnalysisBase): r"""Calculate RMSF of given atoms across a trajectory. diff --git a/testsuite/MDAnalysisTests/analysis/test_contacts.py b/testsuite/MDAnalysisTests/analysis/test_contacts.py index a42a9e8abd6..c342920bc85 100644 --- a/testsuite/MDAnalysisTests/analysis/test_contacts.py +++ b/testsuite/MDAnalysisTests/analysis/test_contacts.py @@ -302,16 +302,6 @@ def test_non_callable_method(self, universe): with pytest.raises(ValueError): self._run_Contacts(universe, method=2, stop=2) - def test_save(self, universe): - with tempdir.in_tempdir(): - ca = self._run_Contacts(universe) - ca.save('testfile.npy') - saved = np.genfromtxt('testfile.npy') - assert_array_almost_equal(ca.timeseries, saved) - # check the header was written correctly - with open('testfile.npy', 'r') as fin: - assert fin.readline().strip() == '# q1 analysis' - def test_q1q2(): u = mda.Universe(PSF, DCD) diff --git a/testsuite/MDAnalysisTests/analysis/test_rms.py b/testsuite/MDAnalysisTests/analysis/test_rms.py index 8971f83ad34..6071a558b83 100644 --- a/testsuite/MDAnalysisTests/analysis/test_rms.py +++ b/testsuite/MDAnalysisTests/analysis/test_rms.py @@ -221,20 +221,15 @@ def test_rmsd_single_frame(self, universe): err_msg="error: rmsd profile should match" + "test values") - def test_mass_weighted_and_save(self, universe, outfile, correct_values): + def test_mass_weighted(self, universe, correct_values): # mass weighting the CA should give the same answer as weighing # equally because all CA have the same mass RMSD = MDAnalysis.analysis.rms.RMSD(universe, select='name CA', weights='mass').run(step=49) - RMSD.save(outfile) assert_almost_equal(RMSD.rmsd, correct_values, 4, err_msg="error: rmsd profile should match" "test values") - saved = np.loadtxt(outfile) - assert_almost_equal(RMSD.rmsd, saved, 4, - err_msg="error: rmsd profile should match " - "saved test values") def test_custom_weighted(self, universe, correct_values_mass): RMSD = MDAnalysis.analysis.rms.RMSD(universe, weights="mass").run(step=49) @@ -324,11 +319,6 @@ def test_group_selections_unequal_len(self, universe): groupselections= ['resname MET','type NH3']) - def test_save_before_run(self, universe): - with pytest.raises(NoDataError): - RMSD = MDAnalysis.analysis.rms.RMSD(universe) - RMSD.save('blah') - class TestRMSF(object): @pytest.fixture()