Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
tsoc
openmm
Commits
cc158237
Commit
cc158237
authored
Apr 16, 2025
by
Evan Pretti
Browse files
Read comment block length from DCD when appending
parent
de180e4e
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
102 additions
and
6 deletions
+102
-6
wrappers/python/openmm/app/dcdfile.py
wrappers/python/openmm/app/dcdfile.py
+10
-4
wrappers/python/tests/TestDcdFile.py
wrappers/python/tests/TestDcdFile.py
+92
-2
No files found.
wrappers/python/openmm/app/dcdfile.py
View file @
cc158237
...
...
@@ -6,7 +6,7 @@ Simbios, the NIH National Center for Physics-Based Simulation of
Biological Structures at Stanford, funded under the NIH Roadmap for
Medical Research, grant U54 GM072970. See https://simtk.org.
Portions copyright (c) 2012 Stanford University and the Authors.
Portions copyright (c) 2012
-2025
Stanford University and the Authors.
Authors: Peter Eastman
Contributors:
...
...
@@ -84,12 +84,18 @@ class DCDFile(object):
if
topology
.
getUnitCellDimensions
()
is
not
None
:
boxFlag
=
1
if
append
:
file
.
seek
(
8
,
os
.
SEEK_SET
)
file
.
seek
(
0
,
os
.
SEEK_SET
)
headerBytes
=
struct
.
unpack
(
'<i'
,
file
.
read
(
4
))[
0
]
headerMagic
=
file
.
read
(
4
)
if
headerBytes
!=
84
or
headerMagic
!=
b
'CORD'
:
raise
ValueError
(
'Cannot append to DCD file with invalid header'
)
self
.
_modelCount
=
struct
.
unpack
(
'<i'
,
file
.
read
(
4
))[
0
]
file
.
seek
(
268
,
os
.
SEEK_SET
)
file
.
seek
(
92
,
os
.
SEEK_SET
)
commentsBytes
=
struct
.
unpack
(
'<i'
,
file
.
read
(
4
))[
0
]
file
.
seek
(
104
+
commentsBytes
,
os
.
SEEK_SET
)
numAtoms
=
struct
.
unpack
(
'<i'
,
file
.
read
(
4
))[
0
]
if
numAtoms
!=
topology
.
getNumAtoms
():
raise
ValueError
(
'Cannot append
to a DCD file that contains a different number of
atoms'
)
raise
ValueError
(
f
'Cannot append
from system with
{
topology
.
getNumAtoms
()
}
atoms to DCD file with
{
numAtoms
}
atoms'
)
else
:
header
=
struct
.
pack
(
'<i4c9if'
,
84
,
b
'C'
,
b
'O'
,
b
'R'
,
b
'D'
,
0
,
firstStep
,
interval
,
0
,
0
,
0
,
0
,
0
,
0
,
dt
)
header
+=
struct
.
pack
(
'<13i'
,
boxFlag
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
24
,
84
,
164
,
2
)
...
...
wrappers/python/tests/TestDcdFile.py
View file @
cc158237
...
...
@@ -5,11 +5,10 @@ import openmm as mm
from
openmm
import
unit
from
random
import
random
import
os
import
struct
def
_read_dcd_header
(
file
):
import
struct
with
open
(
file
,
"r+b"
)
as
f
:
f
.
seek
(
8
,
os
.
SEEK_SET
)
modelCount
=
struct
.
unpack
(
"<i"
,
f
.
read
(
4
))[
0
]
...
...
@@ -129,6 +128,97 @@ class TestDCDFile(unittest.TestCase):
self
.
assertEqual
(
20
,
currStep
)
os
.
remove
(
fname
)
def
testAppendAtomCountMismatch
(
self
):
"""Test that appending to a DCD file with a different number of atoms raises an error."""
fname
=
tempfile
.
mktemp
(
suffix
=
'.dcd'
)
pdb
=
app
.
PDBFile
(
'systems/alanine-dipeptide-explicit.pdb'
)
ff
=
app
.
ForceField
(
'amber99sb.xml'
,
'tip3p.xml'
)
system
=
ff
.
createSystem
(
pdb
.
topology
)
# Create a simulation and write some frames to a DCD file.
integrator
=
mm
.
VerletIntegrator
(
0.001
*
unit
.
picoseconds
)
simulation
=
app
.
Simulation
(
pdb
.
topology
,
system
,
integrator
,
mm
.
Platform
.
getPlatform
(
'Reference'
))
atomSubset1
=
[
atom
.
index
for
chain
,
_
in
zip
(
pdb
.
topology
.
chains
(),
range
(
1
))
for
atom
in
chain
.
atoms
()]
atomSubset2
=
[
atom
.
index
for
chain
,
_
in
zip
(
pdb
.
topology
.
chains
(),
range
(
2
))
for
atom
in
chain
.
atoms
()]
dcd
=
app
.
DCDReporter
(
fname
,
2
,
atomSubset
=
atomSubset1
)
simulation
.
reporters
.
append
(
dcd
)
simulation
.
context
.
setPositions
(
pdb
.
positions
)
simulation
.
context
.
setVelocitiesToTemperature
(
300
*
unit
.
kelvin
)
simulation
.
step
(
10
)
del
simulation
del
dcd
# Create a new simulation and have it append some more frames.
integrator
=
mm
.
VerletIntegrator
(
0.001
*
unit
.
picoseconds
)
simulation
=
app
.
Simulation
(
pdb
.
topology
,
system
,
integrator
,
mm
.
Platform
.
getPlatform
(
'Reference'
))
simulation
.
currentStep
=
10
dcd
=
app
.
DCDReporter
(
fname
,
2
,
append
=
True
,
atomSubset
=
atomSubset2
)
simulation
.
reporters
.
append
(
dcd
)
simulation
.
context
.
setPositions
(
pdb
.
positions
)
simulation
.
context
.
setVelocitiesToTemperature
(
300
*
unit
.
kelvin
)
with
self
.
assertRaises
(
ValueError
):
simulation
.
step
(
10
)
def
testAppendLongCommentBlock
(
self
):
"""Test appending to an existing trajectory with a long comment block."""
fname
=
tempfile
.
mktemp
(
suffix
=
'.dcd'
)
pdb
=
app
.
PDBFile
(
'systems/alanine-dipeptide-implicit.pdb'
)
ff
=
app
.
ForceField
(
'amber99sb.xml'
,
'tip3p.xml'
)
system
=
ff
.
createSystem
(
pdb
.
topology
)
# Create a simulation and write some frames to a DCD file.
integrator
=
mm
.
VerletIntegrator
(
0.001
*
unit
.
picoseconds
)
simulation
=
app
.
Simulation
(
pdb
.
topology
,
system
,
integrator
,
mm
.
Platform
.
getPlatform
(
'Reference'
))
dcd
=
app
.
DCDReporter
(
fname
,
2
)
simulation
.
reporters
.
append
(
dcd
)
simulation
.
context
.
setPositions
(
pdb
.
positions
)
simulation
.
context
.
setVelocitiesToTemperature
(
300
*
unit
.
kelvin
)
simulation
.
step
(
10
)
self
.
assertEqual
(
5
,
dcd
.
_dcd
.
_modelCount
)
del
simulation
del
dcd
len1
=
os
.
stat
(
fname
).
st_size
# Some software writes more than 2 80-byte "comment lines" to a DCD
# file. Modify the DCD to simulate this and ensure we can append.
commentLines
=
10
with
open
(
fname
,
"rb"
)
as
dcdFile
:
dcdHeader
=
dcdFile
.
read
(
92
)
dcdCommentsLength
=
struct
.
unpack
(
"<i"
,
dcdFile
.
read
(
4
))[
0
]
dcdFile
.
read
(
dcdCommentsLength
+
4
)
dcdContents
=
dcdFile
.
read
()
with
open
(
fname
,
"wb"
)
as
dcdFile
:
dcdFile
.
write
(
dcdHeader
)
dcdNewCommentsLength
=
4
+
80
*
commentLines
dcdFile
.
write
(
struct
.
pack
(
"<2i"
,
dcdNewCommentsLength
,
commentLines
))
dcdFile
.
write
(
bytes
(
80
*
commentLines
))
dcdFile
.
write
(
struct
.
pack
(
"<i"
,
dcdNewCommentsLength
))
dcdFile
.
write
(
dcdContents
)
# Create a new simulation and have it append some more frames.
integrator
=
mm
.
VerletIntegrator
(
0.001
*
unit
.
picoseconds
)
simulation
=
app
.
Simulation
(
pdb
.
topology
,
system
,
integrator
,
mm
.
Platform
.
getPlatform
(
'Reference'
))
simulation
.
currentStep
=
10
dcd
=
app
.
DCDReporter
(
fname
,
2
,
append
=
True
)
simulation
.
reporters
.
append
(
dcd
)
simulation
.
context
.
setPositions
(
pdb
.
positions
)
simulation
.
context
.
setVelocitiesToTemperature
(
300
*
unit
.
kelvin
)
simulation
.
step
(
10
)
self
.
assertEqual
(
10
,
dcd
.
_dcd
.
_modelCount
)
len2
=
os
.
stat
(
fname
).
st_size
self
.
assertEqual
(
len2
-
len1
,
dcdNewCommentsLength
-
dcdCommentsLength
+
5
*
3
*
4
*
(
system
.
getNumParticles
()
+
2
))
del
simulation
del
dcd
modelCount
,
currStep
=
_read_dcd_header
(
fname
)
self
.
assertEqual
(
10
,
modelCount
)
self
.
assertEqual
(
20
,
currStep
)
os
.
remove
(
fname
)
if
__name__
==
'__main__'
:
unittest
.
main
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment