Skip to content

IMDv2 generic support implementation with tests - #141

Open
amruthesht wants to merge 38 commits into
mainfrom
imdv2-support
Open

amruthesht wants to merge 38 commits into
mainfrom
imdv2-support

Conversation

@amruthesht

@amruthesht amruthesht commented Jun 1, 2026 •

Copy link
Copy Markdown
Contributor

This PR provides generic IMDv2 support for handling various v2 streaming scenarios in imdclient

Fixes #140 , #143

Changes made in this Pull Request:

Note: IMDv2 in GROMACS seems to expects transmission rate from the user via the client, as discussed in #143
It ignores IMD-nst in the *.mdp file. Thus the IMDClient object was modified to send IMD_TRATE right after IMD_GO as set in the object initiation when using v2.

PR Checklist

  • Tests?
  • Docs?
  • CHANGELOG updated?
  • Issue raised/referenced?

@codecov

codecov Bot commented Jun 1, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.09%. Comparing base (b243331) to head (406d8bb).

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR extends imdclient to handle more IMDv2 streaming patterns (notably variable energy-packet ordering) and adds/updates integration tests and simulation inputs to validate IMDv2 behavior across supported engines.

Changes:

  • Update IMDv2 frame parsing to tolerate multiple leading energy packets before coordinates and to reuse cached energies when energies are omitted.
  • Add IMDv2 integration test coverage alongside existing IMDv3 tests for NAMD, GROMACS, and LAMMPS.
  • Add new IMDv2 engine input/config files and rename/refactor test datafile constants to separate v2/v3 variants.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
imdclient/IMDClient.py Adjust IMDv2 producer parsing to handle multiple/optional energy packets before coordinates.
imdclient/tests/base.py Refactor integration test base class and add an IMDv2-specific integration test class.
imdclient/tests/test_namd.py Split shared NAMD fixtures and add IMDv2 + IMDv3 integration test classes with version-specific inputs.
imdclient/tests/test_lammps.py Split shared LAMMPS fixtures and add IMDv2 + IMDv3 integration test classes with version-specific inputs.
imdclient/tests/test_gromacs.py Split shared GROMACS fixtures and add IMDv2 + IMDv3 integration test classes with version-specific inputs.
imdclient/tests/minimalreader.py Handle missing box data when converting to MDAnalysis dimensions during stream processing.
imdclient/tests/datafiles.py Rename/split datafile constants to explicitly distinguish v2 vs v3 simulation inputs.
imdclient/data/namd/md/namd_v2_nst_1.namd Add NAMD IMDv2 test configuration (NST=1).
imdclient/data/namd/md/namd_v2_nst_8.namd Add NAMD IMDv2 test configuration (NST=8).
imdclient/data/lammps/md/lammps_v2_nst_1.in Add LAMMPS IMDv2 test input (NST=1).
imdclient/data/lammps/md/lammps_v2_nst_8.in Add LAMMPS IMDv2 test input (NST=8).
imdclient/data/lammps/md/lammps_v3_nst_1.in Expand LAMMPS IMDv3 fix options to explicitly enable time/box/coords/vel/forces.
imdclient/data/lammps/md/lammps_v3_nst_8.in Expand LAMMPS IMDv3 fix options to explicitly enable time/box/coords/vel/forces.
imdclient/data/gromacs/md/gromacs_v2_nst1.mdp Add GROMACS IMDv2 test MDP (NST=1).
imdclient/data/gromacs/md/gromacs_v2_nst8.mdp Add GROMACS IMDv2 test MDP (NST=8).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread imdclient/IMDClient.py Resolved
Comment thread imdclient/tests/test_lammps.py Resolved
Comment thread imdclient/tests/base.py Resolved
Comment thread imdclient/tests/minimalreader.py Resolved
Comment thread imdclient/IMDClient.py Resolved
@amruthesht
amruthesht force-pushed the imdv2-support branch 2 times, most recently from fca1842 to bd67a88 Compare June 5, 2026 19:35

@orbeckst orbeckst left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

