Skip to content

Commit

Permalink
Make CRD EXT format selectable in CRDWriter (#3635)
Browse files Browse the repository at this point in the history
* Fixes issue #3605
* Inclusion of an boolean kwarg extension=False|True for the CRDWriter.write() function to
   force use of the EXTENDED output format
* add tests for EXT writing
* update CHANGELOG
* update AUTHORS
  • Loading branch information
mdpoleto authored Apr 18, 2022
1 parent c0a4f61 commit 32de86f
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 10 deletions.
3 changes: 2 additions & 1 deletion package/AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,8 @@ Chronological list of authors
- Sukeerti T
- Robot Jelly
- Mark Verma

- Marcelo D. Poleto


External code
-------------
Expand Down
2 changes: 2 additions & 0 deletions package/CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ Enhancements
monatomic ion charges or edge cases with nitrogen, sulfur, phosphorus and
conjugated systems should now have correctly assigned bond orders and
charges.
* CRD extended format can now be explicitly requested with the `extended`
keyword (Issue #3605)

Changes
* ITPParser no longer adds an angle for water molecules that have the SETTLE
Expand Down
20 changes: 18 additions & 2 deletions package/MDAnalysis/coordinates/CRD.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ class CRDWriter(base.WriterBase):
.. versionchanged:: 0.11.0
Frames now 0-based instead of 1-based
.. versionchanged:: 2.2.0
CRD extended format can now be explicitly requested with the
`extended` keyword
"""
format = 'CRD'
units = {'time': None, 'length': 'Angstrom'}
Expand All @@ -151,11 +154,23 @@ def __init__(self, filename, **kwargs):
----------
filename : str or :class:`~MDAnalysis.lib.util.NamedStream`
name of the output file or a stream
extended : bool (optional)
By default, noextended CRD format is used [``False``].
However, extended CRD format can be forced by
specifying `extended` ``=True``. Note that the extended format
is *always* used if the number of atoms exceeds 99,999, regardless
of the setting of `extended`.
.. versionadded:: 2.2.0
"""

self.filename = util.filename(filename, ext='crd')
self.crd = None

# account for explicit crd format, if requested
self.extended = kwargs.pop("extended", False)

def write(self, selection, frame=None):
"""Write selection at current trajectory frame to file.
Expand All @@ -182,14 +197,15 @@ def write(self, selection, frame=None):
except AttributeError:
frame = 0 # should catch cases when we are analyzing a single PDB (?)


atoms = selection.atoms # make sure to use atoms (Issue 46)
coor = atoms.positions # can write from selection == Universe (Issue 49)

n_atoms = len(atoms)
# Detect which format string we're using to output (EXT or not)
# *len refers to how to truncate various things,
# depending on output format!
if n_atoms > 99999:
if self.extended or n_atoms > 99999:
at_fmt = self.fmt['ATOM_EXT']
serial_len = 10
resid_len = 8
Expand Down Expand Up @@ -238,7 +254,7 @@ def write(self, selection, frame=None):
crd.write("*\n")

# Write NUMATOMS
if n_atoms > 99999:
if self.extended or n_atoms > 99999:
crd.write(self.fmt['NUMATOMS_EXT'].format(n_atoms))
else:
crd.write(self.fmt['NUMATOMS'].format(n_atoms))
Expand Down
39 changes: 32 additions & 7 deletions testsuite/MDAnalysisTests/coordinates/test_crd.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@

import pytest
from numpy.testing import (
assert_equal,
assert_equal,assert_allclose
)

import MDAnalysis as mda
import os

from MDAnalysisTests.datafiles import CRD
from MDAnalysisTests import make_Universe
Expand All @@ -40,7 +41,7 @@ def u(self):

@pytest.fixture()
def outfile(self, tmpdir):
return str(tmpdir) + '/out.crd'
return os.path.join(str(tmpdir), 'test.crd')

def test_write_atoms(self, u, outfile):
# Test that written file when read gives same coordinates
Expand All @@ -66,11 +67,35 @@ def CRD_iter(fn):
for ref, other in zip(CRD_iter(CRD), CRD_iter(outfile)):
assert ref == other

def test_write_EXT(self):
# TODO: Write tests that use EXT output format
# Must have *lots* of atoms, maybe fake the system
# to make tests faster
pass
def test_write_EXT(self, u, outfile):
# Use the `extended` keyword to force the EXT format
u.atoms.write(outfile, extended=True)

with open(outfile, 'r') as inf:
format_line = inf.readlines()[2]
assert 'EXT' in format_line, "EXT format expected"

def test_write_EXT_read(self, u, outfile):
# Read EXT format and check atom positions
u.atoms.write(outfile, extended=True)

u2 = mda.Universe(outfile)

sel1 = u.select_atoms('all')
sel2 = u2.select_atoms('all')

cog1 = sel1.center_of_geometry()
cog2 = sel2.center_of_geometry()

assert_equal(len(u.atoms), len(u2.atoms)), 'Equal number of '\
'atoms expected in both CRD formats'
assert_equal(len(u.atoms.residues),
len(u2.atoms.residues)), 'Equal number of residues expected in'\
'both CRD formats'
assert_equal(len(u.atoms.segments),
len(u2.atoms.segments)), 'Equal number of segments expected in'\
'both CRD formats'
assert_allclose(cog1, cog2, rtol=1e-6, atol=0), 'Same centroid expected for both CRD formats'


class TestCRDWriterMissingAttrs(object):
Expand Down

0 comments on commit 32de86f

Please sign in to comment.