imdclient 0.1.1__py3-none-any.whl → 0.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- imdclient/{IMDREADER.py → IMD.py} +16 -15
- imdclient/IMDClient.py +146 -71
- imdclient/data/gromacs/md/gromacs_v3_nst8.mdp +58 -0
- imdclient/data/lammps/md/{lammps_v3.in → lammps_v3_nst_1.in} +3 -3
- imdclient/data/lammps/md/lammps_v3_nst_8.in +71 -0
- imdclient/data/namd/md/{namd_v3.namd → namd_v3_nst_1.namd} +17 -5
- imdclient/data/namd/md/namd_v3_nst_8.namd +59 -0
- imdclient/tests/base.py +133 -45
- imdclient/tests/conftest.py +14 -10
- imdclient/tests/datafiles.py +17 -9
- imdclient/tests/docker_testing/docker.md +25 -0
- imdclient/tests/test_gromacs.py +32 -10
- imdclient/tests/test_imdclient.py +51 -0
- imdclient/tests/test_imdreader.py +20 -6
- imdclient/tests/test_lammps.py +57 -12
- imdclient/tests/test_manual.py +52 -29
- imdclient/tests/test_namd.py +101 -14
- imdclient/tests/test_stream_analysis.py +2 -2
- imdclient/tests/utils.py +0 -1
- imdclient/utils.py +8 -8
- imdclient-0.1.3.dist-info/LICENSE +5 -0
- {imdclient-0.1.1.dist-info → imdclient-0.1.3.dist-info}/METADATA +21 -32
- imdclient-0.1.3.dist-info/RECORD +42 -0
- {imdclient-0.1.1.dist-info → imdclient-0.1.3.dist-info}/WHEEL +1 -1
- imdclient/data/gromacs/md/gromacs_v3_nst1.tpr +0 -0
- imdclient/data/gromacs/md/gromacs_v3_nst1.trr +0 -0
- imdclient/data/lammps/md/lammps_trj.h5md +0 -0
- imdclient/data/namd/md/alanin.dcd +0 -0
- imdclient-0.1.1.dist-info/LICENSE +0 -21
- imdclient-0.1.1.dist-info/RECORD +0 -42
- {imdclient-0.1.1.dist-info → imdclient-0.1.3.dist-info}/AUTHORS.md +0 -0
- {imdclient-0.1.1.dist-info → imdclient-0.1.3.dist-info}/top_level.txt +0 -0
imdclient/tests/base.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
from imdclient.IMDClient import IMDClient
|
2
|
+
from imdclient.IMD import IMDReader
|
2
3
|
import pytest
|
3
4
|
from pathlib import Path
|
4
5
|
import os
|
@@ -9,8 +10,11 @@ from numpy.testing import (
|
|
9
10
|
assert_allclose,
|
10
11
|
)
|
11
12
|
import numpy as np
|
12
|
-
|
13
|
+
import docker
|
13
14
|
import logging
|
15
|
+
import shutil
|
16
|
+
import MDAnalysis as mda
|
17
|
+
from .utils import get_free_port
|
14
18
|
|
15
19
|
logger = logging.getLogger("imdclient.IMDClient")
|
16
20
|
|
@@ -61,62 +65,146 @@ def assert_allclose_with_logging(a, b, rtol=1e-07, atol=0, equal_nan=False):
|
|
61
65
|
class IMDv3IntegrationTest:
|
62
66
|
|
63
67
|
@pytest.fixture()
|
64
|
-
def
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
68
|
+
def setup_command(self):
|
69
|
+
return None
|
70
|
+
|
71
|
+
@pytest.fixture()
|
72
|
+
def port(self):
|
73
|
+
yield get_free_port()
|
74
|
+
|
75
|
+
@pytest.fixture()
|
76
|
+
def docker_client(
|
77
|
+
self,
|
78
|
+
tmp_path,
|
79
|
+
input_files,
|
80
|
+
setup_command,
|
81
|
+
simulation_command,
|
82
|
+
port,
|
83
|
+
):
|
84
|
+
# In CI, container process needs access to tmp_path
|
85
|
+
tmp_path.chmod(0o777)
|
86
|
+
docker_client = docker.from_env()
|
87
|
+
img = docker_client.images.pull(
|
88
|
+
"ghcr.io/becksteinlab/streaming-md-docker:main-Common-CPU"
|
89
|
+
)
|
90
|
+
# Copy input files into tmp_path
|
91
|
+
for inp in input_files:
|
92
|
+
shutil.copy(inp, tmp_path)
|
93
|
+
|
94
|
+
cmdstring = "cd '/tmp'"
|
95
|
+
# Run the setup command, if any
|
96
|
+
if setup_command is not None:
|
97
|
+
# This should be blocking
|
98
|
+
cmdstring += " && " + setup_command
|
99
|
+
|
100
|
+
cmdstring += " && " + simulation_command
|
101
|
+
|
102
|
+
# Start the container, mount tmp_path, run simulation
|
103
|
+
container = docker_client.containers.run(
|
104
|
+
img,
|
105
|
+
f"/bin/sh -c '{cmdstring}'",
|
106
|
+
detach=True,
|
107
|
+
volumes={tmp_path.as_posix(): {"bind": "/tmp", "mode": "rw"}},
|
108
|
+
ports={"8888/tcp": port},
|
109
|
+
name="sim",
|
110
|
+
remove=True,
|
75
111
|
)
|
76
|
-
t = time.time()
|
77
112
|
|
78
|
-
|
79
|
-
|
80
|
-
|
113
|
+
# For now, just wait 30 seconds
|
114
|
+
# life is too short to figure out how to redirect all stdout from inside
|
115
|
+
# a container
|
116
|
+
time.sleep(30)
|
117
|
+
|
118
|
+
yield
|
119
|
+
try:
|
120
|
+
container.stop()
|
121
|
+
except docker.errors.NotFound:
|
122
|
+
pass
|
123
|
+
|
124
|
+
@pytest.fixture()
|
125
|
+
def imd_u(self, docker_client, topol, tmp_path, port):
|
126
|
+
u = mda.Universe((tmp_path / topol), f"imd://localhost:{port}")
|
127
|
+
with mda.Writer(
|
128
|
+
(tmp_path / "imd.trr").as_posix(), u.trajectory.n_atoms
|
129
|
+
) as w:
|
130
|
+
for ts in u.trajectory:
|
131
|
+
w.write(u.atoms)
|
132
|
+
yield mda.Universe((tmp_path / topol), (tmp_path / "imd.trr"))
|
133
|
+
|
134
|
+
@pytest.fixture()
|
135
|
+
def true_u(self, topol, traj, imd_u, tmp_path):
|
136
|
+
u = mda.Universe(
|
137
|
+
(tmp_path / topol),
|
138
|
+
(tmp_path / traj),
|
139
|
+
)
|
140
|
+
yield u
|
81
141
|
|
82
|
-
|
83
|
-
|
84
|
-
|
142
|
+
@pytest.fixture()
|
143
|
+
def comp_time(self):
|
144
|
+
return True
|
85
145
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
os.killpg(os.getpgid(p.pid), signal.SIGTERM)
|
146
|
+
@pytest.fixture()
|
147
|
+
def comp_dt(self):
|
148
|
+
return True
|
90
149
|
|
91
150
|
@pytest.fixture()
|
92
|
-
def
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
if
|
151
|
+
def comp_step(self):
|
152
|
+
return True
|
153
|
+
|
154
|
+
def test_compare_imd_to_true_traj(
|
155
|
+
self, imd_u, true_u, first_frame, comp_time, comp_dt, comp_step
|
156
|
+
):
|
157
|
+
for i in range(first_frame, len(true_u.trajectory)):
|
158
|
+
if comp_time:
|
159
|
+
assert_allclose(
|
160
|
+
true_u.trajectory[i].time,
|
161
|
+
imd_u.trajectory[i - first_frame].time,
|
162
|
+
atol=1e-03,
|
163
|
+
)
|
164
|
+
if comp_dt:
|
165
|
+
assert_allclose(
|
166
|
+
true_u.trajectory[i].dt,
|
167
|
+
imd_u.trajectory[i - first_frame].dt,
|
168
|
+
atol=1e-03,
|
169
|
+
)
|
170
|
+
if comp_step:
|
171
|
+
assert_allclose(
|
172
|
+
true_u.trajectory[i].data["step"],
|
173
|
+
imd_u.trajectory[i - first_frame].data["step"],
|
174
|
+
)
|
175
|
+
if (
|
176
|
+
true_u.trajectory[i].dimensions is not None
|
177
|
+
and imd_u.trajectory[i - first_frame].dimensions is not None
|
178
|
+
):
|
106
179
|
assert_allclose_with_logging(
|
107
|
-
|
108
|
-
|
180
|
+
true_u.trajectory[i].dimensions,
|
181
|
+
imd_u.trajectory[i - first_frame].dimensions,
|
109
182
|
atol=1e-03,
|
110
183
|
)
|
111
|
-
if
|
184
|
+
if (
|
185
|
+
true_u.trajectory[i].has_positions
|
186
|
+
and imd_u.trajectory[i - first_frame].has_positions
|
187
|
+
):
|
112
188
|
assert_allclose_with_logging(
|
113
|
-
|
189
|
+
true_u.trajectory[i].positions,
|
190
|
+
imd_u.trajectory[i - first_frame].positions,
|
191
|
+
atol=1e-03,
|
114
192
|
)
|
115
|
-
if
|
193
|
+
if (
|
194
|
+
true_u.trajectory[i].has_velocities
|
195
|
+
and imd_u.trajectory[i - first_frame].has_velocities
|
196
|
+
):
|
116
197
|
assert_allclose_with_logging(
|
117
|
-
|
198
|
+
true_u.trajectory[i].velocities,
|
199
|
+
imd_u.trajectory[i - first_frame].velocities,
|
200
|
+
atol=1e-03,
|
118
201
|
)
|
119
|
-
if
|
202
|
+
if (
|
203
|
+
true_u.trajectory[i].has_forces
|
204
|
+
and imd_u.trajectory[i - first_frame].has_forces
|
205
|
+
):
|
120
206
|
assert_allclose_with_logging(
|
121
|
-
|
207
|
+
true_u.trajectory[i].forces,
|
208
|
+
imd_u.trajectory[i - first_frame].forces,
|
209
|
+
atol=1e-03,
|
122
210
|
)
|
imdclient/tests/conftest.py
CHANGED
@@ -6,33 +6,37 @@ Global pytest fixtures
|
|
6
6
|
# Command line arguments for 'test_manual.py'
|
7
7
|
def pytest_addoption(parser):
|
8
8
|
parser.addoption(
|
9
|
-
"--
|
9
|
+
"--topol_path_arg",
|
10
10
|
action="store",
|
11
|
+
default=None,
|
11
12
|
)
|
12
13
|
parser.addoption(
|
13
|
-
"--
|
14
|
+
"--traj_path_arg",
|
14
15
|
action="store",
|
16
|
+
default=None,
|
17
|
+
)
|
18
|
+
parser.addoption(
|
19
|
+
"--first_frame_arg", action="store", type=int, default=None
|
15
20
|
)
|
16
|
-
parser.addoption("--first_frame_arg", action="store", type=int)
|
17
21
|
|
18
22
|
|
19
23
|
def pytest_generate_tests(metafunc):
|
20
24
|
# This is called for every test. Only get/set command line arguments
|
21
25
|
# if the argument is specified in the list of test "fixturenames".
|
22
|
-
topol = metafunc.config.option.
|
23
|
-
traj = metafunc.config.option.
|
26
|
+
topol = metafunc.config.option.topol_path_arg
|
27
|
+
traj = metafunc.config.option.traj_path_arg
|
24
28
|
first_frame = metafunc.config.option.first_frame_arg
|
25
29
|
|
26
30
|
if all(
|
27
31
|
arg in metafunc.fixturenames
|
28
|
-
for arg in ["
|
32
|
+
for arg in ["topol_path_arg", "traj_path_arg", "first_frame_arg"]
|
29
33
|
):
|
30
34
|
if topol is None or traj is None or first_frame is None:
|
31
35
|
raise ValueError(
|
32
|
-
"Must pass all three of '--
|
33
|
-
+ "'--
|
36
|
+
"Must pass all three of '--topol_path_arg <path/to/topology>', "
|
37
|
+
+ "'--traj_path_arg <path/to/trajectory>', "
|
34
38
|
+ "'--first_frame_arg <first traj frame to compare to IMD>"
|
35
39
|
)
|
36
|
-
metafunc.parametrize("
|
37
|
-
metafunc.parametrize("
|
40
|
+
metafunc.parametrize("topol_path_arg", [topol])
|
41
|
+
metafunc.parametrize("traj_path_arg", [traj])
|
38
42
|
metafunc.parametrize("first_frame_arg", [first_frame])
|
imdclient/tests/datafiles.py
CHANGED
@@ -16,18 +16,26 @@ from pathlib import Path
|
|
16
16
|
_data_ref = resources.files("imdclient.data")
|
17
17
|
|
18
18
|
LAMMPS_TOPOL = (_data_ref / "lammps" / "md" / "lammps_topol.data").as_posix()
|
19
|
-
|
20
|
-
|
21
|
-
GROMACS_TRAJ = (
|
22
|
-
_data_ref / "gromacs" / "md" / "gromacs_v3_nst1.trr"
|
19
|
+
LAMMPS_IN_NST_1 = (
|
20
|
+
_data_ref / "lammps" / "md" / "lammps_v3_nst_1.in"
|
23
21
|
).as_posix()
|
24
|
-
|
25
|
-
_data_ref / "
|
22
|
+
LAMMPS_IN_NST_8 = (
|
23
|
+
_data_ref / "lammps" / "md" / "lammps_v3_nst_8.in"
|
26
24
|
).as_posix()
|
27
|
-
|
25
|
+
|
26
|
+
|
27
|
+
GROMACS_GRO = (_data_ref / "gromacs" / "md" / "gromacs_struct.gro").as_posix()
|
28
|
+
GROMACS_MDP_NST_1 = (
|
29
|
+
_data_ref / "gromacs" / "md" / "gromacs_v3_nst1.mdp"
|
30
|
+
).as_posix()
|
31
|
+
GROMACS_MDP_NST_8 = (
|
32
|
+
_data_ref / "gromacs" / "md" / "gromacs_v3_nst8.mdp"
|
33
|
+
).as_posix()
|
34
|
+
GROMACS_TOP = (_data_ref / "gromacs" / "md" / "gromacs_v3.top").as_posix()
|
35
|
+
|
28
36
|
NAMD_TOPOL = (_data_ref / "namd" / "md" / "alanin.pdb").as_posix()
|
29
|
-
|
30
|
-
|
37
|
+
NAMD_CONF_NST_1 = (_data_ref / "namd" / "md" / "namd_v3_nst_1.namd").as_posix()
|
38
|
+
NAMD_CONF_NST_8 = (_data_ref / "namd" / "md" / "namd_v3_nst_8.namd").as_posix()
|
31
39
|
NAMD_PARAMS = (_data_ref / "namd" / "md" / "alanin.params").as_posix()
|
32
40
|
NAMD_PSF = (_data_ref / "namd" / "md" / "alanin.psf").as_posix()
|
33
41
|
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Running simulation engines compiled for GPU acceleration from a container
|
2
|
+
|
3
|
+
Ensure [docker](https://www.docker.com/) and the [NVIDIA container toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html) are installed.
|
4
|
+
|
5
|
+
|
6
|
+
To run the container:
|
7
|
+
```bash
|
8
|
+
docker pull ghcr.io/becksteinlab/streaming-md-docker:main-Common-GPU
|
9
|
+
|
10
|
+
docker run -v $PWD/imdclient/data:/home/conda:rw -it --runtime=nvidia --gpus=all \
|
11
|
+
ghcr.io/becksteinlab/streaming-md-docker:main-Common-GPU
|
12
|
+
```
|
13
|
+
|
14
|
+
To run each simulation engine with repository simulation configurations:
|
15
|
+
```bash
|
16
|
+
cd /home/conda/namd/md
|
17
|
+
namd3 +devices 0 namd_v3.namd
|
18
|
+
|
19
|
+
cd /home/conda/gromacs/md
|
20
|
+
gmx grompp -f gromacs_v3_nst1.mdp -c gromacs_struct.gro -p gromacs_v3.top
|
21
|
+
gmx mdrun -s topol.tpr -nb gpu
|
22
|
+
|
23
|
+
cd /home/conda/lammps/md
|
24
|
+
lmp -sf gpu < lammps_v3_nst_1.in
|
25
|
+
```
|
imdclient/tests/test_gromacs.py
CHANGED
@@ -2,10 +2,16 @@ import MDAnalysis as mda
|
|
2
2
|
import pytest
|
3
3
|
import logging
|
4
4
|
from .base import IMDv3IntegrationTest
|
5
|
-
from .datafiles import
|
5
|
+
from .datafiles import (
|
6
|
+
GROMACS_GRO,
|
7
|
+
GROMACS_TOP,
|
8
|
+
GROMACS_MDP_NST_1,
|
9
|
+
GROMACS_MDP_NST_8,
|
10
|
+
)
|
11
|
+
from pathlib import Path
|
6
12
|
|
7
13
|
logger = logging.getLogger("imdclient.IMDClient")
|
8
|
-
file_handler = logging.FileHandler("
|
14
|
+
file_handler = logging.FileHandler("gromacs_test.log")
|
9
15
|
formatter = logging.Formatter(
|
10
16
|
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
11
17
|
)
|
@@ -16,18 +22,34 @@ logger.setLevel(logging.DEBUG)
|
|
16
22
|
|
17
23
|
class TestIMDv3Gromacs(IMDv3IntegrationTest):
|
18
24
|
|
25
|
+
@pytest.fixture(params=[GROMACS_MDP_NST_1, GROMACS_MDP_NST_8])
|
26
|
+
def mdp(self, request):
|
27
|
+
return request.param
|
28
|
+
|
19
29
|
@pytest.fixture()
|
20
|
-
def
|
21
|
-
return f"
|
30
|
+
def setup_command(self, mdp):
|
31
|
+
return f"gmx grompp -f {Path(mdp).name} -c {Path(GROMACS_GRO).name} -p {Path(GROMACS_TOP).name} -o topol.tpr"
|
22
32
|
|
23
33
|
@pytest.fixture()
|
24
|
-
def
|
25
|
-
return "
|
34
|
+
def simulation_command(self):
|
35
|
+
return f"gmx mdrun -s topol.tpr -o ci.trr -imdport 8888 -imdwait"
|
26
36
|
|
27
37
|
@pytest.fixture()
|
28
|
-
def
|
29
|
-
return
|
38
|
+
def input_files(self, mdp):
|
39
|
+
return [GROMACS_TOP, mdp, GROMACS_GRO]
|
40
|
+
|
41
|
+
@pytest.fixture()
|
42
|
+
def traj(self):
|
43
|
+
return "ci.trr"
|
30
44
|
|
31
45
|
@pytest.fixture()
|
32
|
-
def
|
33
|
-
return
|
46
|
+
def topol(self):
|
47
|
+
return Path(GROMACS_GRO).name
|
48
|
+
|
49
|
+
# @pytest.fixture()
|
50
|
+
# def match_string(self):
|
51
|
+
# return "IMD: Will wait until I have a connection and IMD_GO orders."
|
52
|
+
|
53
|
+
@pytest.fixture()
|
54
|
+
def first_frame(self):
|
55
|
+
return 0
|
@@ -148,3 +148,54 @@ class TestIMDClientV3:
|
|
148
148
|
client.get_imdframe()
|
149
149
|
# server should receive disconnect from client (though it doesn't have to do anything)
|
150
150
|
server.expect_packet(IMDHeaderType.IMD_DISCONNECT)
|
151
|
+
|
152
|
+
|
153
|
+
class TestIMDClientV3ContextManager:
|
154
|
+
@pytest.fixture
|
155
|
+
def port(self):
|
156
|
+
return get_free_port()
|
157
|
+
|
158
|
+
@pytest.fixture
|
159
|
+
def universe(self):
|
160
|
+
return mda.Universe(COORDINATES_TOPOLOGY, COORDINATES_H5MD)
|
161
|
+
|
162
|
+
@pytest.fixture
|
163
|
+
def imdsinfo(self):
|
164
|
+
return create_default_imdsinfo_v3()
|
165
|
+
|
166
|
+
@pytest.fixture
|
167
|
+
def server(self, universe, imdsinfo, port):
|
168
|
+
server = InThreadIMDServer(universe.trajectory)
|
169
|
+
server.set_imdsessioninfo(imdsinfo)
|
170
|
+
yield server
|
171
|
+
server.cleanup()
|
172
|
+
|
173
|
+
def test_context_manager_traj_unchanged(self, server, port, universe):
|
174
|
+
server.handshake_sequence("localhost", port, first_frame=False)
|
175
|
+
|
176
|
+
i = 0
|
177
|
+
with IMDClient(
|
178
|
+
"localhost",
|
179
|
+
port,
|
180
|
+
universe.trajectory.n_atoms,
|
181
|
+
) as client:
|
182
|
+
server.send_frames(0, 5)
|
183
|
+
while i < 5:
|
184
|
+
|
185
|
+
imdf = client.get_imdframe()
|
186
|
+
assert_allclose(universe.trajectory[i].time, imdf.time)
|
187
|
+
assert_allclose(universe.trajectory[i].dt, imdf.dt)
|
188
|
+
assert_allclose(universe.trajectory[i].data["step"], imdf.step)
|
189
|
+
assert_allclose(
|
190
|
+
universe.trajectory[i].positions, imdf.positions
|
191
|
+
)
|
192
|
+
assert_allclose(
|
193
|
+
universe.trajectory[i].velocities, imdf.velocities
|
194
|
+
)
|
195
|
+
assert_allclose(universe.trajectory[i].forces, imdf.forces)
|
196
|
+
assert_allclose(
|
197
|
+
universe.trajectory[i].triclinic_dimensions, imdf.box
|
198
|
+
)
|
199
|
+
i += 1
|
200
|
+
server.expect_packet(IMDHeaderType.IMD_DISCONNECT)
|
201
|
+
assert i == 5
|
@@ -31,7 +31,7 @@ import pytest
|
|
31
31
|
from MDAnalysis.transformations import translate
|
32
32
|
import pickle
|
33
33
|
|
34
|
-
from imdclient.
|
34
|
+
from imdclient.IMD import IMDReader
|
35
35
|
|
36
36
|
logger = logging.getLogger("imdclient.IMDClient")
|
37
37
|
file_handler = logging.FileHandler("test.log")
|
@@ -55,7 +55,7 @@ class IMDReference(BaseReference):
|
|
55
55
|
self.n_atoms = traj.n_atoms
|
56
56
|
self.prec = 3
|
57
57
|
|
58
|
-
self.trajectory = f"localhost:{self.port}"
|
58
|
+
self.trajectory = f"imd://localhost:{self.port}"
|
59
59
|
self.topology = COORDINATES_TOPOLOGY
|
60
60
|
self.changing_dimensions = True
|
61
61
|
self.reader = IMDReader
|
@@ -171,9 +171,7 @@ class TestIMDReaderBaseAPI(MultiframeReaderTest):
|
|
171
171
|
decimal=ref.prec,
|
172
172
|
)
|
173
173
|
|
174
|
-
@pytest.mark.skip(
|
175
|
-
reason="Stream-based reader can only be read iteratively"
|
176
|
-
)
|
174
|
+
@pytest.mark.skip(reason="Stream-based reader can only be read iteratively")
|
177
175
|
def test_changing_dimensions(self, ref, reader):
|
178
176
|
if ref.changing_dimensions:
|
179
177
|
reader.rewind()
|
@@ -585,7 +583,7 @@ class TestStreamIteration:
|
|
585
583
|
server.set_imdsessioninfo(imdsinfo)
|
586
584
|
server.handshake_sequence("localhost", port, first_frame=True)
|
587
585
|
reader = IMDReader(
|
588
|
-
f"localhost:{port}",
|
586
|
+
f"imd://localhost:{port}",
|
589
587
|
n_atoms=universe.trajectory.n_atoms,
|
590
588
|
)
|
591
589
|
server.send_frames(1, 5)
|
@@ -642,3 +640,19 @@ class TestStreamIteration:
|
|
642
640
|
with pytest.raises(RuntimeError):
|
643
641
|
for ts in sub_sliced_reader:
|
644
642
|
pass
|
643
|
+
|
644
|
+
|
645
|
+
def test_n_atoms_mismatch():
|
646
|
+
universe = mda.Universe(COORDINATES_TOPOLOGY, COORDINATES_H5MD)
|
647
|
+
port = get_free_port()
|
648
|
+
server = InThreadIMDServer(universe.trajectory)
|
649
|
+
server.set_imdsessioninfo(create_default_imdsinfo_v3())
|
650
|
+
server.handshake_sequence("localhost", port, first_frame=True)
|
651
|
+
with pytest.raises(
|
652
|
+
EOFError,
|
653
|
+
match="IMDProducer: Expected n_atoms value 6, got 5. Ensure you are using the correct topology file.",
|
654
|
+
):
|
655
|
+
IMDReader(
|
656
|
+
f"imd://localhost:{port}",
|
657
|
+
n_atoms=universe.trajectory.n_atoms + 1,
|
658
|
+
)
|
imdclient/tests/test_lammps.py
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
import MDAnalysis as mda
|
2
2
|
import pytest
|
3
|
+
from pathlib import Path
|
3
4
|
import logging
|
4
5
|
from .base import IMDv3IntegrationTest
|
5
|
-
from .datafiles import
|
6
|
+
from .datafiles import LAMMPS_TOPOL, LAMMPS_IN_NST_1, LAMMPS_IN_NST_8
|
6
7
|
|
7
8
|
logger = logging.getLogger("imdclient.IMDClient")
|
8
|
-
file_handler = logging.FileHandler("
|
9
|
+
file_handler = logging.FileHandler("lammps_test.log")
|
9
10
|
formatter = logging.Formatter(
|
10
11
|
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
11
12
|
)
|
@@ -16,23 +17,67 @@ logger.setLevel(logging.DEBUG)
|
|
16
17
|
|
17
18
|
class TestIMDv3Lammps(IMDv3IntegrationTest):
|
18
19
|
|
20
|
+
@pytest.fixture(params=[LAMMPS_IN_NST_1, LAMMPS_IN_NST_8])
|
21
|
+
def inp(self, request):
|
22
|
+
return request.param
|
23
|
+
|
24
|
+
@pytest.fixture()
|
25
|
+
def simulation_command(self, inp):
|
26
|
+
return f"lmp < {Path(inp).name}"
|
27
|
+
|
28
|
+
@pytest.fixture()
|
29
|
+
def topol(self):
|
30
|
+
return Path(LAMMPS_TOPOL).name
|
31
|
+
|
32
|
+
@pytest.fixture()
|
33
|
+
def traj(self):
|
34
|
+
return "lammps_trj.h5md"
|
35
|
+
|
19
36
|
@pytest.fixture()
|
20
|
-
def
|
21
|
-
return
|
37
|
+
def input_files(self, inp):
|
38
|
+
return [inp, LAMMPS_TOPOL]
|
39
|
+
|
40
|
+
# @pytest.fixture()
|
41
|
+
# def match_string(self):
|
42
|
+
# return "Waiting for IMD connection on port 8888"
|
22
43
|
|
23
44
|
@pytest.fixture()
|
24
|
-
def
|
25
|
-
|
45
|
+
def first_frame(self, inp):
|
46
|
+
if inp == LAMMPS_IN_NST_1:
|
47
|
+
return 1
|
48
|
+
else:
|
49
|
+
return 0
|
26
50
|
|
51
|
+
# Not present in lammps-produced H5MD
|
27
52
|
@pytest.fixture()
|
28
|
-
def
|
29
|
-
return
|
53
|
+
def comp_dt(self):
|
54
|
+
return False
|
30
55
|
|
56
|
+
# This must wait until after imd stream has ended
|
31
57
|
@pytest.fixture()
|
32
|
-
def
|
33
|
-
|
34
|
-
|
35
|
-
|
58
|
+
def true_u(self, topol, traj, imd_u, tmp_path):
|
59
|
+
u = mda.Universe(
|
60
|
+
(tmp_path / topol),
|
61
|
+
(tmp_path / traj),
|
36
62
|
atom_style="id type x y z",
|
37
63
|
convert_units=False,
|
38
64
|
)
|
65
|
+
yield u
|
66
|
+
|
67
|
+
@pytest.fixture()
|
68
|
+
def imd_u(self, docker_client, topol, tmp_path, port):
|
69
|
+
u = mda.Universe(
|
70
|
+
(tmp_path / topol),
|
71
|
+
f"imd://localhost:{port}",
|
72
|
+
atom_style="id type x y z",
|
73
|
+
)
|
74
|
+
with mda.Writer(
|
75
|
+
(tmp_path / "imd.trr").as_posix(), u.trajectory.n_atoms
|
76
|
+
) as w:
|
77
|
+
for ts in u.trajectory:
|
78
|
+
w.write(u.atoms)
|
79
|
+
yield mda.Universe(
|
80
|
+
(tmp_path / topol),
|
81
|
+
(tmp_path / "imd.trr"),
|
82
|
+
atom_style="id type x y z",
|
83
|
+
)
|