As discussed in meeting, wrap the GROMACS streamed coordinates into the unit cell by

  1. extracting the ts.dimensions from the saved trajectory
  2. create two on-the-fly transformations
  3. use the transformations with the in-memory universe that you build with the numpy array of the IMD data

This should generate an in-memory trajectory of wrapped coordinates.

@orbeckst orbeckst left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I only managed a partial review (code, not tests). The fact that it works is great!

Do we use the the same IMDClient for v3 and v2? Do any of the changes affect v3?

My primary comments so far are just all related to docs.

We need to document the v2 capabilities. Can you create a protocol page for the v2 format as we understand it (then we have a v2 and a v3 page). On the IMDClient docs page we should also have a section on v2 that lists any shortcomings; some out of our control (no dimensions, no v/f), some our implementation (energies can be out of sync as I understand it).

Add an entry to CHANGELOG. This will have to be 0.3.0.

Comment thread imdclient/IMDClient.py Outdated
IMD transmission rate to be set after client send go signal.
This parameter is only set to the server when using IMDv2. Default behavior is to not set the transmission rate.
This parameter is useful when running GROMACS with IMDv2, where transmission rate can only be set via the client.
IMDv2 implementations in LAMMPS and NAMD support setting the transmission rate via relevant input file parameters.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

  1. Add an definition of what "IMD transmission rate" is, e.g., a which integrator step IMD packages are sent. Include a link to https://imdclient.readthedocs.io/en/latest/protocol_v3.html#transmission-rate
IMD :ref:`transmission rate <transmission-rate>` to be set after client send go signal.
  1. State what the default value for IMDv2 in GROMACS is.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does GROMACS default to transmission_rate = 1? I.e., is it safe for users to leave it as None or will it hang their simulations?

You could add a note box

.. warning::
   When using GROMACS with IMDv2, users should set `transmission_rate` explicitly.
   Otherwise the GROMACS default of 1 will be chosen. This default setting will send 
   every integrator time step and may impact performance substantially.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

And add an indication in which version this option was added

transmission_rate : int, optional [``None``]
        IMD transmission rate to be set after client send go signal. 
        This parameter is only set to the server when using IMDv2. Defaul...
        ...
        IMDv2 implementations in LAMMPS and NAMD support setting the transmission rate via relevant input file parameters.

        .. versionadded:: 0.3.0

Check that it looks right when the docs are rendered.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Modified and added based on IMDv2 behavior in GROMACS, LAMMPS, and NAMD

Comment thread imdclient/IMDClient.py
This parameter is useful when running GROMACS with IMDv2, where transmission rate can only be set via the client.
IMDv2 implementations in LAMMPS and NAMD support setting the transmission rate via relevant input file parameters.
**kwargs : dict (optional)
Additional keyword arguments to pass to the :class:`BaseIMDProducer` and :class:`IMDFrameBuffer`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Add a

.. versionchanged:: 0.3.0
   Added capability to process IMDv2 protocol streams.

(Note: need two blank lines above)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done!

Comment thread imdclient/IMDClient.py Resolved
Comment thread imdclient/IMDClient.py
header = self._get_header()
if header.type == IMDHeaderType.IMD_ENERGIES and header.length == 1:
leading_energies = 0
while header.type == IMDHeaderType.IMD_ENERGIES and header.length == 1:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

When do you get multiple energy packets in sequence? Only in v2?

Add a note that energy handling in v2 can miss something/report out of sync.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done!

Comment thread imdclient/IMDClient.py
Comment on lines -551 to +568
# Either receive energies + positions or just positions
# Consume any leading energy packets first, then handle positions.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this change how v3 streams are processed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No, this is only implemented under IMDProducerV2

Comment thread imdclient/IMDClient.py Outdated

self._go()

if transmission_rate is not None and self._imdsinfo.version == 2:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

If version == 3 and transmission rate is set, issue a warning that the kwarg is ignored, for least surprise to user

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

