-
Notifications
You must be signed in to change notification settings - Fork 648
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 header length in dcd #1767
fix header length in dcd #1767
Changes from all commits
6fdf06d
fd68f60
adaf9d9
b307e73
75b69bc
2c55dcd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -165,21 +165,21 @@ def outfile(self, tmpdir): | |
|
||
@pytest.fixture() | ||
def correct_values(self): | ||
return [[0, 0, 0], [49, 49, 4.68953]] | ||
return [[0, 1000, 0], [49, 1049, 4.68953]] | ||
|
||
@pytest.fixture() | ||
def correct_values_mass(self): | ||
return [[0, 0, 0], [49, 49, 4.74920]] | ||
return [[0, 1000, 0], [49, 1049, 4.74920]] | ||
|
||
@pytest.fixture() | ||
def correct_values_group(self): | ||
return [[0, 0, 0, 0, 0], | ||
[49, 49, 4.7857, 4.7048, 4.6924]] | ||
return [[0, 1000, 0, 0, 0], | ||
[49, 1049, 4.7857, 4.7048, 4.6924]] | ||
|
||
@pytest.fixture() | ||
def correct_values_backbone_group(self): | ||
return [[0, 0, 0, 0, 0], | ||
[49, 49, 4.6997, 1.9154, 2.7139]] | ||
return [[0, 1000, 0, 0, 0], | ||
[49, 1049, 4.6997, 1.9154, 2.7139]] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you clarify why results in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i.e., if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the changed time. The DCD file doesn't start at time point 0 but rather at time 1000. We have been treating this wrong for some time. |
||
|
||
|
||
def test_progress_meter(self, capsys, universe): | ||
|
@@ -217,7 +217,7 @@ def test_rmsd_atomgroup_selections(self, universe): | |
def test_rmsd_single_frame(self, universe): | ||
RMSD = MDAnalysis.analysis.rms.RMSD(universe, select='name CA', | ||
start=5, stop=6).run() | ||
single_frame = [[5, 5, 0.91544906]] | ||
single_frame = [[5, 1005, 0.91544906]] | ||
assert_almost_equal(RMSD.rmsd, single_frame, 4, | ||
err_msg="error: rmsd profile should match" + | ||
"test values") | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -75,6 +75,8 @@ def reader(self, trajectory): | |
|
||
def iter_ts(self, i): | ||
ts = self.universe.trajectory[i] | ||
# correct time because memory reader doesn't read the correct time | ||
ts.time = ts.frame * self.dt | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you briefly clarify why DCD change is impacting memory reader here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the memory reader tests are based on the DCD file and assumed it started from 0. This code restores that assumption. The memory reader can't actually deal with a trajectory that doesn't start at 0 at the moment. See the new issue #1769 |
||
return ts | ||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,7 @@ | |
from collections import namedtuple | ||
import os | ||
import string | ||
import struct | ||
|
||
import hypothesis.strategies as strategies | ||
from hypothesis import example, given | ||
|
@@ -242,6 +243,22 @@ def test_write_header(tmpdir): | |
assert header['nsavc'] == 10 | ||
assert np.allclose(header['delta'], .02) | ||
|
||
# we also check the bytes written directly. | ||
with open(testfile, 'rb') as fh: | ||
header_bytes = fh.read() | ||
# check for magic number | ||
assert struct.unpack('i', header_bytes[:4])[0] == 84 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's been a while since I had to reverse engineer Fortran binary, but this looks right- There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, the magic number is the length of the data block. It looks like all data blocks in the DCD file are marked with numbers of the corresponding length at the beginning and end. As I can see the header of a DCD file has 3-4 blocks.
|
||
# magic number should be written again before remark section | ||
assert struct.unpack('i', header_bytes[88:92])[0] == 84 | ||
# length of remark section. We hard code this to 244 right now | ||
assert struct.unpack('i', header_bytes[92:96])[0] == 244 | ||
# say we have 3 block of length 80 | ||
assert struct.unpack('i', header_bytes[96:100])[0] == 3 | ||
# after the remark section the length should be reported again | ||
assert struct.unpack('i', header_bytes[340:344])[0] == 244 | ||
# this is a magic number as far as I see | ||
assert struct.unpack('i', header_bytes[344:348])[0] == 4 | ||
|
||
|
||
def test_write_no_header(tmpdir): | ||
fname = str(tmpdir.join('test.dcd')) | ||
|
@@ -301,7 +318,7 @@ def write_dcd(in_name, out_name, remarks='testing', header=None): | |
|
||
@given(remarks=strategies.text( | ||
alphabet=string.printable, min_size=0, | ||
max_size=240)) # handle the printable ASCII strings | ||
max_size=239)) # handle the printable ASCII strings | ||
@example(remarks='') | ||
def test_written_remarks_property(remarks, tmpdir, dcd): | ||
# property based testing for writing of a wide range of string | ||
|
@@ -310,7 +327,7 @@ def test_written_remarks_property(remarks, tmpdir, dcd): | |
header = dcd.header | ||
header['remarks'] = remarks | ||
write_dcd(DCD, testfile, header=header) | ||
expected_remarks = remarks[:240] | ||
expected_remarks = remarks | ||
with DCDFile(testfile) as f: | ||
assert f.header['remarks'] == expected_remarks | ||
|
||
|
@@ -323,6 +340,8 @@ def written_dcd(tmpdir_factory): | |
testfile = str(testfile) | ||
write_dcd(DCD, testfile) | ||
Result = namedtuple("Result", "testfile, header, orgfile") | ||
# throw away last char we didn't save due to null termination | ||
header['remarks'] = header['remarks'][:-1] | ||
return Result(testfile, header, DCD) | ||
|
||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed we have a problem with 0 terminating a string if they are longer then 240 characters. This isn't an issue for writing! It might cause issues for reading with external libraries. Our own cython code seems to handle a missing 0 terminator just fine. There is almost no way for us to test this. The cython library converts the char array into proper python string internally. We never get to see the raw char buffer in python.
I can again to a test of the expected byte. But nothing more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I adjusted the tests and docs for this change. This way we can be sure that any DCD written by MDAnalysis doesn't trip over another C library reading DCD.