Skip to content

Commit 7b87dc3

Browse files
Removed instant selectors (Fixes Issue #1377) (#2535)
* Removed instant selectors (Fixes Issue #1377)
1 parent ae4b516 commit 7b87dc3

File tree

14 files changed

+27
-627
lines changed

14 files changed

+27
-627
lines changed

package/CHANGELOG

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ Enhancements
8686
* Improve the distance search in water bridge analysis with capped_distance (PR #2480)
8787

8888
Changes
89+
* Removed instant selectors on Universe and Group objects (e.g. AtomGroup.C,
90+
Segment.r1, Universe.s4AKE). Use select_atoms instead (Issue #1377)
8991
* Calling Universe() now raises a TypeError advising you to use Universe.empty.
9092
Universe.empty() now no longer has n_atoms=0 as default. (Issue #2527)
9193
* deprecated `start`, `stop`, and `step` keywords have been removed from `__init__`

package/MDAnalysis/core/groups.py

Lines changed: 13 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -2203,55 +2203,19 @@ class AtomGroup(GroupBase):
22032203
:class:`AtomGroup` instances are always bound to a
22042204
:class:`MDAnalysis.core.universe.Universe`. They cannot exist in isolation.
22052205
2206-
.. rubric:: Deprecated functionality
2207-
2208-
*Instant selectors* will be removed in the 1.0 release. See issue `#1377
2209-
<https://github.com/MDAnalysis/mdanalysis/issues/1377>`_ for more details.
2210-
2211-
:class:`Atoms<Atom>` can also be accessed in a Pythonic fashion by using the
2212-
:class:`Atom` name as an attribute. For instance, ::
2213-
2214-
ag.CA
2215-
2216-
will provide an :class:`AtomGroup` of all CA :class:`Atoms<Atom>` in the
2217-
group. These *instant selector* attributes are auto-generated for
2218-
each atom name encountered in the group.
2219-
2220-
Notes
2221-
-----
2222-
The name-attribute instant selector access to :class:`Atoms<Atom>` is mainly
2223-
meant for quick interactive work. Thus it either returns a single
2224-
:class:`Atom` if there is only one matching :class:`Atom`, *or* a
2225-
new :class:`AtomGroup` for multiple matches. This makes it difficult to use
2226-
the feature consistently in scripts.
2227-
22282206
22292207
See Also
22302208
--------
22312209
:class:`MDAnalysis.core.universe.Universe`
22322210
2233-
22342211
.. deprecated:: 0.16.2
22352212
*Instant selectors* of :class:`AtomGroup` will be removed in the 1.0
2236-
release. See :ref:`Instant selectors <instance-selectors>` for details
2237-
and alternatives.
2213+
release.
2214+
.. versionchanged:: 1.0.0
2215+
Removed instant selectors, use select_atoms('name ...') to select
2216+
atoms by name.
22382217
"""
2239-
def __getitem__(self, item):
2240-
# DEPRECATED in 0.16.2
2241-
# REMOVE in 1.0
2242-
#
2243-
# u.atoms['HT1'] access, otherwise default
2244-
if isinstance(item, string_types):
2245-
try:
2246-
return self._get_named_atom(item)
2247-
except (AttributeError, selection.SelectionError):
2248-
pass
2249-
return super(AtomGroup, self).__getitem__(item)
2250-
22512218
def __getattr__(self, attr):
2252-
# DEPRECATED in 0.16.2
2253-
# REMOVE in 1.0
2254-
#
22552219
# is this a known attribute failure?
22562220
# TODO: Generalise this to cover many attributes
22572221
if attr in ('fragments', 'fragindices', 'n_fragments', 'unwrap'):
@@ -2260,12 +2224,6 @@ def __getattr__(self, attr):
22602224
# raise NDE(_ATTR_ERRORS[attr])
22612225
raise NoDataError("AtomGroup.{} not available; this requires Bonds"
22622226
"".format(attr))
2263-
elif hasattr(self.universe._topology, 'names'):
2264-
# Ugly hack to make multiple __getattr__s work
2265-
try:
2266-
return self._get_named_atom(attr)
2267-
except selection.SelectionError:
2268-
pass
22692227
raise AttributeError("{cls} has no attribute {attr}".format(
22702228
cls=self.__class__.__name__, attr=attr))
22712229

@@ -3256,8 +3214,8 @@ class ResidueGroup(GroupBase):
32563214
32573215
.. deprecated:: 0.16.2
32583216
*Instant selectors* of Segments will be removed in the 1.0 release.
3259-
See :ref:`Instant selectors <instance-selectors>` for details and
3260-
alternatives.
3217+
.. versionchanged:: 1.0.0
3218+
Removed instant selectors, use select_atoms instead
32613219
"""
32623220

32633221
@property
@@ -3419,8 +3377,8 @@ class SegmentGroup(GroupBase):
34193377
34203378
.. deprecated:: 0.16.2
34213379
*Instant selectors* of Segments will be removed in the 1.0 release.
3422-
See :ref:`Instant selectors <instance-selectors>` for details and
3423-
alternatives.
3380+
.. versionchanged:: 1.0.0
3381+
Removed instant selectors, use select_atoms instead
34243382
"""
34253383

34263384
@property
@@ -3841,8 +3799,11 @@ class Segment(ComponentBase):
38413799
38423800
.. deprecated:: 0.16.2
38433801
*Instant selectors* of :class:`Segments<Segment>` will be removed in the
3844-
1.0 release. See :ref:`Instant selectors <instance-selectors>` for
3845-
details and alternatives.
3802+
1.0 release.
3803+
.. versionchanged:: 1.0.0
3804+
Removed instant selectors, use either segment.residues[...] to select
3805+
residue by number, or segment.residues[segment.residue.resnames = ...]
3806+
to select by resname.
38463807
"""
38473808
def __repr__(self):
38483809
me = '<Segment'
@@ -3870,26 +3831,6 @@ def residues(self):
38703831
rg._cache['unique'] = rg
38713832
return rg
38723833

3873-
def __getattr__(self, attr):
3874-
# DEPRECATED in 0.16.2
3875-
# REMOVE in 1.0
3876-
#
3877-
# Segment.r1 access
3878-
if attr.startswith('r') and attr[1:].isdigit():
3879-
resnum = int(attr[1:])
3880-
rg = self.residues[resnum - 1] # convert to 0 based
3881-
warnings.warn("Instant selectors Segment.r<N> will be removed in "
3882-
"1.0. Use Segment.residues[N-1] instead.",
3883-
DeprecationWarning)
3884-
return rg
3885-
# Resname accesss
3886-
if hasattr(self.residues, 'resnames'):
3887-
try:
3888-
return self.residues._get_named_residue(attr)
3889-
except selection.SelectionError:
3890-
pass
3891-
raise AttributeError("{cls} has no attribute {attr}"
3892-
"".format(cls=self.__class__.__name__, attr=attr))
38933834

38943835
# Accessing these attrs doesn't trigger an update. The class and instance
38953836
# methods of UpdatingAtomGroup that are used during __init__ must all be

package/MDAnalysis/core/topologyattrs.py

Lines changed: 0 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
import numpy as np
4646
import warnings
4747

48-
from numpy.lib.utils import deprecate
4948

5049
from ..lib.util import (cached, convert_aa_code, iterable, warn_if_not_unique,
5150
unique_int_1d)
@@ -481,63 +480,6 @@ class Atomnames(AtomAttr):
481480
def _gen_initial_values(na, nr, ns):
482481
return np.array(['' for _ in range(na)], dtype=object)
483482

484-
def getattr__(atomgroup, name):
485-
try:
486-
return atomgroup._get_named_atom(name)
487-
except selection.SelectionError:
488-
six.raise_from(
489-
AttributeError("'{0}' object has no attribute '{1}'".format(
490-
atomgroup.__class__.__name__, name)),
491-
None)
492-
493-
def _get_named_atom(group, name):
494-
"""Get all atoms with name *name* in the current AtomGroup.
495-
496-
For more than one atom it returns a list of :class:`Atom`
497-
instance. A single :class:`Atom` is returned just as such. If
498-
no atoms are found, a :exc:`SelectionError` is raised.
499-
500-
.. versionadded:: 0.9.2
501-
502-
.. deprecated:: 0.16.2
503-
*Instant selectors* will be removed in the 1.0 release.
504-
Use ``AtomGroup.select_atoms('name <name>')`` instead.
505-
See issue `#1377
506-
<https://github.com/MDAnalysis/mdanalysis/issues/1377>`_ for
507-
more details.
508-
509-
"""
510-
# There can be more than one atom with the same name
511-
atomlist = group.atoms.unique[group.atoms.unique.names == name]
512-
if len(atomlist) == 0:
513-
raise selection.SelectionError(
514-
"No atoms with name '{0}'".format(name))
515-
elif len(atomlist) == 1:
516-
# XXX: keep this, makes more sense for names
517-
atomlist = atomlist[0]
518-
warnings.warn("Instant selector AtomGroup['<name>'] or AtomGroup.<name> "
519-
"is deprecated and will be removed in 1.0. "
520-
"Use AtomGroup.select_atoms('name <name>') instead.",
521-
DeprecationWarning)
522-
return atomlist
523-
524-
# AtomGroup already has a getattr
525-
# transplants[AtomGroup].append(
526-
# ('__getattr__', getattr__))
527-
528-
transplants[Residue].append(
529-
('__getattr__', getattr__))
530-
531-
# this is also getitem for a residue
532-
transplants[Residue].append(
533-
('__getitem__', getattr__))
534-
535-
transplants[AtomGroup].append(
536-
('_get_named_atom', _get_named_atom))
537-
538-
transplants[Residue].append(
539-
('_get_named_atom', _get_named_atom))
540-
541483
def phi_selection(residue):
542484
"""AtomGroup corresponding to the phi protein backbone dihedral
543485
C'-N-CA-C.
@@ -1383,63 +1325,6 @@ class Resnames(ResidueAttr):
13831325
def _gen_initial_values(na, nr, ns):
13841326
return np.array(['' for _ in range(nr)], dtype=object)
13851327

1386-
def getattr__(residuegroup, resname):
1387-
try:
1388-
return residuegroup._get_named_residue(resname)
1389-
except selection.SelectionError:
1390-
six.raise_from(
1391-
AttributeError("'{0}' object has no attribute '{1}'".format(
1392-
residuegroup.__class__.__name__, resname)),
1393-
None)
1394-
1395-
transplants[ResidueGroup].append(('__getattr__', getattr__))
1396-
# This transplant is hardcoded for now to allow for multiple getattr things
1397-
#transplants[Segment].append(('__getattr__', getattr__))
1398-
1399-
def _get_named_residue(group, resname):
1400-
"""Get all residues with name *resname* in the current ResidueGroup
1401-
or Segment.
1402-
1403-
For more than one residue it returns a
1404-
:class:`MDAnalysis.core.groups.ResidueGroup` instance. A single
1405-
:class:`MDAnalysis.core.group.Residue` is returned for a single match.
1406-
If no residues are found, a :exc:`SelectionError` is raised.
1407-
1408-
.. versionadded:: 0.9.2
1409-
1410-
.. deprecated:: 0.16.2
1411-
*Instant selectors* will be removed in the 1.0 release.
1412-
Use ``ResidueGroup[ResidueGroup.resnames == '<name>']``
1413-
or ``Segment.residues[Segment.residues == '<name>']``
1414-
instead.
1415-
See issue `#1377
1416-
<https://github.com/MDAnalysis/mdanalysis/issues/1377>`_ for
1417-
more details.
1418-
1419-
"""
1420-
# There can be more than one residue with the same name
1421-
residues = group.residues.unique[
1422-
group.residues.unique.resnames == resname]
1423-
if len(residues) == 0:
1424-
raise selection.SelectionError(
1425-
"No residues with resname '{0}'".format(resname))
1426-
warnings.warn("Instant selector ResidueGroup.<name> "
1427-
"or Segment.<name> "
1428-
"is deprecated and will be removed in 1.0. "
1429-
"Use ResidueGroup[ResidueGroup.resnames == '<name>'] "
1430-
"or Segment.residues[Segment.residues == '<name>'] "
1431-
"instead.",
1432-
DeprecationWarning)
1433-
if len(residues) == 1:
1434-
# XXX: keep this, makes more sense for names
1435-
return residues[0]
1436-
else:
1437-
# XXX: but inconsistent (see residues and Issue 47)
1438-
return residues
1439-
1440-
transplants[ResidueGroup].append(
1441-
('_get_named_residue', _get_named_residue))
1442-
14431328
def sequence(self, **kwargs):
14441329
"""Returns the amino acid sequence.
14451330
@@ -1627,60 +1512,6 @@ class Segids(SegmentAttr):
16271512
def _gen_initial_values(na, nr, ns):
16281513
return np.array(['' for _ in range(ns)], dtype=object)
16291514

1630-
def getattr__(segmentgroup, segid):
1631-
try:
1632-
return segmentgroup._get_named_segment(segid)
1633-
except selection.SelectionError:
1634-
six.raise_from(
1635-
AttributeError("'{0}' object has no attribute '{1}'".format(
1636-
segmentgroup.__class__.__name__, segid)),
1637-
None)
1638-
1639-
transplants[SegmentGroup].append(
1640-
('__getattr__', getattr__))
1641-
1642-
def _get_named_segment(group, segid):
1643-
"""Get all segments with name *segid* in the current SegmentGroup.
1644-
1645-
For more than one residue it returns a
1646-
:class:`MDAnalysis.core.groups.SegmentGroup` instance. A single
1647-
:class:`MDAnalysis.core.group.Segment` is returned for a single match.
1648-
If no residues are found, a :exc:`SelectionError` is raised.
1649-
1650-
.. versionadded:: 0.9.2
1651-
1652-
.. deprecated:: 0.16.2
1653-
*Instant selectors* will be removed in the 1.0 release.
1654-
Use ``SegmentGroup[SegmentGroup.segids == '<name>']`` instead.
1655-
See issue `#1377
1656-
<https://github.com/MDAnalysis/mdanalysis/issues/1377>`_ for
1657-
more details.
1658-
1659-
"""
1660-
# Undo adding 's' if segid started with digit
1661-
if segid.startswith('s') and len(segid) >= 2 and segid[1].isdigit():
1662-
segid = segid[1:]
1663-
1664-
# There can be more than one segment with the same name
1665-
segments = group.segments.unique[
1666-
group.segments.unique.segids == segid]
1667-
if len(segments) == 0:
1668-
raise selection.SelectionError(
1669-
"No segments with segid '{0}'".format(segid))
1670-
warnings.warn("Instant selector SegmentGroup.<name> "
1671-
"is deprecated and will be removed in 1.0. "
1672-
"Use SegmentGroup[SegmentGroup.segids == '<name>'] "
1673-
"instead.",
1674-
DeprecationWarning)
1675-
if len(segments) == 1:
1676-
# XXX: keep this, makes more sense for names
1677-
return segments[0]
1678-
else:
1679-
# XXX: but inconsistent (see residues and Issue 47)
1680-
return segments
1681-
1682-
transplants[SegmentGroup].append(
1683-
('_get_named_segment', _get_named_segment))
16841515

16851516
def _check_connection_values(func):
16861517
"""

0 commit comments

Comments
 (0)