Skip to content

Commit

Permalink
Add AtomGroup stub, fixes MDAnalysis#1067 (MDAnalysis#1070)
Browse files Browse the repository at this point in the history
* Add AtomGroup stub

Any class used from this module will raise a warning. The classes work
without needed to be specially imported.

* fix Universe Warning Message

* update changelog

* add test for deprecation warning

* Added compatibility for old AtomGroup init methods

* Added tests for deprecated Group init methods
  • Loading branch information
kain88-de authored and richardjgowers committed Nov 13, 2016
1 parent 9d5d7bf commit 2b85baa
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 2 deletions.
1 change: 1 addition & 0 deletions package/CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ Changes
* atoms.translate/rotateby don't accept AtomGroup tuples as parameters anymore (Issue #1025)
* atoms.rotate by default now uses the centroid as center of rotation like rotateby (Issue #1022)
* XTCFile and TRRFile only raise IOError now on error.
* Deprecate usage of MDAnalaysis.core.AtomGroup

Deprecations (Issue #599)
* Use of rms_fit_trj deprecated in favor of AlignTraj class (Issue #845)
Expand Down
44 changes: 44 additions & 0 deletions package/MDAnalysis/core/AtomGroup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import warnings

from .groups import (Atom, AtomGroup, Residue, ResidueGroup, Segment,
SegmentGroup)
from . import universe


def deprecate_class(class_new, message):
"""utility to deprecate a class"""

class new_class(class_new):
def __init__(self, *args, **kwargs):
super(new_class, self).__init__(*args, **kwargs)
warnings.warn(message, DeprecationWarning)

return new_class


Universe = deprecate_class(
universe.Universe,
"MDAnalysis.core.AtomGroup.Universe has been removed."
"Please use MDAnalaysis.Universe."
"This stub will be removed in 1.0")

_group_message = ("MDAnalysis.core.AtomGroup.{0} has been removed."
"Please use MDAnalaysis.groups.{0}"
"This stub will be removed in 1.0")

Atom = deprecate_class(Atom, message=_group_message.format('Atom'))
AtomGroup = deprecate_class(
AtomGroup, message=_group_message.format('AtomGroup'))

Residue = deprecate_class(Residue, message=_group_message.format('Residue'))
ResidueGroup = deprecate_class(
ResidueGroup, message=_group_message.format('ResidueGroup'))

Segment = deprecate_class(Segment, message=_group_message.format('Segment'))
SegmentGroup = deprecate_class(
SegmentGroup, message=_group_message.format('SegmentGroup'))

__all__ = [
'Universe', 'Atom', 'AtomGroup', 'Residue', 'ResidueGroup', 'Segment',
'SegmentGroup'
]
1 change: 1 addition & 0 deletions package/MDAnalysis/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,3 +429,4 @@ class flagsDocs(object):
from . import groups
from . import selection
from . import Timeseries
from . import AtomGroup
22 changes: 20 additions & 2 deletions package/MDAnalysis/core/groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import functools
import itertools
import os
import warnings

import MDAnalysis
from ..lib import util
Expand Down Expand Up @@ -161,7 +162,12 @@ class _MutableBase(object):
"""
# This signature must be kept in sync with the __init__ signature of
# GroupBase and ComponentBase.
def __new__(cls, ix, u):
def __new__(cls, *args):
try:
ix, u = args
except ValueError:
# deprecated AtomGroup init method..
u = args[0][0].universe
try:
return object.__new__(u._classes[cls])
except KeyError:
Expand Down Expand Up @@ -194,7 +200,19 @@ class GroupBase(_MutableBase):
"""Base class from which a Universe's Group class is built.
"""
def __init__(self, ix, u):
def __init__(self, *args):
if len(args) == 1:
warnings.warn("Using deprecated init method for Group. "
"In the future use `Group(indices, universe)`. "
"This init method will be removed in version 1.0.",
DeprecationWarning)
# list of atoms/res/segs, old init method
ix = [at.ix for at in args[0]]
u = args[0][0].universe
else:
# current/new init method
ix, u = args

# indices for the objects I hold
self._ix = np.asarray(ix, dtype=np.int64)
self._u = u
Expand Down
71 changes: 71 additions & 0 deletions testsuite/MDAnalysisTests/core/test_atomgroup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from glob import glob
from os import path
import numpy as np
import warnings

from numpy.testing import (
assert_,
Expand All @@ -37,8 +38,78 @@
)

from MDAnalysisTests.datafiles import (PSF, DCD)
from MDAnalysisTests.core.groupbase import make_Universe
from MDAnalysisTests import tempdir

# I want to catch all warnings in the tests. If this is not set at the start it
# could cause test that check for warnings to fail.
warnings.simplefilter('always')

class TestDeprecationWarnings(object):
@staticmethod
def test_AtomGroupUniverse_usage_warning():
with warnings.catch_warnings(record=True) as warn:
warnings.simplefilter('always')
mda.core.AtomGroup.Universe(PSF, DCD)
assert_equal(len(warn), 1)

@staticmethod
def test_old_AtomGroup_init_warns():
u = make_Universe(('names',))
at_list = list(u.atoms[:10])
with warnings.catch_warnings(record=True) as warn:
warnings.simplefilter('always')
ag = mda.core.groups.AtomGroup(at_list)
assert_equal(len(warn), 1)

@staticmethod
def test_old_AtomGroup_init_works():
u = make_Universe(('names',))
at_list = list(u.atoms[:10])
ag = mda.core.groups.AtomGroup(at_list)

assert_(isinstance(ag, mda.core.groups.AtomGroup))
assert_(len(ag) == 10)
assert_equal(ag.names, u.atoms[:10].names)

@staticmethod
def test_old_ResidueGroup_init_warns():
u = make_Universe(('resnames',))
res_list = list(u.residues[:10])
with warnings.catch_warnings(record=True) as warn:
warnings.simplefilter('always')
rg = mda.core.groups.ResidueGroup(res_list)
assert_equal(len(warn), 1)

@staticmethod
def test_old_ResidueGroup_init_works():
u = make_Universe(('resnames',))
res_list = list(u.residues[:10])
rg = mda.core.groups.ResidueGroup(res_list)

assert_(isinstance(rg, mda.core.groups.ResidueGroup))
assert_(len(rg) == 10)
assert_equal(rg.resnames, u.residues[:10].resnames)

@staticmethod
def test_old_SegmentGroup_init_warns():
u = make_Universe(('segids',))
seg_list = list(u.segments[:3])
with warnings.catch_warnings(record=True) as warn:
warnings.simplefilter('always')
sg = mda.core.groups.SegmentGroup(seg_list)
assert_equal(len(warn), 1)

@staticmethod
def test_old_SegmentGroup_init_works():
u = make_Universe(('segids',))
seg_list = list(u.segments[:3])
sg = mda.core.groups.SegmentGroup(seg_list)

assert_(isinstance(sg, mda.core.groups.SegmentGroup))
assert_(len(sg) == 3)
assert_equal(sg.segids, u.segments[:3].segids)


class TestAtomGroupToTopology(object):
"""Test the conversion of AtomGroup to TopologyObjects"""
Expand Down

0 comments on commit 2b85baa

Please sign in to comment.