imdclient 0.1.2__tar.gz → 0.1.4__tar.gz

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.
Files changed (79) hide show
  1. imdclient-0.1.4/LICENSE +5 -0
  2. imdclient-0.1.4/PKG-INFO +132 -0
  3. {imdclient-0.1.2 → imdclient-0.1.4}/README.md +10 -5
  4. imdclient-0.1.2/imdclient/IMDREADER.py → imdclient-0.1.4/imdclient/IMD.py +5 -4
  5. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/IMDClient.py +118 -15
  6. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/IMDProtocol.py +1 -0
  7. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/data/gromacs/md/gromacs_v3_nst1.mdp +3 -3
  8. imdclient-0.1.4/imdclient/data/gromacs/md/gromacs_v3_nst8.mdp +58 -0
  9. imdclient-0.1.2/imdclient/data/lammps/md/lammps_v3.in → imdclient-0.1.4/imdclient/data/lammps/md/lammps_v3_nst_1.in +3 -3
  10. imdclient-0.1.4/imdclient/data/lammps/md/lammps_v3_nst_8.in +71 -0
  11. imdclient-0.1.2/imdclient/data/namd/md/namd_v3.namd → imdclient-0.1.4/imdclient/data/namd/md/namd_v3_nst_1.namd +17 -5
  12. imdclient-0.1.4/imdclient/data/namd/md/namd_v3_nst_8.namd +59 -0
  13. imdclient-0.1.4/imdclient/tests/base.py +256 -0
  14. imdclient-0.1.4/imdclient/tests/conftest.py +3 -0
  15. imdclient-0.1.4/imdclient/tests/datafiles.py +57 -0
  16. imdclient-0.1.4/imdclient/tests/docker_testing/docker.md +25 -0
  17. imdclient-0.1.4/imdclient/tests/hpc_testing/gromacs/README.md +112 -0
  18. imdclient-0.1.4/imdclient/tests/hpc_testing/gromacs/gmx_gpu_test.mdp +58 -0
  19. imdclient-0.1.4/imdclient/tests/hpc_testing/gromacs/gmx_gpu_test.top +11764 -0
  20. imdclient-0.1.4/imdclient/tests/hpc_testing/gromacs/struct.gro +21151 -0
  21. imdclient-0.1.4/imdclient/tests/hpc_testing/gromacs/validate_gmx.sh +90 -0
  22. imdclient-0.1.4/imdclient/tests/hpc_testing/lammps/README.md +62 -0
  23. imdclient-0.1.4/imdclient/tests/hpc_testing/lammps/lammps_v3_nst_1.in +71 -0
  24. imdclient-0.1.4/imdclient/tests/hpc_testing/lammps/topology_after_min.data +8022 -0
  25. imdclient-0.1.4/imdclient/tests/hpc_testing/lammps/validate_lmp.sh +66 -0
  26. imdclient-0.1.4/imdclient/tests/hpc_testing/namd/README.md +73 -0
  27. imdclient-0.1.4/imdclient/tests/hpc_testing/namd/alanin.params +402 -0
  28. imdclient-0.1.4/imdclient/tests/hpc_testing/namd/alanin.pdb +77 -0
  29. imdclient-0.1.4/imdclient/tests/hpc_testing/namd/alanin.psf +206 -0
  30. imdclient-0.1.4/imdclient/tests/hpc_testing/namd/namd_v3_nst_1.namd +59 -0
  31. imdclient-0.1.4/imdclient/tests/hpc_testing/namd/validate_namd.sh +71 -0
  32. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/tests/server.py +2 -11
  33. imdclient-0.1.4/imdclient/tests/test_gromacs.py +55 -0
  34. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/tests/test_imdclient.py +69 -0
  35. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/tests/test_imdreader.py +74 -1
  36. imdclient-0.1.4/imdclient/tests/test_lammps.py +83 -0
  37. imdclient-0.1.4/imdclient/tests/test_manual.py +249 -0
  38. imdclient-0.1.4/imdclient/tests/test_namd.py +125 -0
  39. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/tests/test_stream_analysis.py +1 -1
  40. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/tests/utils.py +0 -1
  41. imdclient-0.1.4/imdclient.egg-info/PKG-INFO +132 -0
  42. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient.egg-info/SOURCES.txt +23 -8
  43. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient.egg-info/requires.txt +1 -0
  44. {imdclient-0.1.2 → imdclient-0.1.4}/pyproject.toml +1 -0
  45. imdclient-0.1.2/LICENSE +0 -674
  46. imdclient-0.1.2/PKG-INFO +0 -795
  47. imdclient-0.1.2/imdclient/data/gromacs/md/gromacs_v3_nst1.tpr +0 -0
  48. imdclient-0.1.2/imdclient/data/gromacs/md/gromacs_v3_nst1.trr +0 -0
  49. imdclient-0.1.2/imdclient/data/lammps/md/lammps_trj.h5md +0 -0
  50. imdclient-0.1.2/imdclient/data/namd/md/alanin.dcd +0 -0
  51. imdclient-0.1.2/imdclient/tests/base.py +0 -122
  52. imdclient-0.1.2/imdclient/tests/conftest.py +0 -42
  53. imdclient-0.1.2/imdclient/tests/datafiles.py +0 -34
  54. imdclient-0.1.2/imdclient/tests/test_gromacs.py +0 -33
  55. imdclient-0.1.2/imdclient/tests/test_lammps.py +0 -38
  56. imdclient-0.1.2/imdclient/tests/test_manual.py +0 -91
  57. imdclient-0.1.2/imdclient/tests/test_namd.py +0 -38
  58. imdclient-0.1.2/imdclient.egg-info/PKG-INFO +0 -795
  59. {imdclient-0.1.2 → imdclient-0.1.4}/AUTHORS.md +0 -0
  60. {imdclient-0.1.2 → imdclient-0.1.4}/CHANGELOG.md +0 -0
  61. {imdclient-0.1.2 → imdclient-0.1.4}/CODE_OF_CONDUCT.md +0 -0
  62. {imdclient-0.1.2 → imdclient-0.1.4}/MANIFEST.in +0 -0
  63. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/__init__.py +0 -0
  64. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/backends.py +0 -0
  65. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/data/__init__.py +0 -0
  66. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/data/gromacs/md/gromacs_struct.gro +0 -0
  67. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/data/gromacs/md/gromacs_v3.top +0 -0
  68. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/data/lammps/md/lammps_topol.data +0 -0
  69. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/data/namd/md/alanin.params +0 -0
  70. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/data/namd/md/alanin.pdb +0 -0
  71. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/data/namd/md/alanin.psf +0 -0
  72. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/results.py +0 -0
  73. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/streamanalysis.py +0 -0
  74. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/streambase.py +0 -0
  75. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/tests/__init__.py +0 -0
  76. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient/utils.py +0 -0
  77. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient.egg-info/dependency_links.txt +0 -0
  78. {imdclient-0.1.2 → imdclient-0.1.4}/imdclient.egg-info/top_level.txt +0 -0
  79. {imdclient-0.1.2 → imdclient-0.1.4}/setup.cfg +0 -0
