Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change error to warning on Universe creation #4754

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package/CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ The rules for this file:
* 2.8.0

Fixes
* Changes error to warning on Universe creation if guessing fails
due to missing information (Issue #4750, PR #4754)
* Adds guessed attributes documentation back to each parser page
and updates overall guesser docs (Issue #4696)
* Fix Bohrium (Bh) atomic mass in tables.py (PR #3753)
Expand Down
29 changes: 25 additions & 4 deletions package/MDAnalysis/core/universe.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,8 @@ def __init__(self, topology=None, *coordinates, all_coordinates=False,
force_guess = list(force_guess) + ['bonds', 'angles', 'dihedrals']

self.guess_TopologyAttrs(
context, to_guess, force_guess, vdwradii=vdwradii, **kwargs)
orbeckst marked this conversation as resolved.
Show resolved Hide resolved
context, to_guess, force_guess, error_if_missing=False
)


def copy(self):
Expand Down Expand Up @@ -1498,7 +1499,9 @@ def from_smiles(cls, smiles, sanitize=True, addHs=True,
return cls(mol, **kwargs)

def guess_TopologyAttrs(
self, context=None, to_guess=None, force_guess=None, **kwargs):
self, context=None, to_guess=None, force_guess=None,
error_if_missing=True, **kwargs
):
"""
Guess and add attributes through a specific context-aware guesser.

Expand All @@ -1523,6 +1526,13 @@ def guess_TopologyAttrs(
TopologyAttr does not already exist in the Universe, this has no
effect. If the TopologyAttr does already exist, all values will
be overwritten by guessed values.
error_if_missing: bool
orbeckst marked this conversation as resolved.
Show resolved Hide resolved
If `True`, raise an error if the guesser cannot guess the attribute
due to missing TopologyAttrs used as the inputs for guessing.
If `False`, a warning will be raised instead.
Errors will always be raised if an attribute is in the
``force_guess`` list, even if this parameter is set to False.

**kwargs: extra arguments to be passed to the guesser class

Examples
Expand All @@ -1537,7 +1547,11 @@ def guess_TopologyAttrs(
if not context:
context = self._context

guesser = get_guesser(context, self.universe, **kwargs)
# update iteratively to avoid multiple kwargs clashing
guesser_kwargs = {}
guesser_kwargs.update(self._kwargs)
guesser_kwargs.update(kwargs)
guesser = get_guesser(context, self.universe, **guesser_kwargs)
self._context = guesser

if to_guess is None:
Expand Down Expand Up @@ -1577,7 +1591,14 @@ def guess_TopologyAttrs(
for attr in total_guess:
if guesser.is_guessable(attr):
fg = attr in force_guess
values = guesser.guess_attr(attr, fg)
try:
values = guesser.guess_attr(attr, fg)
except ValueError as e:
if error_if_missing or fg:
raise e
else:
warnings.warn(str(e))
continue

if values is not None:
if attr in objects:
Expand Down
2 changes: 1 addition & 1 deletion package/MDAnalysis/guesser/default_guesser.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ def guess_types(self, atom_types=None, indices_to_guess=None):
atom_types = self._universe.atoms.names
except AttributeError:
raise ValueError(
"there is no reference attributes in this universe"
"there is no reference attributes in this universe "
"to guess types from")

if indices_to_guess is not None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ Default behavior

By default, MDAnalysis will guess the "mass" and "type" (atom type) attributes for all particles in the Universe
using the :class:`~MDAnalysis.guesser.default_guesser.DefaultGuesser` at the time of Universe creation,
if they are not read from the input file.
if they are not read from the input file. If the required information is not present in the input file,
a warning will be raised.
Please see the :class:`~MDAnalysis.guesser.default_guesser.DefaultGuesser` for more information.


Expand Down
19 changes: 18 additions & 1 deletion testsuite/MDAnalysisTests/guesser/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from numpy.testing import assert_allclose, assert_equal


class TesttBaseGuesser():
class TestBaseGuesser():

def test_get_guesser(self):
class TestGuesser1(GuesserBase):
Expand Down Expand Up @@ -100,3 +100,20 @@ def test_partial_guess_attr_with_unknown_no_value_label(self):
top = Topology(4, 1, 1, attrs=[names, types, ])
u = mda.Universe(top, to_guess=['types'])
assert_equal(u.atoms.types, ['', '', '', ''])


@pytest.mark.parametrize(
"universe_input",
[datafiles.DCD, datafiles.XTC, np.random.rand(3, 3), datafiles.PDB]
)
def test_universe_creation_from_coordinates(universe_input):
mda.Universe(universe_input)


def test_universe_creation_from_specific_array():
a = np.array([
[0., 0., 150.], [0., 0., 150.], [200., 0., 150.],
[0., 0., 150.], [100., 100., 150.], [200., 100., 150.],
[0., 200., 150.], [100., 200., 150.], [200., 200., 150.]
])
mda.Universe(a, n_atoms=9)
21 changes: 18 additions & 3 deletions testsuite/MDAnalysisTests/guesser/test_default_guesser.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,11 @@ def test_partial_guess_elements(self, default_guesser):

def test_guess_elements_from_no_data(self):
top = Topology(5)
msg = "there is no reference attributes in this universe"
"to guess types from"
with pytest.raises(ValueError, match=(msg)):
msg = (
"there is no reference attributes in this "
"universe to guess types from"
)
with pytest.warns(UserWarning, match=msg):
mda.Universe(top, to_guess=['types'])

@pytest.mark.parametrize('name, element', (
Expand Down Expand Up @@ -236,6 +238,19 @@ def test_guess_bonds_water():
(3, 5)))


@pytest.mark.parametrize(
"fudge_factor, n_bonds",
[(0, 0), (0.55, 4), (200, 6)]
)
def test_guess_bonds_water_fudge_factor_passed(fudge_factor, n_bonds):
u = mda.Universe(
datafiles.two_water_gro,
fudge_factor=fudge_factor,
to_guess=("types", "bonds")
)
assert len(u.atoms.bonds) == n_bonds


def test_guess_bonds_adk():
u = mda.Universe(datafiles.PSF, datafiles.DCD)
u.guess_TopologyAttrs(force_guess=['types'])
Expand Down
Loading