Skip to content

Commit

Permalink
Merge pull request #317 from MDAnalysis/feature-unified_iter
Browse files Browse the repository at this point in the history
Cleaned up Reader classes
  • Loading branch information
orbeckst committed Jun 16, 2015
2 parents 67b3a26 + 993ee19 commit fbceab4
Show file tree
Hide file tree
Showing 11 changed files with 36 additions and 113 deletions.
2 changes: 2 additions & 0 deletions package/CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ The rules for this file:
* Removed FormatError, now replaced by ValueError
* distances.contact_matrix(): changed keyword 'suppress_progmet' to
'quiet'
* base.Reader now defines __iter__
* __iter__ removed from many Readers (now use base.Reader implementation)

Fixes
* analysis.hbonds.HydrogenBondAnalysis performs a sanity check for
Expand Down
13 changes: 1 addition & 12 deletions package/MDAnalysis/coordinates/DCD.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,20 +462,9 @@ def _dcd_header(self):
'charmm', 'first', 'with_unitcell']
return dict(zip(desc, struct.unpack("LLiiiiidiPPiiii", self._dcd_C_str)))

def __iter__(self):
# Reset the trajectory file, read from the start
# usage is "from ts in dcd:" where dcd does not have indexes
def _reopen(self):
self._reset_dcd_read()

def iterDCD():
for i in xrange(0, self.numframes, self.skip): # FIXME: skip is not working!!!
try:
yield self._read_next_timestep()
except IOError:
raise StopIteration

return iterDCD()

def _read_next_timestep(self, ts=None):
if ts is None:
ts = self.ts
Expand Down
9 changes: 0 additions & 9 deletions package/MDAnalysis/coordinates/DLPoly.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,15 +260,6 @@ def _read_numframes(self):

return numframes

def __iter__(self):
self._reopen()
while True:
try:
yield self._read_next_timestep()
except IOError:
self.rewind()
raise StopIteration

def rewind(self):
self._reopen()
self.next()
Expand Down
10 changes: 0 additions & 10 deletions package/MDAnalysis/coordinates/GMS.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,16 +165,6 @@ def _read_out_numframes(self, filename):
self.close()
return int(counter)

def __iter__(self):
self.ts.frame = 0 # start at 0 so that the first frame becomes 1
self._reopen()
while True:
try:
yield self._read_next_timestep()
except EOFError:
self.close()
raise StopIteration

def _read_next_timestep(self, ts=None):
# check that the timestep object exists
if ts is None:
Expand Down
7 changes: 0 additions & 7 deletions package/MDAnalysis/coordinates/MOL2.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,6 @@ def __init__(self, filename, convert_units=None, **kwargs):
self.delta = 0
self.skip_timestep = 1

def __iter__(self):
for i in xrange(0, self.numframes):
try:
yield self._read_frame(i)
except IOError:
raise StopIteration

def parse_block(self, block):
sections = {}
cursor = None
Expand Down
15 changes: 7 additions & 8 deletions package/MDAnalysis/coordinates/PDB.py
Original file line number Diff line number Diff line change
Expand Up @@ -551,12 +551,13 @@ def Writer(self, filename, **kwargs):
kwargs.setdefault('multiframe', self.numframes > 1)
return PrimitivePDBWriter(filename, **kwargs)

def __iter__(self):
for i in xrange(0, self.numframes):
try:
yield self._read_frame(i)
except IOError:
raise StopIteration
def rewind(self):
self._read_frame(0)

def _reopen(self):
# Pretend the current TS is 0 (in 1 based) so "next" is the
# first frame
self.ts.frame = 0

def _read_next_timestep(self, ts=None):
if ts is None:
Expand All @@ -571,8 +572,6 @@ def _read_next_timestep(self, ts=None):
return self._read_frame(frame)

def _read_frame(self, frame):
if numpy.dtype(type(frame)) != numpy.dtype(int):
raise TypeError("frame must be a integer")
# Assume _read_frame is passed a 0-based frame number. Convert this to
# 1-based.
frame += 1
Expand Down
30 changes: 3 additions & 27 deletions package/MDAnalysis/coordinates/TRJ.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,6 @@
.. autoclass:: NCDFReader
:members:
.. automethod:: __getitem__
.. automethod:: __iter__
.. autoclass:: NCDFWriter
:members:
Expand Down Expand Up @@ -369,15 +366,6 @@ def rewind(self):
self._reopen()
self.next()

def __iter__(self):
self._reopen()
while True:
try:
yield self._read_next_timestep()
except EOFError:
self.rewind()
raise StopIteration