@@ -0,0 +1,5 @@
1
+ Copyright 2024 Lawson Woods
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
@@ -0,0 +1,132 @@
1
+ Metadata-Version: 2.1
2
+ Name: imdclient
3
+ Version: 0.1.4
4
+ Summary: Receiver for IMD v2 and v3 data from simulation engines like Gromacs, LAMMPS, and NAMD
5
+ Author-email: Lawson <ljwoods2@asu.edu>
6
+ Maintainer-email: Lawson <ljwoods2@asu.edu>
7
+ License: Copyright 2024 Lawson Woods
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12
+ Keywords: molecular simulations
13
+ Requires-Python: >=3.9
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ License-File: AUTHORS.md
17
+ Requires-Dist: MDAnalysis>=2.7.0
18
+ Provides-Extra: test
19
+ Requires-Dist: pytest>=6.0; extra == "test"
20
+ Requires-Dist: pytest-xdist>=2.5; extra == "test"
21
+ Requires-Dist: pytest-cov>=3.0; extra == "test"
22
+ Requires-Dist: MDAnalysisTests>=2.7.0; extra == "test"
23
+ Requires-Dist: docker-py; extra == "test"
24
+ Provides-Extra: doc
25
+ Requires-Dist: sphinx; extra == "doc"
26
+ Requires-Dist: sphinx_rtd_theme; extra == "doc"
27
+
28
+ IMDClient
29
+ ==============================
30
+ [//]: # (Badges)
31
+
32
+ | **Latest release** | [![Last release tag][badge_release]][url_latest_release] ![GitHub commits since latest release (by date) for a branch][badge_commits_since] [![Documentation Status][badge_docs]][url_docs]|
33
+ | :----------------- | :------- |
34
+ | **Status** | [![GH Actions Status][badge_actions]][url_actions] [![codecov][badge_codecov]][url_codecov] |
35
+ | **Community** | [![License: MIT][badge_license]][url_license] [![Powered by MDAnalysis][badge_mda]][url_mda]|
36
+
37
+ [badge_actions]: https://github.com/becksteinlab/imdclient/actions/workflows/gh-ci.yaml/badge.svg
38
+ [badge_codecov]: https://codecov.io/gh/becksteinlab/imdclient/branch/main/graph/badge.svg
39
+ [badge_commits_since]: https://img.shields.io/github/commits-since/becksteinlab/imdclient/latest
40
+ [badge_docs]: https://readthedocs.org/projects/imdclient/badge/?version=latest
41
+ [badge_license]: https://img.shields.io/badge/License-MIT-blue.svg
42
+ [badge_mda]: https://img.shields.io/badge/powered%20by-MDAnalysis-orange.svg?logoWidth=16&logo=data:image/x-icon;base64,AAABAAEAEBAAAAEAIAAoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJD+XwCY/fEAkf3uAJf97wGT/a+HfHaoiIWE7n9/f+6Hh4fvgICAjwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACT/yYAlP//AJ///wCg//8JjvOchXly1oaGhv+Ghob/j4+P/39/f3IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJH8aQCY/8wAkv2kfY+elJ6al/yVlZX7iIiI8H9/f7h/f38UAAAAAAAAAAAAAAAAAAAAAAAAAAB/f38egYF/noqAebF8gYaagnx3oFpUUtZpaWr/WFhY8zo6OmT///8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgICAn46Ojv+Hh4b/jouJ/4iGhfcAAADnAAAA/wAAAP8AAADIAAAAAwCj/zIAnf2VAJD/PAAAAAAAAAAAAAAAAICAgNGHh4f/gICA/4SEhP+Xl5f/AwMD/wAAAP8AAAD/AAAA/wAAAB8Aov9/ALr//wCS/Z0AAAAAAAAAAAAAAACBgYGOjo6O/4mJif+Pj4//iYmJ/wAAAOAAAAD+AAAA/wAAAP8AAABhAP7+FgCi/38Axf4fAAAAAAAAAAAAAAAAiIiID4GBgYKCgoKogoB+fYSEgZhgYGDZXl5e/m9vb/9ISEjpEBAQxw8AAFQAAAAAAAAANQAAADcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjo6Mb5iYmP+cnJz/jY2N95CQkO4pKSn/AAAA7gAAAP0AAAD7AAAAhgAAAAEAAAAAAAAAAACL/gsAkv2uAJX/QQAAAAB9fX3egoKC/4CAgP+NjY3/c3Nz+wAAAP8AAAD/AAAA/wAAAPUAAAAcAAAAAAAAAAAAnP4NAJL9rgCR/0YAAAAAfX19w4ODg/98fHz/i4uL/4qKivwAAAD/AAAA/wAAAP8AAAD1AAAAGwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALGxsVyqqqr/mpqa/6mpqf9KSUn/AAAA5QAAAPkAAAD5AAAAhQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADkUFBSuZ2dn/3V1df8uLi7bAAAATgBGfyQAAAA2AAAAMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0AAADoAAAA/wAAAP8AAAD/AAAAWgC3/2AAnv3eAJ/+dgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9AAAA/wAAAP8AAAD/AAAA/wAKDzEAnP3WAKn//wCS/OgAf/8MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIQAAANwAAADtAAAA7QAAAMAAABUMAJn9gwCe/e0Aj/2LAP//AQAAAAAAAAAA
43
+ [badge_release]: https://img.shields.io/github/release-pre/becksteinlab/imdclient.svg
44
+ [url_actions]: https://github.com/becksteinlab/imdclient/actions?query=branch%3Amain+workflow%3Agh-ci
45
+ [url_codecov]: https://codecov.io/gh/becksteinlab/imdclient/branch/main
46
+ [url_docs]: https://imdclient.readthedocs.io/en/latest/?badge=latest
47
+ [url_latest_release]: https://github.com/becksteinlab/imdclient/releases
48
+ [url_license]: https://opensource.org/license/mit
49
+ [url_mda]: https://www.mdanalysis.org
50
+
51
+ Receiver for [IMDv3 protocol](https://imdclient.readthedocs.io/en/latest/protocol_v3.html) from simulation engines like Gromacs, LAMMPS, and NAMD.
52
+
53
+ IMDClient is bound by a [Code of Conduct](https://github.com/becksteinlab/imdreader/blob/main/CODE_OF_CONDUCT.md).
54
+
55
+ ### Installation
56
+
57
+ IMDClient is available via PyPi and can be installed with pip:
58
+ ```bash
59
+ pip install imdclient
60
+ ```
61
+
62
+ To build IMDClient from source,
63
+ we highly recommend using virtual environments.
64
+ If possible, we strongly recommend that you use
65
+ [Anaconda](https://docs.conda.io/en/latest/) as your package manager.
66
+ Below we provide instructions both for `conda` and
67
+ for `pip`.
68
+
69
+ #### With conda
70
+
71
+ Ensure that you have [conda](https://docs.conda.io/projects/conda/en/latest/user-guide/install/index.html) installed.
72
+
73
+ Create a virtual environment and activate it:
74
+
75
+ ```
76
+ conda create --name imdclient
77
+ conda activate imdclient
78
+ ```
79
+
80
+ <!-- Install the development and documentation dependencies:
81
+
82
+ ```
83
+ conda env update --name imdreader --file devtools/conda-envs/test_env.yaml
84
+ conda env update --name imdreader --file docs/requirements.yaml
85
+ ``` -->
86
+
87
+ Build this package from source:
88
+
89
+ ```
90
+ pip install -e .
91
+ ```
92
+
93
+ If you want to update your dependencies (which can be risky!), run:
94
+
95
+ ```
96
+ conda update --all
97
+ ```
98
+
99
+ And when you are finished, you can exit the virtual environment with:
100
+
101
+ ```
102
+ conda deactivate
103
+ ```
104
+
105
+ #### With pip
106
+
107
+ To build the package from source, run:
108
+
109
+ ```
110
+ pip install .
111
+ ```
112
+
113
+ If you want to create a development environment, install
114
+ the dependencies required for tests and docs with:
115
+
116
+ ```
117
+ pip install ".[test,doc]"
118
+ ```
119
+
120
+ ### Copyright
121
+
122
+ The IMDClient source code is hosted at https://github.com/becksteinlab/imdclient
123
+ and is available under the MIT license (see the file [LICENSE](https://github.com/becksteinlab/imdclient/blob/main/LICENSE)).
124
+
125
+ Copyright (c) 2024, Lawson
126
+
127
+
128
+ #### Acknowledgements
129
+
130
+ Project based on the
131
+ [MDAnalysis Cookiecutter](https://github.com/MDAnalysis/cookiecutter-mda) version 0.1.
132
+ <!-- Please cite [MDAnalysis](https://github.com/MDAnalysis/mdanalysis#citation) when using IMDReader in published work. -->
@@ -5,28 +5,33 @@ IMDClient
5
5
  | **Latest release** | [![Last release tag][badge_release]][url_latest_release] ![GitHub commits since latest release (by date) for a branch][badge_commits_since] [![Documentation Status][badge_docs]][url_docs]|
6
6
  | :----------------- | :------- |
7
7
  | **Status** | [![GH Actions Status][badge_actions]][url_actions] [![codecov][badge_codecov]][url_codecov] |
8
- | **Community** | [![License: GPL v3][badge_license]][url_license] [![Powered by MDAnalysis][badge_mda]][url_mda]|
8
+ | **Community** | [![License: MIT][badge_license]][url_license] [![Powered by MDAnalysis][badge_mda]][url_mda]|
9
9
 
10
10
  [badge_actions]: https://github.com/becksteinlab/imdclient/actions/workflows/gh-ci.yaml/badge.svg
11
11
  [badge_codecov]: https://codecov.io/gh/becksteinlab/imdclient/branch/main/graph/badge.svg
12
12
  [badge_commits_since]: https://img.shields.io/github/commits-since/becksteinlab/imdclient/latest
13
13
  [badge_docs]: https://readthedocs.org/projects/imdclient/badge/?version=latest
14
- [badge_license]: https://img.shields.io/badge/License-GPLv3-blue.svg
14
+ [badge_license]: https://img.shields.io/badge/License-MIT-blue.svg
15
15
  [badge_mda]: https://img.shields.io/badge/powered%20by-MDAnalysis-orange.svg?logoWidth=16&logo=data:image/x-icon;base64,AAABAAEAEBAAAAEAIAAoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJD+XwCY/fEAkf3uAJf97wGT/a+HfHaoiIWE7n9/f+6Hh4fvgICAjwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACT/yYAlP//AJ///wCg//8JjvOchXly1oaGhv+Ghob/j4+P/39/f3IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJH8aQCY/8wAkv2kfY+elJ6al/yVlZX7iIiI8H9/f7h/f38UAAAAAAAAAAAAAAAAAAAAAAAAAAB/f38egYF/noqAebF8gYaagnx3oFpUUtZpaWr/WFhY8zo6OmT///8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgICAn46Ojv+Hh4b/jouJ/4iGhfcAAADnAAAA/wAAAP8AAADIAAAAAwCj/zIAnf2VAJD/PAAAAAAAAAAAAAAAAICAgNGHh4f/gICA/4SEhP+Xl5f/AwMD/wAAAP8AAAD/AAAA/wAAAB8Aov9/ALr//wCS/Z0AAAAAAAAAAAAAAACBgYGOjo6O/4mJif+Pj4//iYmJ/wAAAOAAAAD+AAAA/wAAAP8AAABhAP7+FgCi/38Axf4fAAAAAAAAAAAAAAAAiIiID4GBgYKCgoKogoB+fYSEgZhgYGDZXl5e/m9vb/9ISEjpEBAQxw8AAFQAAAAAAAAANQAAADcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjo6Mb5iYmP+cnJz/jY2N95CQkO4pKSn/AAAA7gAAAP0AAAD7AAAAhgAAAAEAAAAAAAAAAACL/gsAkv2uAJX/QQAAAAB9fX3egoKC/4CAgP+NjY3/c3Nz+wAAAP8AAAD/AAAA/wAAAPUAAAAcAAAAAAAAAAAAnP4NAJL9rgCR/0YAAAAAfX19w4ODg/98fHz/i4uL/4qKivwAAAD/AAAA/wAAAP8AAAD1AAAAGwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALGxsVyqqqr/mpqa/6mpqf9KSUn/AAAA5QAAAPkAAAD5AAAAhQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADkUFBSuZ2dn/3V1df8uLi7bAAAATgBGfyQAAAA2AAAAMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0AAADoAAAA/wAAAP8AAAD/AAAAWgC3/2AAnv3eAJ/+dgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9AAAA/wAAAP8AAAD/AAAA/wAKDzEAnP3WAKn//wCS/OgAf/8MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIQAAANwAAADtAAAA7QAAAMAAABUMAJn9gwCe/e0Aj/2LAP//AQAAAAAAAAAA
16
16
  [badge_release]: https://img.shields.io/github/release-pre/becksteinlab/imdclient.svg
17
17
  [url_actions]: https://github.com/becksteinlab/imdclient/actions?query=branch%3Amain+workflow%3Agh-ci
18
18
  [url_codecov]: https://codecov.io/gh/becksteinlab/imdclient/branch/main
19
19
  [url_docs]: https://imdclient.readthedocs.io/en/latest/?badge=latest
20
20
  [url_latest_release]: https://github.com/becksteinlab/imdclient/releases
21
- [url_license]: https://www.gnu.org/licenses/gpl-3.0
21
+ [url_license]: https://opensource.org/license/mit
22
22
  [url_mda]: https://www.mdanalysis.org
23
23
 
24
- Receiver for IMDv3 protocol from simulation engines like Gromacs, LAMMPS, and NAMD.
24
+ Receiver for [IMDv3 protocol](https://imdclient.readthedocs.io/en/latest/protocol_v3.html) from simulation engines like Gromacs, LAMMPS, and NAMD.
25
25
 
26
26
  IMDClient is bound by a [Code of Conduct](https://github.com/becksteinlab/imdreader/blob/main/CODE_OF_CONDUCT.md).
27
27
 
28
28
  ### Installation
29
29
 
30
+ IMDClient is available via PyPi and can be installed with pip:
31
+ ```bash
32
+ pip install imdclient
33
+ ```
34
+
30
35
  To build IMDClient from source,
31
36
  we highly recommend using virtual environments.
32
37
  If possible, we strongly recommend that you use
@@ -88,7 +93,7 @@ pip install ".[test,doc]"
88
93
  ### Copyright
89
94
 
90
95
  The IMDClient source code is hosted at https://github.com/becksteinlab/imdclient
91
- and is available under the GNU General Public License, version 3 (see the file [LICENSE](https://github.com/becksteinlab/imdclient/blob/main/LICENSE)).
96
+ and is available under the MIT license (see the file [LICENSE](https://github.com/becksteinlab/imdclient/blob/main/LICENSE)).
92
97
 
93
98
  Copyright (c) 2024, Lawson
94
99
 
@@ -50,6 +50,7 @@ class IMDReader(StreamReaderBase):
50
50
  ):
51
51
  super(IMDReader, self).__init__(filename, **kwargs)
52
52
 
53
+ self._imdclient = None
53
54
  logger.debug("IMDReader initializing")
54
55
 
55
56
  if n_atoms is None:
@@ -83,9 +84,8 @@ class IMDReader(StreamReaderBase):
83
84
 
84
85
  try:
85
86
  imdf = self._imdclient.get_imdframe()
86
- except EOFError:
87
- # Not strictly necessary, but for clarity
88
- raise StopIteration
87
+ except EOFError as e:
88
+ raise e
89
89
 
90
90
  self._frame = frame
91
91
  self._load_imdframe_into_ts(imdf)
@@ -126,6 +126,7 @@ class IMDReader(StreamReaderBase):
126
126
  def close(self):
127
127
  """Gracefully shut down the reader. Stops the producer thread."""
128
128
  logger.debug("IMDReader close() called")
129
- self._imdclient.stop()
129
+ if self._imdclient is not None:
130
+ self._imdclient.stop()
130
131
  # NOTE: removeme after testing
131
132
  logger.debug("IMDReader shut down gracefully.")
@@ -25,6 +25,7 @@ import time
25
25
  import numpy as np
26
26
  from typing import Union, Dict
27
27
  import signal
28
+ import atexit
28
29
 
29
30
  logger = logging.getLogger(__name__)
30
31
 
@@ -42,7 +43,13 @@ class IMDClient:
42
43
  socket_bufsize : int, (optional)
43
44
  Size of the socket buffer in bytes. Default is to use the system default
44
45
  buffer_size : int (optional)
45
- IMDFramebuffer will be filled with as many :class:`IMDFrame` fit in `buffer_size` [``10MB``]
46
+ IMDFramebuffer will be filled with as many :class:`IMDFrame` fit in `buffer_size` bytes [``10MB``]
47
+ timeout : int, optional
48
+ Timeout for the socket in seconds [``5``]
49
+ continue_after_disconnect : bool, optional [``None``]
50
+ If True, the client will attempt to change the simulation engine's waiting behavior to
51
+ non-blocking after the client disconnects. If False, the client will attempt to change it
52
+ to blocking. If None, the client will not attempt to change the simulation engine's behavior.
46
53
  **kwargs : dict (optional)
47
54
  Additional keyword arguments to pass to the :class:`BaseIMDProducer` and :class:`IMDFrameBuffer`
48
55
  """
@@ -54,6 +61,7 @@ class IMDClient:
54
61
  n_atoms,
55
62
  socket_bufsize=None,
56
63
  multithreaded=True,
64
+ continue_after_disconnect=None,
57
65
  **kwargs,
58
66
  ):
59
67
 
@@ -61,6 +69,7 @@ class IMDClient:
61
69
  self._conn = self._connect_to_server(host, port, socket_bufsize)
62
70
  self._imdsinfo = self._await_IMD_handshake()
63
71
  self._multithreaded = multithreaded
72
+ self._continue_after_disconnect = continue_after_disconnect
64
73
 
65
74
  if self._multithreaded:
66
75
  self._buf = IMDFrameBuffer(
@@ -68,8 +77,10 @@ class IMDClient:
68
77
  n_atoms,
69
78
  **kwargs,
70
79
  )
80
+ self._error_queue = queue.Queue()
71
81
  else:
72
82
  self._buf = None
83
+ self._error_queue = None
73
84
  if self._imdsinfo.version == 2:
74
85
  self._producer = IMDProducerV2(
75
86
  self._conn,
@@ -77,6 +88,7 @@ class IMDClient:
77
88
  self._imdsinfo,
78
89
  n_atoms,
79
90
  multithreaded,
91
+ self._error_queue,
80
92
  **kwargs,
81
93
  )
82
94
  elif self._imdsinfo.version == 3:
@@ -86,23 +98,60 @@ class IMDClient:
86
98
  self._imdsinfo,
87
99
  n_atoms,
88
100
  multithreaded,
101
+ self._error_queue,
89
102
  **kwargs,
90
103
  )
91
104
 
92
105
  self._go()
93
106
 
94
107
  if self._multithreaded:
108
+ # Disconnect MUST occur. This covers typical cases (Python, IPython interpreter)
95
109
  signal.signal(signal.SIGINT, self.signal_handler)
110
+ signal.signal(signal.SIGTERM, self.signal_handler)
111
+
112
+ # Disconnect and socket shutdown MUST occur. This covers Jupyter use
113
+ # since in jupyter, the signal handler is reset to the default
114
+ # by pre- and post- hooks
115
+ # https://stackoverflow.com/questions/70841648/jupyter-reverts-signal-handler-to-default-when-running-next-cell
116
+ try:
117
+ import IPython
118
+ except ImportError:
119
+ has_ipython = False
120
+ else:
121
+ has_ipython = True
122
+
123
+ if has_ipython:
124
+ try:
125
+ from IPython import get_ipython
126
+
127
+ if get_ipython() is not None:
128
+ kernel = get_ipython().kernel
129
+ kernel.pre_handler_hook = lambda: None
130
+ kernel.post_handler_hook = lambda: None
131
+ logger.debug("Running in Jupyter")
132
+ except NameError:
133
+ logger.debug("Running in non-jupyter IPython environment")
134
+
135
+ # Final case: error is raised outside of IMDClient code
136
+ logger.debug("Registering atexit")
137
+ atexit.register(self.stop)
138
+
96
139
  self._producer.start()
97
140
 
98
141
  def signal_handler(self, sig, frame):
99
142
  """Catch SIGINT to allow clean shutdown on CTRL+C
100
143
  This also ensures that main thread execution doesn't get stuck
101
144
  waiting in buf.pop_full_imdframe()"""
145
+ logger.debug("Intercepted signal")
102
146
  self.stop()
147
+ logger.debug("Shutdown success")
103
148
 
104
149
  def get_imdframe(self):
105
150
  """
151
+ Returns
152
+ -------
153
+ IMDFrame
154
+ The next frame from the IMD server
106
155
  Raises
107
156
  ------
108
157
  EOFError
@@ -116,6 +165,9 @@ class IMDClient:
116
165
  # and doesn't need to be notified
117
166
  self._disconnect()
118
167
  self._stopped = True
168
+
169
+ if self._error_queue.qsize():
170
+ raise EOFError(f"{self._error_queue.get()}")
119
171
  raise EOFError
120
172
  else:
121
173
  try:
@@ -125,14 +177,23 @@ class IMDClient:
125
177
  raise EOFError
126
178
 
127
179
  def get_imdsessioninfo(self):
180
+ """
181
+ Returns
182
+ -------
183
+ IMDSessionInfo
184
+ Information about the IMD session
185
+ """
128
186
  return self._imdsinfo
129
187
 
130
188
  def stop(self):
189
+ """
190
+ Stop the client and close the connection
191
+ """
131
192
  if self._multithreaded:
132
193
  if not self._stopped:
133
- self._buf.notify_consumer_finished()
134
- self._disconnect()
135
194
  self._stopped = True
195
+ self._disconnect()
196
+ self._buf.notify_consumer_finished()
136
197
  else:
137
198
  self._disconnect()
138
199
 
@@ -239,6 +300,17 @@ class IMDClient:
239
300
  self._conn.sendall(go)
240
301
  logger.debug("IMDClient: Sent go packet to server")
241
302
 
303
+ if self._continue_after_disconnect is not None:
304
+ wait_behavior = (int)(not self._continue_after_disconnect)
305
+ wait_packet = create_header_bytes(
306
+ IMDHeaderType.IMD_WAIT, wait_behavior
307
+ )
308
+ self._conn.sendall(wait_packet)
309
+ logger.debug(
310
+ "IMDClient: Attempted to change wait behavior to %s",
311
+ not self._continue_after_disconnect
312
+ )
313
+
242
314
  def _disconnect(self):
243
315
  # MUST disconnect before stopping execution
244
316
  # if simulation already ended, this method will do nothing
@@ -254,6 +326,13 @@ class IMDClient:
254
326
  finally:
255
327
  self._conn.close()
256
328
 
329
+ def __enter__(self):
330
+ return self
331
+
332
+ def __exit__(self, exc_type, exc_val, exc_tb):
333
+ self.stop()
334
+ return False
335
+
257
336
 
258
337
  class BaseIMDProducer(threading.Thread):
259
338
  """
@@ -269,11 +348,14 @@ class BaseIMDProducer(threading.Thread):
269
348
  Information about the IMD session
270
349
  n_atoms : int
271
350
  Number of atoms in the simulation
272
- multithreaded : bool, optional
351
+ multithreaded : bool
273
352
  If True, socket interaction will occur in a separate thread &
274
353
  frames will be buffered. Single-threaded, blocking IMDClient
275
- should only be used in testing [[``True``]]
276
-
354
+ should only be used in testing
355
+ error_queue: queue.Queue
356
+ Queue to hold errors produced by the producer thread
357
+ timeout : int, optional
358
+ Timeout for the socket in seconds [``5``]
277
359
  """
278
360
 
279
361
  def __init__(
@@ -282,7 +364,8 @@ class BaseIMDProducer(threading.Thread):
282
364
  buffer,
283
365
  sinfo,
284
366
  n_atoms,
285
- multithreaded=True,
367
+ multithreaded,
368
+ error_queue,
286
369
  timeout=5,
287
370
  **kwargs,
288
371
  ):
@@ -291,6 +374,7 @@ class BaseIMDProducer(threading.Thread):
291
374
  self._imdsinfo = sinfo
292
375
  self._paused = False
293
376
 
377
+ self.error_queue = error_queue
294
378
  # Timeout for first frame should be longer
295
379
  # than rest of frames
296
380
  self._timeout = timeout
@@ -385,6 +469,7 @@ class BaseIMDProducer(threading.Thread):
385
469
  logger.debug("IMDProducer: Simulation ended normally, cleaning up")
386
470
  except Exception as e:
387
471
  logger.debug("IMDProducer: An unexpected error occurred: %s", e)
472
+ self.error_queue.put(e)
388
473
  finally:
389
474
  logger.debug("IMDProducer: Stopping run loop")
390
475
  # Tell consumer not to expect more frames to be added
@@ -400,9 +485,19 @@ class BaseIMDProducer(threading.Thread):
400
485
  )
401
486
  # Sometimes we do not care what the value is
402
487
  if expected_value is not None and header.length != expected_value:
403
- raise RuntimeError(
404
- f"IMDProducer: Expected header value {expected_value}, got {header.length}"
405
- )
488
+ if expected_type in [
489
+ IMDHeaderType.IMD_FCOORDS,
490
+ IMDHeaderType.IMD_VELOCITIES,
491
+ IMDHeaderType.IMD_FORCES,
492
+ ]:
493
+ raise RuntimeError(
494
+ f"IMDProducer: Expected n_atoms value {expected_value}, got {header.length}. "
495
+ + "Ensure you are using the correct topology file."
496
+ )
497
+ else:
498
+ raise RuntimeError(
499
+ f"IMDProducer: Expected header value {expected_value}, got {header.length}"
500
+ )
406
501
 
407
502
  def _get_header(self):
408
503
  self._read(self._header)
@@ -422,9 +517,18 @@ class BaseIMDProducer(threading.Thread):
422
517
 
423
518
 
424
519
  class IMDProducerV2(BaseIMDProducer):
425
- def __init__(self, conn, buffer, sinfo, n_atoms, multithreaded, **kwargs):
520
+ def __init__(
521
+ self,
522
+ conn,
523
+ buffer,
524
+ sinfo,
525
+ n_atoms,
526
+ multithreaded,
527
+ error_queue,
528
+ **kwargs,
529
+ ):
426
530
  super(IMDProducerV2, self).__init__(
427
- conn, buffer, sinfo, n_atoms, multithreaded, **kwargs
531
+ conn, buffer, sinfo, n_atoms, multithreaded, error_queue, **kwargs
428
532
  )
429
533
 
430
534
  self._energies = bytearray(IMDENERGYPACKETLENGTH)
@@ -517,6 +621,7 @@ class IMDProducerV3(BaseIMDProducer):
517
621
  sinfo,
518
622
  n_atoms,
519
623
  multithreaded,
624
+ error_queue,
520
625
  **kwargs,
521
626
  ):
522
627
  super(IMDProducerV3, self).__init__(
@@ -525,6 +630,7 @@ class IMDProducerV3(BaseIMDProducer):
525
630
  sinfo,
526
631
  n_atoms,
527
632
  multithreaded,
633
+ error_queue,
528
634
  **kwargs,
529
635
  )
530
636
  # The body of an x/v/f packet should contain
@@ -633,9 +739,6 @@ class IMDProducerV3(BaseIMDProducer):
633
739
  ).reshape((self._n_atoms, 3)),
634
740
  )
635
741
 
636
- def __del__(self):
637
- logger.debug("IMDProducer: I am being deleted")
638
-
639
742
 
640
743
  class IMDFrameBuffer:
641
744
  """
@@ -34,6 +34,7 @@ class IMDHeaderType(Enum):
34
34
  IMD_BOX = 13
35
35
  IMD_VELOCITIES = 14
36
36
  IMD_FORCES = 15
37
+ IMD_WAIT = 16
37
38
 
38
39
 
39
40
  def parse_energy_bytes(data, endianness):
@@ -1,5 +1,5 @@
1
1
  title = PRODUCTION IN NPT
2
- ld-seed = 1
2
+ ld-seed = 1
3
3
  ; Run parameters
4
4
  integrator = md ; leap-frog integrator
5
5
  nsteps = 100 ; 1 * 1000 = 1 ps
@@ -7,9 +7,9 @@ dt = 0.001 ; 1 fs
7
7
  ; Output control
8
8
  nstxout = 1 ; save coordinates every 1 fs
9
9
  nstvout = 1 ; save velocities every 1 fs
10
- nstfout = 1
10
+ nstfout = 1 ; save forces every 1 fs
11
11
  nstenergy = 1 ; save energies every 1 fs
12
- nstlog = 10 ; update log file every 1 ps
12
+ nstlog = 10
13
13
  ; Center of mass (COM) motion
14
14
  nstcomm = 10 ; remove COM motion every 10 steps
15
15
  comm-mode = Linear ; remove only COM translation (liquids in PBC)
@@ -0,0 +1,58 @@
1
+ title = PRODUCTION IN NPT
2
+ ld-seed = 1
3
+ ; Run parameters
4
+ integrator = md ; leap-frog integrator
5
+ nsteps = 100 ; 1 * 1000 = 1 ps
6
+ dt = 0.001 ; 1 fs
7
+ ; Output control
8
+ nstxout = 8 ; save coordinates every 1 fs
9
+ nstvout = 8 ; save velocities every 1 fs
10
+ nstfout = 8
11
+ nstenergy = 8 ; save energies every 1 fs
12
+ nstlog = 10 ; update log file every 1 ps
13
+ ; Center of mass (COM) motion
14
+ nstcomm = 10 ; remove COM motion every 10 steps
15
+ comm-mode = Linear ; remove only COM translation (liquids in PBC)
16
+ ; Bond parameters
17
+ continuation = yes ; first dynamics run
18
+ constraint_algorithm = lincs ; holonomic constraints
19
+ constraints = all-bonds ; all bonds lengths are constrained
20
+ lincs_iter = 1 ; accuracy of LINCS
21
+ lincs_order = 4 ; also related to accuracy
22
+ ; Nonbonded settings
23
+ cutoff-scheme = Verlet ; Buffered neighbor searching
24
+ ns_type = grid ; search neighboring grid cells
25
+ nstlist = 10 ; 10 fs, largely irrelevant with Verlet
26
+ rcoulomb = 1.0 ; short-range electrostatic cutoff (in nm)
27
+ rvdw = 1.0 ; short-range van der Waals cutoff (in nm)
28
+ DispCorr = EnerPres ; account for cut-off vdW scheme
29
+ ; Electrostatics
30
+ coulombtype = PME ; Particle Mesh Ewald for long-range electrostatics
31
+ pme_order = 4 ; cubic interpolation
32
+ fourierspacing = 0.12 ; grid spacing for FFT
33
+ ; Temperature coupling is on
34
+ tcoupl = Nose-Hoover ; good for production, after equilibration
35
+ ; we define separate thermostats for the solute and solvent (need to adapt)
36
+ ; see default groups defined by Gromacs for your system or define your own (make_ndx)
37
+ tc-grps = Protein SOL ; the separate groups for the thermostats
38
+ tau-t = 1.0 1.0 ; time constants for thermostats (ps)
39
+ ref-t = 300 300 ; reference temperature for thermostats (K)
40
+ ; Pressure coupling is off
41
+ pcoupl = Parrinello-Rahman ; good for production, after equilibration
42
+ tau-p = 2.0 ; time constant for barostat (ps)
43
+ compressibility = 4.5e-5 ; compressibility (1/bar) set to water at ~300K
44
+ ref-p = 1.0 ; reference pressure for barostat (bar)
45
+ ; Periodic boundary conditions
46
+ pbc = xyz ; 3-D PBC
47
+ ; Velocity generation
48
+ gen_vel = no
49
+ IMD-group = System
50
+ IMD-nst = 8
51
+ IMD-version = 3
52
+ IMD-time = yes
53
+ IMD-box = yes
54
+ IMD-coords = yes
55
+ IMD-unwrap = no
56
+ IMD-vels = yes
57
+ IMD-forces = yes
58
+ IMD-energies = no
@@ -52,8 +52,8 @@ velocity all create 300 102939 dist gaussian mom yes rot yes
52
52
  fix 1 all nve
53
53
 
54
54
  # Create source of truth trajectory
55
- # dump h5md1 all h5md 1 lammps_trj.h5md position velocity force box yes
56
- # dump_modify h5md1 unwrap no
55
+ dump h5md1 all h5md 1 lammps_trj.h5md position velocity force box yes
56
+ dump_modify h5md1 unwrap no
57
57
 
58
58
  ## IMD settings
59
59
  # https://docs.lammps.org/fix_imd.html
@@ -63,7 +63,7 @@ fix 2 all imd 8888 version 3 unwrap off nowait off
63
63
  run 100
64
64
 
65
65
  # Stop dumping information to the dump file.
66
- # undump h5md1
66
+ undump h5md1
67
67
 
68
68
  # Unfix the NVE. Additional lines if any will assume that this fix is off.
69
69
  unfix 1