From e776f124c18c41f8990b487e8557d3ad82fe7d1f Mon Sep 17 00:00:00 2001 From: Irfan Alibay Date: Sun, 27 Oct 2024 01:06:58 +0000 Subject: [PATCH] Expose `MDAnalysis.topology.guessers` and `MDAnalysis.guesser.tables` under `MDAnalysis.topology.core` (#4766) * Enable direct import via MDAnalysis.topology * Switch deprecated guesser methods to individual deprecate calls --- package/MDAnalysis/topology/core.py | 8 +++ package/MDAnalysis/topology/guessers.py | 24 +++++-- .../MDAnalysisTests/topology/test_guessers.py | 64 +++++++++++++++++-- 3 files changed, 83 insertions(+), 13 deletions(-) diff --git a/package/MDAnalysis/topology/core.py b/package/MDAnalysis/topology/core.py index 3ed1c7a346..b5d7318301 100644 --- a/package/MDAnalysis/topology/core.py +++ b/package/MDAnalysis/topology/core.py @@ -38,4 +38,12 @@ from ..core._get_readers import get_parser_for from ..lib.util import cached +# Deprecated local imports +from MDAnalysis.guesser import tables +from .guessers import ( + guess_atom_element, guess_atom_type, + get_atom_mass, guess_atom_mass, guess_atom_charge, + guess_bonds, guess_angles, guess_dihedrals, guess_improper_dihedrals, +) + #tumbleweed diff --git a/package/MDAnalysis/topology/guessers.py b/package/MDAnalysis/topology/guessers.py index 7d81f23961..a4661c871c 100644 --- a/package/MDAnalysis/topology/guessers.py +++ b/package/MDAnalysis/topology/guessers.py @@ -107,19 +107,17 @@ from ..lib import distances from MDAnalysis.guesser import tables +from MDAnalysis.lib.util import deprecate -wmsg = ( - "Deprecated in version 2.8.0\n" +deprecation_msg = ( "MDAnalysis.topology.guessers is deprecated in favour of " - "the new Guessers API and will be removed in MDAnalysis version 3.0.0. " + "the new Guessers API. " "See MDAnalysis.guesser.default_guesser for more details." ) -warnings.warn(wmsg, category=DeprecationWarning) - - +@deprecate(release="2.8.0", remove="3.0.0", message=deprecation_msg) def guess_masses(atom_types): """Guess the mass of many atoms based upon their type @@ -137,6 +135,7 @@ def guess_masses(atom_types): return masses +@deprecate(release="2.8.0", remove="3.0.0", message=deprecation_msg) def validate_atom_types(atom_types): """Vaildates the atom types based on whether they are available in our tables @@ -162,6 +161,7 @@ def validate_atom_types(atom_types): warnings.warn("Failed to guess the mass for the following atom types: {}".format(atom_type)) +@deprecate(release="2.8.0", remove="3.0.0", message=deprecation_msg) def guess_types(atom_names): """Guess the atom type of many atoms based on atom name @@ -177,6 +177,7 @@ def guess_types(atom_names): return np.array([guess_atom_element(name) for name in atom_names], dtype=object) +@deprecate(release="2.8.0", remove="3.0.0", message=deprecation_msg) def guess_atom_type(atomname): """Guess atom type from the name. @@ -197,6 +198,8 @@ def guess_atom_type(atomname): NUMBERS = re.compile(r'[0-9]') # match numbers SYMBOLS = re.compile(r'[*+-]') # match *, +, - + +@deprecate(release="2.8.0", remove="3.0.0", message=deprecation_msg) def guess_atom_element(atomname): """Guess the element of the atom from the name. @@ -246,6 +249,7 @@ def guess_atom_element(atomname): return no_symbols +@deprecate(release="2.8.0", remove="3.0.0", message=deprecation_msg) def guess_bonds(atoms, coords, box=None, **kwargs): r"""Guess if bonds exist between two atoms based on their distance. @@ -354,6 +358,7 @@ def guess_bonds(atoms, coords, box=None, **kwargs): return tuple(bonds) +@deprecate(release="2.8.0", remove="3.0.0", message=deprecation_msg) def guess_angles(bonds): """Given a list of Bonds, find all angles that exist between atoms. @@ -390,6 +395,7 @@ def guess_angles(bonds): return tuple(angles_found) +@deprecate(release="2.8.0", remove="3.0.0", message=deprecation_msg) def guess_dihedrals(angles): """Given a list of Angles, find all dihedrals that exist between atoms. @@ -423,6 +429,7 @@ def guess_dihedrals(angles): return tuple(dihedrals_found) +@deprecate(release="2.8.0", remove="3.0.0", message=deprecation_msg) def guess_improper_dihedrals(angles): """Given a list of Angles, find all improper dihedrals that exist between atoms. @@ -459,6 +466,7 @@ def guess_improper_dihedrals(angles): return tuple(dihedrals_found) +@deprecate(release="2.8.0", remove="3.0.0", message=deprecation_msg) def get_atom_mass(element): """Return the atomic mass in u for *element*. @@ -478,6 +486,7 @@ def get_atom_mass(element): return 0.0 +@deprecate(release="2.8.0", remove="3.0.0", message=deprecation_msg) def guess_atom_mass(atomname): """Guess a mass based on the atom name. @@ -489,6 +498,7 @@ def guess_atom_mass(atomname): return get_atom_mass(guess_atom_element(atomname)) +@deprecate(release="2.8.0", remove="3.0.0", message=deprecation_msg) def guess_atom_charge(atomname): """Guess atom charge from the name. @@ -498,6 +508,7 @@ def guess_atom_charge(atomname): return 0.0 +@deprecate(release="2.8.0", remove="3.0.0", message=deprecation_msg) def guess_aromaticities(atomgroup): """Guess aromaticity of atoms using RDKit @@ -518,6 +529,7 @@ def guess_aromaticities(atomgroup): return np.array([atom.GetIsAromatic() for atom in mol.GetAtoms()]) +@deprecate(release="2.8.0", remove="3.0.0", message=deprecation_msg) def guess_gasteiger_charges(atomgroup): """Guess Gasteiger partial charges using RDKit diff --git a/testsuite/MDAnalysisTests/topology/test_guessers.py b/testsuite/MDAnalysisTests/topology/test_guessers.py index 7ab62b56ee..939d147d34 100644 --- a/testsuite/MDAnalysisTests/topology/test_guessers.py +++ b/testsuite/MDAnalysisTests/topology/test_guessers.py @@ -46,12 +46,6 @@ reason="requires RDKit") -def test_moved_to_guessers_warning(): - wmsg = "deprecated in favour of the new Guessers API" - with pytest.warns(DeprecationWarning, match=wmsg): - reload(guessers) - - class TestGuessMasses(object): def test_guess_masses(self): out = guessers.guess_masses(['C', 'C', 'H']) @@ -60,7 +54,7 @@ def test_guess_masses(self): assert_equal(out, np.array([12.011, 12.011, 1.008])) def test_guess_masses_warn(self): - with pytest.warns(UserWarning): + with pytest.warns(UserWarning, match='Failed to guess the mass'): guessers.guess_masses(['X']) def test_guess_masses_miss(self): @@ -210,3 +204,59 @@ def test_guess_gasteiger_charges(smi): u = mda.Universe(mol) values = guessers.guess_gasteiger_charges(u.atoms) assert_equal(values, expected) + + +class TestDeprecationWarning: + wmsg = ( + "MDAnalysis.topology.guessers is deprecated in favour of " + "the new Guessers API. " + "See MDAnalysis.guesser.default_guesser for more details." + ) + + @pytest.mark.parametrize('func, arg', [ + [guessers.guess_masses, ['C']], + [guessers.validate_atom_types, ['C']], + [guessers.guess_types, ['CA']], + [guessers.guess_atom_type, 'CA'], + [guessers.guess_atom_element, 'CA'], + [guessers.get_atom_mass, 'C'], + [guessers.guess_atom_mass, 'CA'], + [guessers.guess_atom_charge, 'CA'], + ]) + def test_mass_type_elements_deprecations(self, func, arg): + with pytest.warns(DeprecationWarning, match=self.wmsg): + func(arg) + + def test_bonds_deprecations(self): + u = mda.Universe(datafiles.two_water_gro) + + with pytest.warns(DeprecationWarning, match=self.wmsg): + guessers.guess_bonds(u.atoms, u.atoms.positions) + + def test_angles_dihedral_deprecations(self): + u = make_starshape() + ag = u.atoms[:5] + + with pytest.warns(DeprecationWarning, match=self.wmsg): + angles = guessers.guess_angles(ag.bonds) + + # add angles back to the Universe + u.add_TopologyAttr(Angles(angles)) + + with pytest.warns(DeprecationWarning, match=self.wmsg): + guessers.guess_dihedrals(ag.angles) + + with pytest.warns(DeprecationWarning, match=self.wmsg): + guessers.guess_improper_dihedrals(ag.angles) + + @requires_rdkit + def test_rdkit_guessers_deprecations(self): + mol = Chem.MolFromSmiles('c1ccccc1') + mol = Chem.AddHs(mol) + u = mda.Universe(mol) + + with pytest.warns(DeprecationWarning, match=self.wmsg): + guessers.guess_aromaticities(u.atoms) + + with pytest.warns(DeprecationWarning, match=self.wmsg): + guessers.guess_gasteiger_charges(u.atoms)