class NCDFReader(base.Reader):
"""Reader for `AMBER NETCDF format`_ (version 1.0).
Expand Down Expand Up @@ -536,6 +524,9 @@ def _read_frame(self, frame):
self._current_frame = frame
return ts

def _reopen(self):
self._current_frame = -1

def _read_next_timestep(self, ts=None):
if ts is None:
ts = self.ts
Expand All @@ -544,21 +535,6 @@ def _read_next_timestep(self, ts=None):
except IndexError:
raise IOError

def _sliced_iter(self, start, stop, step):
def iterNETCDF(start=start, stop=stop, step=step):
for i in xrange(start, stop, step):
yield self._read_frame(i)

return iterNETCDF()

def __iter__(self):
"""Iterate over the whole trajectory"""
for i in xrange(0, self.numframes):
try:
yield self._read_frame(i)
except IndexError:
raise StopIteration

def close(self):
"""Close trajectory; any further access will raise an :exc:`IOError`"""
if not self.trjfile is None:
Expand Down
9 changes: 0 additions & 9 deletions package/MDAnalysis/coordinates/TRZ.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,15 +341,6 @@ def skip_timestep(self):
self.rewind()
return self._skip_timestep

def __iter__(self):
self._reopen()
while True:
try:
yield self._read_next_timestep()
except IOError:
self.rewind()
raise StopIteration

# can use base.Reader __getitem__ implementation
def _read_frame(self, frame):
"""Move to *frame* and fill timestep with data."""
Expand Down
10 changes: 0 additions & 10 deletions package/MDAnalysis/coordinates/XYZ.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,16 +315,6 @@ def _read_xyz_numframes(self, filename):
numframes = int(counter / linesPerFrame)
return numframes

def __iter__(self):
self.ts.frame = 0 # start at 0 so that the first frame becomes 1
self._reopen()
while True:
try:
yield self._read_next_timestep()
except EOFError:
self.close()
raise StopIteration

def _read_next_timestep(self, ts=None):
# check that the timestep object exists
if ts is None:
Expand Down
26 changes: 23 additions & 3 deletions package/MDAnalysis/coordinates/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,8 @@ def next(self):

def rewind(self):
"""Position at beginning of trajectory"""
self[0]
self._reopen()
self.next()

@property
def dt(self):
Expand Down Expand Up @@ -689,7 +690,20 @@ def __del__(self):
self.close()

def __iter__(self):
raise NotImplementedError("BUG: Override __iter__() in the trajectory reader (%s)!" % type(self))
self._reopen()
while True:
try:
yield self._read_next_timestep()
except (EOFError, IOError):
self.rewind()
raise StopIteration

def _reopen(self):
"""Should position Reader to just before first frame
Calling next after this should return the first frame
"""
pass

def __getitem__(self, frame):
"""Return the Timestep corresponding to *frame*.
Expand Down Expand Up @@ -742,7 +756,7 @@ def _sliced_iter(self, start, stop, step):
def _iter(start=start, stop=stop, step=step):
try:
for i in xrange(start, stop, step):
yield self[i]
yield self._read_frame(i)
except TypeError: # if _read_frame not implemented
raise TypeError("{0} does not support slicing."
"".format(self.__class__.__name__))
Expand Down Expand Up @@ -1172,6 +1186,12 @@ def _read_first_frame(self):
# Override this in subclasses to create and fill a Timestep
pass

def rewind(self):
pass

def _reopen(self):
pass

def next(self):
raise IOError(self._err.format(self.__class__.__name__))

Expand Down
18 changes: 0 additions & 18 deletions package/MDAnalysis/coordinates/xdrfile/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -718,11 +718,6 @@ def __iter__(self):
else:
yield ts

def rewind(self):
"""Position at beginning of trajectory"""
self._reopen()
self.next() # read first frame

def _reopen(self):
self.close()
self.open_trajectory()
Expand All @@ -744,19 +739,6 @@ def _read_frame(self, frame):
# Renamed this once upon a time.
_goto_frame = _read_frame

def _sliced_iter(self, start, stop, step):
def _iter(start=start, stop=stop, step=step):
if step == 1:
rng = xrange(start + 1, stop, step)
yield self._read_frame(start)
for framenr in rng:
yield self._read_frame(framenr)
else:
rng = xrange(start, stop, step)
for framenr in rng:
yield self._read_frame(framenr)
return _iter()

def timeseries(self, asel, start=0, stop=-1, skip=1, format='afc'):
raise NotImplementedError("timeseries not available for Gromacs trajectories")

Expand Down

0 comments on commit fbceab4

Please sign in to comment.