(I know the docs already say this, so if you think that's sufficient, feel free to ignore , just thinking of principle of least surprise)

Comment thread imdclient/IMDClient.py Resolved
Comment thread imdclient/IMDClient.py Resolved
Comment thread imdclient/IMDClient.py Resolved
@orbeckst orbeckst mentioned this pull request Jun 27, 2026
2 tasks done
@orbeckst

Copy link
Copy Markdown
Member

I released 0.2.4 #146 so please create the 0.3.0 section in the CHANGELOG when you add your entry.

@pytest.fixture()
def first_frame(self):
return 0
def imd_nst(self, mdp):
return request.param

@pytest.fixture()
def first_frame(self, inp):
return request.param

@pytest.fixture()
def first_frame(self, inp):
# def match_string(self):
# return "IMD: Will wait until I have a connection and IMD_GO orders."

class TestIMDv3Gromacs(IMDGromacsTest, IMDv3IntegrationTest):
return request.param


class TestIMDv2Gromacs(IMDGromacsTest, IMDv2IntegrationTest):
yield u


class TestIMDv3Lammps(IMDLammpsTest, IMDv3IntegrationTest):
return 0


class TestIMDv2Lammps(IMDLammpsTest, IMDv2IntegrationTest):
return 0


class TestIMDv3NAMD(IMDNAMDTest, IMDv3IntegrationTest):
)


class TestIMDv2NAMD(IMDNAMDTest, IMDv2IntegrationTest):
@orbeckst

orbeckst commented Sep 4, 2026

Copy link
Copy Markdown
Member

Can you please update to sync it with the base branch? Thanks!

Will try to look at it over the weekend.

@orbeckst orbeckst left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Add entry to CHANGELOG and write somewhere in the docs explicitly that we can also work with v2. Mention why this is not great for analysis.

gen_vel = no
IMD-group = System
IMD-nst = 8
IMD-version = 2

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This will only work with our patched version of GROMACS that also speaks v3. I think you should leave it out.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added new docker image support for vanilla gromacs versions as a PR. once mereged these tests would tests imdv2 support for imdclient using appropriate version of all 3 MD engines (GROMACS, LAMMPS and NAMD)

@orbeckst

Copy link
Copy Markdown
Member

As discussed: use a vanilla version of GROMACS (eg 2025 from conda-forge) to test v2, too.

@orbeckst

Copy link
Copy Markdown
Member

The actual MD engine tests are failing, eg https://github.com/Becksteinlab/imdclient/actions/runs/37972189712/job/113961342160?pr=141 with

E           ConnectionRefusedError: IMDClient: Connection to localhost:56093 refused

What's the issue?

@orbeckst

Copy link
Copy Markdown
Member

From discussion: first need new docker images Becksteinlab/streaming-md-docker#32

@orbeckst

orbeckst commented Nov 5, 2026

Copy link
Copy Markdown
Member

