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

Improve xdr cython #3892

Merged
merged 29 commits into from
Nov 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
cf93942
incremental improvements to libmdaxdr
hmacdope Oct 28, 2022
398afb7
fix wrong dims
hmacdope Oct 28, 2022
3a493e3
add boundscheck=False
hmacdope Oct 28, 2022
f2ea113
slight improvement
hmacdope Oct 28, 2022
f2c440c
move to module level decls
hmacdope Nov 3, 2022
aeb118b
try read_direct
hmacdope Nov 3, 2022
9a0d58e
fix frame iteration
hmacdope Nov 3, 2022
1c7df37
use direct read into array for trr
hmacdope Nov 6, 2022
943e699
experimental trr read
hmacdope Nov 6, 2022
6c02836
Revert "experimental trr read"
hmacdope Nov 6, 2022
4381b9b
add pxd for libmdaxdr
hmacdope Nov 6, 2022
b121911
make timestep fat
hmacdope Nov 9, 2022
ec43aed
add explanation
hmacdope Nov 9, 2022
dc45ce6
Merge remote-tracking branch 'upstream/develop' into improve_xdr_cython
hmacdope Nov 12, 2022
64de6fc
change to xvf
hmacdope Nov 12, 2022
572cc65
add some notes
hmacdope Nov 15, 2022
f36476c
test branching on ts.positions in _read_next_timestep
hmacdope Nov 15, 2022
324a4d9
add CHANGELOG
hmacdope Nov 15, 2022
0162b06
fix docs
hmacdope Nov 15, 2022
1c583ef
add cdef
hmacdope Nov 16, 2022
cfa826e
Update package/MDAnalysis/lib/formats/libmdaxdr.pxd
hmacdope Nov 20, 2022
bd2313d
fix inheritance
hmacdope Nov 20, 2022
e7dac9b
add read failure error
hmacdope Nov 20, 2022
2b223e0
fix changelog
hmacdope Nov 23, 2022
907b852
add to libmdanalysis
hmacdope Nov 23, 2022
77a537b
fix error code checking
hmacdope Nov 23, 2022
fa16ab5
Merge branch 'develop' into improve_xdr_cython
orbeckst Nov 29, 2022
6749992
Consolidate licenses across top directory, testsuite and package (#3939)
hmacdope Nov 29, 2022
7202bea
Merge remote-tracking branch 'upstream/develop' into improve_xdr_cython
hmacdope Nov 29, 2022
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
6 changes: 6 additions & 0 deletions package/CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ The rules for this file:
* 2.4.0

Fixes
* XTC and TRR readers now fail with IOError when a status except EOK (=0) is
detected on reading a frame instead of silently continuing
* Consolidate license files across MDAnalysis library packages (PR #3939)
* Kwargs passed through to `MemoryReader` when using `transfer_to_memory()`
and `in_memory=True`.
Expand All @@ -37,6 +39,10 @@ Fixes
(e.g. bonds, angles) (PR #3779).

Enhancements
* Improve C content of libxdr Cython, add `read_direct` methods to read
coordinates, velocities and forces directly into memoryviews of `Timestep`
attributes, make `TRR` timestep have positions, velocities and forces on
`__init__`. (Issue #3891 PR #3892).
Copy link
Member

Choose a reason for hiding this comment

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

add under Fixes: XTC and TRR readers now fail with IOError when a status except EOK (=0) is detected on reading a frame instead of silently continuing

Copy link
Member Author

Choose a reason for hiding this comment

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

Some readers had enough redundancy built in to avoid not continuing with retcode != EOK but at least its now done consistently.

Copy link
Member Author

Choose a reason for hiding this comment

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

This was the pattern that protected some branches

        if return_code != EOK and return_code != EENDOFFILE \
           and return_code != EINTEGER:
            raise IOError('TRR read error = {}'.format(
                **error_message[return_code]))**

        if return_code == EENDOFFILE or return_code == EINTEGER:
            self.reached_eof = True
            raise StopIteration

# can only be EOK at this point but it was a bit opaque. 

Copy link
Member

Choose a reason for hiding this comment

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

Ok, good to know that we probably do not change a lot of behavior. Nevertheless, the current approach is cleaner.

(Btw, while somewhere I came across my own explanation of why TRR stops with EINTEGER and I think it was related to not being able to read the magic number.)

* Improve C content of libdcd Cython (Issue #3882, PR #3888)
* The timeseries method for exporting coordinates from multiple frames to a
NumPy array was added to ProtoReader (PR #3890)
Expand Down
23 changes: 23 additions & 0 deletions package/MDAnalysis/coordinates/TRR.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
MDAnalysis.coordinates.XTC: Read and write GROMACS XTC trajectory files.
MDAnalysis.coordinates.XDR: BaseReader/Writer for XDR based formats
"""
import errno
from . import base
from .XDR import XDRBaseReader, XDRBaseWriter
from ..lib.formats.libmdaxdr import TRRFile
Expand Down Expand Up @@ -151,6 +152,28 @@ class TRRReader(XDRBaseReader):
_writer = TRRWriter
_file = TRRFile

def _read_next_timestep(self, ts=None):
"""copy next frame into timestep

versionadded:: 2.4.0
TRRReader implements this method so that it can use
read_direct_xvf to read the data directly into the timestep
rather than copying it from a temporary array.
"""
if self._frame == self.n_frames - 1:
raise IOError(errno.EIO, 'trying to go over trajectory limit')
if ts is None:
ts = self.ts
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
# allocate arrays to read into, will set to proper values
# in _frame_to_ts
ts.has_positions = True
ts.has_velocities = True
ts.has_forces = True
frame = self._xdr.read_direct_xvf(ts.positions, ts.velocities, ts.forces)
self._frame += 1
self._frame_to_ts(frame, ts)
return ts

def _frame_to_ts(self, frame, ts):
"""convert a trr-frame to a mda TimeStep"""
ts.time = frame.time
Expand Down
14 changes: 2 additions & 12 deletions package/MDAnalysis/coordinates/XDR.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ class XDRBaseReader(base.ReaderBase):
XDR offsets read from trajectory if offsets file read-in fails
.. versionchanged:: 2.0.0
Add a InterProcessLock when generating offsets

.. versionchanged:: 2.4.0
Use a direct read into ts attributes
hmacdope marked this conversation as resolved.
Show resolved Hide resolved
"""
@store_init_arguments
def __init__(self, filename, convert_units=True, sub=None,
Expand Down Expand Up @@ -288,17 +289,6 @@ def _read_frame(self, i):
timestep = self._read_next_timestep()
return timestep

def _read_next_timestep(self, ts=None):
"""copy next frame into timestep"""
if self._frame == self.n_frames - 1:
raise IOError(errno.EIO, 'trying to go over trajectory limit')
if ts is None:
ts = self.ts
frame = self._xdr.read()
self._frame += 1
self._frame_to_ts(frame, ts)
return ts

def Writer(self, filename, n_atoms=None, **kwargs):
"""Return writer for trajectory format"""
if n_atoms is None:
Expand Down
25 changes: 25 additions & 0 deletions package/MDAnalysis/coordinates/XTC.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
MDAnalysis.coordinates.TRR: Read and write GROMACS TRR trajectory files.
MDAnalysis.coordinates.XDR: BaseReader/Writer for XDR based formats
"""

import errno
from . import base
from .XDR import XDRBaseReader, XDRBaseWriter
from ..lib.formats.libmdaxdr import XTCFile
Expand Down Expand Up @@ -130,12 +132,35 @@ class XTCReader(XDRBaseReader):
See :ref:`Notes on offsets <offsets-label>` for more information about
offsets.



"""
format = 'XTC'
units = {'time': 'ps', 'length': 'nm'}
_writer = XTCWriter
_file = XTCFile

def _read_next_timestep(self, ts=None):
"""
copy next frame into timestep

versionadded:: 2.4.0
XTCReader implements this method so that it can use
read_direct_x method of XTCFile to read the data directly
into the timestep rather than copying it from a temporary array.
"""
if self._frame == self.n_frames - 1:
raise IOError(errno.EIO, 'trying to go over trajectory limit')
if ts is None:
ts = self.ts
if ts.has_positions:
frame = self._xdr.read_direct_x(ts.positions)
else:
frame = self._xdr.read()
self._frame += 1
self._frame_to_ts(frame, ts)
return ts

def _frame_to_ts(self, frame, ts):
"""convert a xtc-frame to a mda TimeStep"""
ts.frame = self._frame
Expand Down
110 changes: 110 additions & 0 deletions package/MDAnalysis/lib/formats/libmdaxdr.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# -*- Mode: python; tab-width: 4; indent-tabs-mode:nil; coding:utf-8 -*-
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
#
# MDAnalysis --- https://www.mdanalysis.org
# Copyright (c) 2006-2017 The MDAnalysis Development Team and contributors
# (see the file AUTHORS for the full list of names)
#
# Released under the GNU Public Licence, v2 or any higher version
#
# Please cite your use of MDAnalysis in published work:
#
# R. J. Gowers, M. Linke, J. Barnoud, T. J. E. Reddy, M. N. Melo, S. L. Seyler,
# D. L. Dotson, J. Domanski, S. Buchoux, I. M. Kenney, and O. Beckstein.
# MDAnalysis: A Python package for the rapid analysis of molecular dynamics
# simulations. In S. Benthall and S. Rostrup editors, Proceedings of the 15th
# Python in Science Conference, pages 102-109, Austin, TX, 2016. SciPy.
# doi: 10.25080/majora-629e541a-00e
#
# N. Michaud-Agrawal, E. J. Denning, T. B. Woolf, and O. Beckstein.
# MDAnalysis: A Toolkit for the Analysis of Molecular Dynamics Simulations.
# J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787
#

import numpy as np
cimport numpy as np

np.import_array()
from libc.stdint cimport int64_t

from libc.stdio cimport SEEK_SET, SEEK_CUR, SEEK_END

cdef extern from 'include/xdrfile.h':
ctypedef struct XDRFILE:
pass

XDRFILE* xdrfile_open (char * path, char * mode)
int xdrfile_close (XDRFILE * xfp)
int xdr_seek(XDRFILE *xfp, int64_t pos, int whence)
int64_t xdr_tell(XDRFILE *xfp)
ctypedef float matrix[3][3]
ctypedef float rvec[3]


cdef extern from 'include/xdrfile_xtc.h':
int read_xtc_natoms(char * fname, int * natoms)
int read_xtc(XDRFILE * xfp, int natoms, int * step, float * time, matrix box,
rvec * x, float * prec)
int write_xtc(XDRFILE * xfp, int natoms, int step, float time, matrix box,
rvec * x, float prec)



cdef extern from 'include/xdrfile_trr.h':
int read_trr_natoms(char *fname, int *natoms)
int read_trr(XDRFILE *xfp, int natoms, int *step, float *time, float *_lambda,
matrix box, rvec *x, rvec *v, rvec *f, int *has_prop)
int write_trr(XDRFILE *xfp, int natoms, int step, float time, float _lambda,
matrix box, rvec *x, rvec *v, rvec *f)


cdef extern from 'include/xtc_seek.h':
int read_xtc_n_frames(char *fn, int *n_frames, int *est_nframes, int64_t **offsets)


cdef extern from 'include/trr_seek.h':
int read_trr_n_frames(char *fn, int *n_frames, int *est_nframes, int64_t **offsets)


cdef class _XDRFile:
"""Base python wrapper for gromacs-xdr formats

This class can be similar to the normal file objects in python. The read()
function will return a frame and all information in it instead of a single
line. Additionally the context-manager protocoll is supported as well.

Note
----
This class can't be initialized; use one of the subclasses :class:`XTCFile` or :class:`TRRFile`.
"""
# number of atoms
cdef readonly int n_atoms
# whether the file is open
cdef int is_open
# whether we have reached the end of the file
cdef int reached_eof
# the XDR file pointer
cdef XDRFILE *xfp
# the name of the xdr file
cdef readonly fname
# the current frame in the file
cdef int current_frame
# the file mode
cdef str mode
# the simulation box
cdef np.ndarray box
# numpy array of offsets into the fle
cdef np.ndarray _offsets
# whether we have the offsets
cdef readonly int _has_offsets


cdef class XTCFile(_XDRFile):
"""File-like wrapper for gromacs XTC files."""
# precision of the XTC file
cdef float precision



cdef class TRRFile(_XDRFile):
"""File-like wrapper for gromacs TRR files"""
Loading