Skip to content

Commit

Permalink
Merge pull request MDAnalysis#3683 from hmacdope/CythonTimestep
Browse files Browse the repository at this point in the history
Cythonized Timestep [Core]
  • Loading branch information
richardjgowers authored Jun 13, 2022
2 parents d7e7276 + 2ca43d6 commit b302e40
Show file tree
Hide file tree
Showing 42 changed files with 1,196 additions and 961 deletions.
4 changes: 3 additions & 1 deletion package/CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ The rules for this file:
* release numbers follow "Semantic Versioning" http://semver.org

------------------------------------------------------------------------------
??/??/?? IAlibay, PicoCentauri, orbeckst
??/??/?? IAlibay, PicoCentauri, orbeckst, hmacdope

* 2.3.0

Expand All @@ -24,6 +24,8 @@ Enhancements
* Add `norm` parameter to InterRDF, InterRDF_s to normalize as rdf,
number density or do not normalize at all. (Issue #3687)
* Additional logger.info output when per-frame analysis starts (PR #3710)
* Timestep has been converted to a Cython Extension type
(CZI Performance track, PR #3683)

Changes

Expand Down
2 changes: 1 addition & 1 deletion package/MDAnalysis/analysis/distances.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def contact_matrix(coord, cutoff=15.0, returntype="numpy", box=None):
* ``"sparse"``: return as a :class:`scipy.sparse.lil_matrix`
box : array-like or ``None``, optional, default ``None``
Simulation cell dimensions in the form of
:attr:`MDAnalysis.trajectory.base.Timestep.dimensions` when
:attr:`MDAnalysis.trajectory.timestep.Timestep.dimensions` when
periodic boundary conditions should be taken into account for
the calculation of contacts.
Expand Down
2 changes: 1 addition & 1 deletion package/MDAnalysis/analysis/pca.py
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ def project_single_frame(self, components=None, group=None, anchor=None):
-------
function
The resulting function f(ts) takes as input a
:class:`~MDAnalysis.coordinates.base.Timestep` ts,
:class:`~MDAnalysis.coordinates.timestep.Timestep` ts,
and returns ts with the projected structure
.. warning::
Expand Down
2 changes: 1 addition & 1 deletion package/MDAnalysis/auxiliary/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@
'Assignment' of auxiliary steps to trajectory timesteps is determined from the time
of the auxiliary step, ``dt`` of the trajectory and time at the first frame of the
trajectory (obtained through a :class:`~MDAnalysis.coordinates.base.Timestep`
trajectory (obtained through a :class:`~MDAnalysis.coordinates.timestep.Timestep`
instance from the trajectory), as::
frame = floor((time_at_step - time_at_frame_0 + dt/2)/dt)
Expand Down
12 changes: 6 additions & 6 deletions package/MDAnalysis/auxiliary/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,13 +355,13 @@ def update_ts(self, ts):
Parameters
----------
ts : :class:`~MDAnalysis.coordinates.base.Timestep` object
ts : :class:`~MDAnalysis.coordinates.timestep.Timestep` object
The trajectory timestep for which corresponding auxiliary data is
to be read and updated.
Returns
-------
:class:`~MDAnalysis.coordinates.base.Timestep`
:class:`~MDAnalysis.coordinates.timestep.Timestep`
*ts* with the representative auxiliary
value in ``ts.aux`` be updated appropriately.
Expand Down Expand Up @@ -395,7 +395,7 @@ def read_ts(self, ts):
Parameters
----------
ts : :class:`~MDAnalysis.coordinates.base.Timestep` object
ts : :class:`~MDAnalysis.coordinates.timestep.Timestep` object
The trajectory timestep for which corresponding auxiliary data is
to be read.
Expand Down Expand Up @@ -449,7 +449,7 @@ def step_to_frame(self, step, ts, return_time_diff=False):
step : int
Number of the auxiliary step to calculate closest trajectory frame
for.
ts : :class:`~MDAnalysis.coordinates.base.Timestep` object
ts : :class:`~MDAnalysis.coordinates.timestep.Timestep` object
(Any) timestep from the trajectory the calculated frame number is to
correspond to.
return_time_diff : bool, optional
Expand Down Expand Up @@ -492,7 +492,7 @@ def move_to_ts(self, ts):
Parameters
----------
ts : :class:`~MDAnalysis.coordinates.base.Timestep` object
ts : :class:`~MDAnalysis.coordinates.timestep.Timestep` object
The trajectory timestep before which the auxiliary reader is to
be positioned.
"""
Expand Down Expand Up @@ -526,7 +526,7 @@ def next_nonempty_frame(self, ts):
Parameters
----------
ts : :class:`~MDAnalysis.coordinates.base.Timestep` object
ts : :class:`~MDAnalysis.coordinates.timestep.Timestep` object
Any timestep from the trajectory for which the next 'non-empty'
frame is to be found.
Expand Down
1 change: 0 additions & 1 deletion package/MDAnalysis/coordinates/DLPoly.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import numpy as np

from . import base
from .base import Timestep
from . import core
from ..lib import util
from ..lib.util import cached, store_init_arguments
Expand Down
2 changes: 0 additions & 2 deletions package/MDAnalysis/coordinates/DMS.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@
from . import base
from .core import triclinic_box

from .base import Timestep


class DMSReader(base.SingleFrameReaderBase):
"""
Expand Down
3 changes: 0 additions & 3 deletions package/MDAnalysis/coordinates/FHIAIMS.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,6 @@
from ..lib import mdamath


from .base import Timestep


class FHIAIMSReader(base.SingleFrameReaderBase):
"""Reader for the FHIAIMS geometry format.
Expand Down
3 changes: 1 addition & 2 deletions package/MDAnalysis/coordinates/GRO.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,10 @@
import numpy as np

from . import base
from .base import Timestep
from .core import triclinic_box, triclinic_vectors
from ..exceptions import NoDataError
from ..lib import util

from .timestep import Timestep

"""unitcell dimensions (A, B, C, alpha, beta, gamma)
Expand Down
8 changes: 4 additions & 4 deletions package/MDAnalysis/coordinates/H5MD.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,11 +243,11 @@ class H5MDReader(base.ReaderBase):
Additional data in the *observables* group of the H5MD file are
loaded into the :attr:`Timestep.data
<MDAnalysis.coordinates.base.Timestep.data>` dictionary.
<MDAnalysis.coordinates.timestep.Timestep.data>` dictionary.
Only 3D-periodic boxes or no periodicity are supported; for no
periodicity, :attr:`Timestep.dimensions
<MDAnalysis.coordinates.base.Timestep.dimensions>` will return ``None``.
<MDAnalysis.coordinates.timestep.Timestep.dimensions>` will return ``None``.
Although H5MD can store varying numbers of particles per time step
as produced by, e.g., GCMC simulations, MDAnalysis can currently
Expand Down Expand Up @@ -826,7 +826,7 @@ class H5MDWriter(base.WriterBase):
H5MD trajectories are automatically recognised by the
file extension ".h5md".
All data from the input :class:`~MDAnalysis.coordinates.base.Timestep` is
All data from the input :class:`~MDAnalysis.coordinates.timestep.Timestep` is
written by default. For detailed information on how :class:`H5MDWriter`
handles units, compression, and chunking, see the Notes section below.
Expand Down Expand Up @@ -934,7 +934,7 @@ class H5MDWriter(base.WriterBase):
By default, the writer will write all available data (positions,
velocities, and forces) if detected in the input
:class:`~MDAnalysis.coordinates.base.Timestep`. In addition, the settings
:class:`~MDAnalysis.coordinates.timestep.Timestep`. In addition, the settings
for `compression` and `compression_opts` will be read from
the first available group of positions, velocities, or forces and used as
the default value. To write a file without any one of these datsets,
Expand Down
9 changes: 5 additions & 4 deletions package/MDAnalysis/coordinates/PDB.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@
from ..lib import util
from ..lib.util import store_init_arguments
from . import base
from .timestep import Timestep
from ..topology.core import guess_atom_element
from ..exceptions import NoDataError

Expand Down Expand Up @@ -870,13 +871,13 @@ def _update_frame(self, obj):
* :attr:`PDBWriter.trajectory` (the underlying trajectory
:class:`~MDAnalysis.coordinates.base.Reader`)
* :attr:`PDBWriter.timestep` (the underlying trajectory
:class:`~MDAnalysis.coordinates.base.Timestep`)
:class:`~MDAnalysis.coordinates.timestep.Timestep`)
Before calling :meth:`_write_next_frame` this method **must** be
called at least once to enable extracting topology information from the
current frame.
"""
if isinstance(obj, base.Timestep):
if isinstance(obj, Timestep):
raise TypeError("PDBWriter cannot write Timestep objects "
"directly, since they lack topology information ("
"atom names and types) required in PDB files")
Expand Down Expand Up @@ -970,14 +971,14 @@ def _write_next_frame(self, ts=None, **kwargs):
:Keywords:
*ts*
:class:`base.Timestep` object containing coordinates to be written to trajectory file;
:class:`timestep.Timestep` object containing coordinates to be written to trajectory file;
if ``None`` then :attr:`PDBWriter.ts`` is tried.
*multiframe*
``False``: write a single frame (default); ``True`` behave as a trajectory writer
.. Note::
Before using this method with another :class:`base.Timestep` in the *ts*
Before using this method with another :class:`timestep.Timestep` in the *ts*
argument, :meth:`PDBWriter._update_frame` *must* be called
with the :class:`~MDAnalysis.core.groups.AtomGroup.Universe` as
its argument so that topology information can be gathered.
Expand Down
36 changes: 1 addition & 35 deletions package/MDAnalysis/coordinates/TRJ.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,28 +41,6 @@
* lengths in Angstrom (Å)
* time in ps (but see below)
AMBER trajectory coordinate frames are based on a custom :class:`Timestep`
object.
.. autoclass:: Timestep
:members:
.. attribute:: _pos
coordinates of the atoms as a :class:`numpy.ndarray` of shape `(n_atoms, 3)`
.. attribute:: _velocities
velocities of the atoms as a :class:`numpy.ndarray` of shape `(n_atoms, 3)`;
only available if the trajectory contains velocities or if the
*velocities* = ``True`` keyword has been supplied.
.. attribute:: _forces
forces of the atoms as a :class:`numpy.ndarray` of shape `(n_atoms, 3)`;
only available if the trajectory contains forces or if the
*forces* = ``True`` keyword has been supplied.
.. _netcdf-trajectories:
Expand Down Expand Up @@ -159,6 +137,7 @@
from math import isclose

import MDAnalysis
from .timestep import Timestep
from . import base
from ..lib import util
from ..lib.util import store_init_arguments
Expand All @@ -172,19 +151,6 @@
logger.warning("netCDF4 is not available. Writing AMBER ncdf files will be slow.")


class Timestep(base.Timestep):
"""AMBER trajectory Timestep.
The Timestep can be initialized with `arg` being an integer
(the number of atoms) and an optional keyword argument `velocities` to
allocate space for both coordinates and velocities;
.. versionchanged:: 0.10.0
Added ability to contain Forces
"""
order = 'C'


class TRJReader(base.ReaderBase):
"""AMBER trajectory reader.
Expand Down
23 changes: 13 additions & 10 deletions package/MDAnalysis/coordinates/TRZ.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@
import errno

from . import base
from .base import Timestep
from ..exceptions import NoDataError
from .timestep import Timestep
from ..lib import util
from ..lib.util import cached, store_init_arguments
from .core import triclinic_box, triclinic_vectors
Expand All @@ -62,8 +63,8 @@ class TRZReader(base.ReaderBase):
Attributes
----------
ts : base.Timestep
:class:`~MDAnalysis.coordinates.base.Timestep` object containing
ts : timestep.Timestep
:class:`~MDAnalysis.coordinates.timestep.Timestep` object containing
coordinates of current frame
Note
Expand All @@ -83,6 +84,8 @@ class TRZReader(base.ReaderBase):
.. versionchanged:: 2.1.0
TRZReader now returns a default :attr:`dt` of 1.0 when it cannot be
obtained from the difference between two frames.
.. versionchanged:: 2.3.0
_frame attribute moved to `ts.data` dictionary.
"""

format = "TRZ"
Expand Down Expand Up @@ -198,7 +201,7 @@ def _read_next_timestep(self, ts=None):
"Maybe `topology` is wrong?".format(
self.n_atoms))
ts.frame = data['nframe'][0] - 1 # 0 based for MDA
ts._frame = data['ntrj'][0]
ts.data['frame'] = data['ntrj'][0] # moved from attr to data
ts.time = data['treal'][0]
ts.dimensions = triclinic_box(*(data['box'].reshape(3, 3)))
ts.data['pressure'] = data['pressure']
Expand Down Expand Up @@ -295,9 +298,9 @@ def skip_timestep(self):
"""Timesteps between trajectory frames"""
curr_frame = self.ts.frame
try:
t0 = self.ts._frame
t0 = self.ts.data['frame']
self.next()
t1 = self.ts._frame
t1 = self.ts.data['frame']
skip_timestep = t1 - t0
except StopIteration:
return 0
Expand Down Expand Up @@ -520,8 +523,8 @@ def _write_next_frame(self, obj):
data[att] = 0.0
faked_attrs.append(att)
try:
data['step'] = ts._frame
except AttributeError:
data['step'] = ts.data['frame']
except KeyError:
data['step'] = ts.frame
faked_attrs.append('step')
try:
Expand All @@ -543,8 +546,8 @@ def _write_next_frame(self, obj):
unitcell = np.zeros(9, dtype=np.float32)

try:
vels = ts._velocities
except AttributeError:
vels = ts.velocities
except NoDataError:
vels = np.zeros((self.n_atoms, 3), dtype=np.float32, order='F')
warnings.warn("Timestep didn't have velocity information, "
"this will be set to zero in output trajectory. ")
Expand Down
4 changes: 2 additions & 2 deletions package/MDAnalysis/coordinates/TXYZ.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
from ..lib import util
from . import base
from ..lib.util import openany, cached, store_init_arguments

from .timestep import Timestep

class TXYZReader(base.ReaderBase):
"""Reads from a TXYZ file"""
Expand All @@ -61,7 +61,7 @@ class TXYZReader(base.ReaderBase):
format = ['TXYZ', 'ARC']
# these are assumed!
units = {'time': 'ps', 'length': 'Angstrom'}
_Timestep = base.Timestep
_Timestep = Timestep

@store_init_arguments
def __init__(self, filename, **kwargs):
Expand Down
3 changes: 2 additions & 1 deletion package/MDAnalysis/coordinates/XYZ.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
logger = logging.getLogger('MDAnalysis.coordinates.XYZ')

from . import base
from .timestep import Timestep
from ..lib import util
from ..lib.util import cached, store_init_arguments
from ..exceptions import NoDataError
Expand Down Expand Up @@ -334,7 +335,7 @@ class XYZReader(base.ReaderBase):
format = "XYZ"
# these are assumed!
units = {'time': 'ps', 'length': 'Angstrom'}
_Timestep = base.Timestep
_Timestep = Timestep

@store_init_arguments
def __init__(self, filename, **kwargs):
Expand Down
Loading

0 comments on commit b302e40

Please sign in to comment.