We have new images (I fixed the deployment workflow, see also Becksteinlab/streaming-md-docker#34 ). If this works here now, then we should be good.

@orbeckst

orbeckst commented Nov 6, 2026

Copy link
Copy Markdown
Member

@amruthesht the MD engine tests fail with multiple Connection to localhost:...... refused errors. This occurs for GROMACS, NAMD, and LAMMPS. Eg all GROMACS tests failed

=========================== short test summary info ============================
FAILED imdclient/tests/test_gromacs.py::TestIMDv3Gromacs::test_continue_after_disconnect[/home/runner/work/imdclient/imdclient/imdclient/data/gromacs/md/gromacs_v3_nst1.mdp] - ConnectionRefusedError: IMDClient: Connection to localhost:56499 refused
FAILED imdclient/tests/test_gromacs.py::TestIMDv3Gromacs::test_continue_after_disconnect[/home/runner/work/imdclient/imdclient/imdclient/data/gromacs/md/gromacs_v3_nst8.mdp] - ConnectionRefusedError: IMDClient: Connection to localhost:60221 refused
FAILED imdclient/tests/test_gromacs.py::TestIMDv3Gromacs::test_wait_after_disconnect[/home/runner/work/imdclient/imdclient/imdclient/data/gromacs/md/gromacs_v3_nst1.mdp] - ConnectionRefusedError: IMDClient: Connection to localhost:37825 refused
FAILED imdclient/tests/test_gromacs.py::TestIMDv3Gromacs::test_wait_after_disconnect[/home/runner/work/imdclient/imdclient/imdclient/data/gromacs/md/gromacs_v3_nst8.mdp] - ConnectionRefusedError: IMDClient: Connection to localhost:34553 refused
ERROR imdclient/tests/test_gromacs.py::TestIMDv3Gromacs::test_compare_imd_to_true_traj[/home/runner/work/imdclient/imdclient/imdclient/data/gromacs/md/gromacs_v3_nst1.mdp] - ConnectionRefusedError: IMDClient: Connection to localhost:35123 refused
ERROR imdclient/tests/test_gromacs.py::TestIMDv3Gromacs::test_compare_imd_to_true_traj[/home/runner/work/imdclient/imdclient/imdclient/data/gromacs/md/gromacs_v3_nst8.mdp] - ConnectionRefusedError: IMDClient: Connection to localhost:47581 refused
ERROR imdclient/tests/test_gromacs.py::TestIMDv2Gromacs::test_compare_imd_to_true_traj[/home/runner/work/imdclient/imdclient/imdclient/data/gromacs/md/gromacs_v2_nst1.mdp] - ConnectionRefusedError: IMDClient: Connection to localhost:46023 refused
ERROR imdclient/tests/test_gromacs.py::TestIMDv2Gromacs::test_compare_imd_to_true_traj[/home/runner/work/imdclient/imdclient/imdclient/data/gromacs/md/gromacs_v2_nst8.mdp] - ConnectionRefusedError: IMDClient: Connection to localhost:55955 refused
============== 4 failed, 1 warning, 4 errors in 252.62s (0:04:12) ==============

and LAMMPS

=========================== short test summary info ============================
ERROR imdclient/tests/test_lammps.py::TestIMDv2Lammps::test_compare_imd_to_true_traj[/home/runner/work/imdclient/imdclient/imdclient/data/lammps/md/lammps_v2_nst_1.in] - ConnectionRefusedError: IMDClient: Connection to localhost:35983 refused
ERROR imdclient/tests/test_lammps.py::TestIMDv2Lammps::test_compare_imd_to_true_traj[/home/runner/work/imdclient/imdclient/imdclient/data/lammps/md/lammps_v2_nst_8.in] - ConnectionRefusedError: IMDClient: Connection to localhost:33241 refused
============== 6 passed, 1 warning, 2 errors in 437.71s (0:07:17) ==============

and NAMD

=========================== short test summary info ============================
FAILED imdclient/tests/test_namd.py::TestIMDv3NAMD::test_wait_after_disconnect[/home/runner/work/imdclient/imdclient/imdclient/data/namd/md/namd_v3_nst_1.namd] - ConnectionRefusedError: IMDClient: Connection to localhost:44577 refused
FAILED imdclient/tests/test_namd.py::TestIMDv3NAMD::test_compare_imd_to_true_traj_forces[/home/runner/work/imdclient/imdclient/imdclient/data/namd/md/namd_v3_nst_1.namd] - AssertionError: Arrays are not almost equal.
FAILED imdclient/tests/test_namd.py::TestIMDv3NAMD::test_compare_imd_to_true_traj_forces[/home/runner/work/imdclient/imdclient/imdclient/data/namd/md/namd_v3_nst_8.namd] - AssertionError: Arrays are not almost equal.
ERROR imdclient/tests/test_namd.py::TestIMDv2NAMD::test_compare_imd_to_true_traj[/home/runner/work/imdclient/imdclient/imdclient/data/namd/md/namd_v2_nst_1.namd] - ConnectionRefusedError: IMDClient: Connection to localhost:48575 refused
ERROR imdclient/tests/test_namd.py::TestIMDv2NAMD::test_compare_imd_to_true_traj[/home/runner/work/imdclient/imdclient/imdclient/data/namd/md/namd_v2_nst_8.namd] - ConnectionRefusedError: IMDClient: Connection to localhost:48851 refused
======== 3 failed, 7 passed, 19 warnings, 2 errors in 561.34s (0:09:21) ========

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

IMDv2 in GROMACS requires client to set trate IMDv2 support and tests for receiving positions Add tests for IMDv2 streams

4 participants