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

Fix Merge for issue-363 branch #781

Merged
merged 4 commits into from
Apr 10, 2016
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
22 changes: 22 additions & 0 deletions package/MDAnalysis/core/groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,28 @@ def __add__(self, other):

return self.__class__(np.concatenate([self._ix, o_ix]), self._u)

def __radd__(self, other):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is so we can call sum on Groups right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. For some reason sum(a) is defined as start + a[0] + a[1] + ... where start is 0 by default. The user could either pass the optional second argument to sum to specify start as an empty atomgroup of the same universe, or we can override __radd__ so that 0 + a[0] = a[0]. Do you think this is a worthwhile feature?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I like it. I think previously I've used reduce(lambda x, y: x+y, ags) or something stupid, so using sum is much better

"""Using built-in sum requires supporting 0 + self. If other is
anything other 0, an exception will be raised.

Parameters
----------
other : int
Other should be 0, or else an exception will be raised.

Returns
-------
self
Group with elements of `self` reproduced

"""
if other == 0:
return self.__class__(self._ix, self._u)
else:
raise TypeError("unsupported operand type(s) for +:"+
" '{}' and '{}'".format(type(self).__name__,
type(other).__name__))

def __contains__(self, other):
if not other.level == self.level:
# maybe raise TypeError instead?
Expand Down
4 changes: 3 additions & 1 deletion package/MDAnalysis/core/topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class TransTable(object):
array must be <= `n_residues`, and the array must be length `n_atoms`;
giving None defaults to placing all atoms in residue 0
residue_segindex : 1-D array
segindex for each atom in the topology; the number of unique values in this
segindex for each residue in the topology; the number of unique values in this
array must be <= `n_segments`, and the array must be length `n_residues`;
giving None defaults to placing all residues in segment 0

Expand Down Expand Up @@ -321,6 +321,8 @@ def __init__(self, n_atoms=1, n_res=1, n_seg=1,
self.n_atoms = n_atoms
self.n_residues = n_res
self.n_segments = n_seg
if attrs is None:
attrs = []
self.tt = TransTable(n_atoms, n_res, n_seg,
atom_resindex=atom_resindex,
residue_segindex=residue_segindex)
Expand Down
14 changes: 14 additions & 0 deletions package/MDAnalysis/core/topologyattrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ class Atomids(AtomAttr):
"""
attrname = 'ids'
singular = 'id'
per_object = 'atom'


#TODO: update docs to property doc
Expand All @@ -273,6 +274,7 @@ class Atomnames(AtomAttr):
"""
attrname = 'names'
singular = 'name'
per_object = 'atom'
transplants = defaultdict(list)

def getattr__(atomgroup, name):
Expand Down Expand Up @@ -321,13 +323,15 @@ class Atomtypes(AtomAttr):
"""Type for each atom"""
attrname = 'types'
singular = 'type'
per_object = 'atom'


#TODO: update docs to property doc
class Radii(AtomAttr):
"""Radii for each atom"""
attrname = 'radii'
singular = 'radius'
per_object = 'atom'


class ChainIDs(AtomAttr):
Expand All @@ -339,24 +343,28 @@ class ChainIDs(AtomAttr):
"""
attrname = 'chainIDs'
singular = 'chainID'
per_object = 'atom'


class ICodes(AtomAttr):
"""Insertion code for Atoms"""
attrname = 'icodes'
singular = 'icode'
per_object = 'atom'


class Tempfactors(AtomAttr):
"""Tempfactor for atoms"""
attrname = 'tempfactors'
singular = 'tempfactor'
per_object = 'atom'


#TODO: need to add cacheing
class Masses(AtomAttr):
attrname = 'masses'
singular = 'mass'
per_object = 'atom'
target_levels = ['atom', 'residue', 'segment']
transplants = defaultdict(list)

Expand Down Expand Up @@ -641,6 +649,7 @@ def principal_axes(atomgroup, **kwargs):
class Charges(AtomAttr):
attrname = 'charges'
singular = 'charge'
per_object = 'atom'
target_levels = ['atom', 'residue', 'segment']
transplants = defaultdict(list)

Expand Down Expand Up @@ -679,19 +688,22 @@ class Bfactors(AtomAttr):
"""Crystallographic B-factors in A**2 for each atom"""
attrname = 'bfactors'
singular = 'bfactor'
per_object = 'atom'


#TODO: update docs to property doc
class Occupancies(AtomAttr):
attrname = 'occupancies'
singular = 'occupancy'
per_object = 'atom'


#TODO: update docs to property doc
class AltLocs(AtomAttr):
"""AltLocs for each atom"""
attrname = 'altLocs'
singular = 'altLoc'
per_object = 'atom'


## residue attributes
Expand All @@ -708,6 +720,7 @@ class ResidueAttr(TopologyAttr):
attrname = 'residueattrs'
singular = 'residueattr'
target_levels = ['residue']
per_object = 'residue'

def get_atoms(self, ag):
rix = self.top.tt.atoms2residues(ag._ix)
Expand Down Expand Up @@ -802,6 +815,7 @@ class SegmentAttr(TopologyAttr):
attrname = 'segmentattrs'
singular = 'segmentattr'
target_levels = ['segment']
per_object = 'segment'

def get_atoms(self, ag):
six = self.top.tt.atoms2segments(ag._ix)
Expand Down
4 changes: 4 additions & 0 deletions package/MDAnalysis/core/topologyobjects.py
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,10 @@ def atomgroup_intersection(self, ag, **kwargs):

.. versionadded:: 0.9.0
"""
# Issue #780 - if self is empty, return self to avoid invalid mask
if not self:
return self

# Strict requires all items in a row to be seen,
# otherwise any item in a row
func = np.all if kwargs.get('strict', False) else np.any
Expand Down
Loading