nanover-server 0.1.2958__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 (196) hide show
  1. nanover_server-0.1.2958/PKG-INFO +45 -0
  2. nanover_server-0.1.2958/VERSION.txt +1 -0
  3. nanover_server-0.1.2958/conda/build.sh +2 -0
  4. nanover_server-0.1.2958/conda/meta.yaml +42 -0
  5. nanover_server-0.1.2958/pyproject.toml +87 -0
  6. nanover_server-0.1.2958/setup.cfg +4 -0
  7. nanover_server-0.1.2958/src/nanover/app/__init__.py +12 -0
  8. nanover_server-0.1.2958/src/nanover/app/cli/recorder_cli.py +123 -0
  9. nanover_server-0.1.2958/src/nanover/app/cli/server_cli.py +233 -0
  10. nanover_server-0.1.2958/src/nanover/app/imd_app.py +310 -0
  11. nanover_server-0.1.2958/src/nanover/app/multiuser.py +66 -0
  12. nanover_server-0.1.2958/src/nanover/app/omni.py +379 -0
  13. nanover_server-0.1.2958/src/nanover/app/py.typed +1 -0
  14. nanover_server-0.1.2958/src/nanover/app/selection.py +312 -0
  15. nanover_server-0.1.2958/src/nanover/ase/__init__.py +6 -0
  16. nanover_server-0.1.2958/src/nanover/ase/converter.py +353 -0
  17. nanover_server-0.1.2958/src/nanover/ase/imd_calculator.py +399 -0
  18. nanover_server-0.1.2958/src/nanover/ase/null_calculator.py +26 -0
  19. nanover_server-0.1.2958/src/nanover/ase/omm_calculator.py +161 -0
  20. nanover_server-0.1.2958/src/nanover/ase/py.typed +1 -0
  21. nanover_server-0.1.2958/src/nanover/ase/simulation.py +290 -0
  22. nanover_server-0.1.2958/src/nanover/ase/thermo.py +39 -0
  23. nanover_server-0.1.2958/src/nanover/ase/trajectory_logger.py +198 -0
  24. nanover_server-0.1.2958/src/nanover/ase/wall_constraint.py +44 -0
  25. nanover_server-0.1.2958/src/nanover/core/__init__.py +7 -0
  26. nanover_server-0.1.2958/src/nanover/core/app_server.py +91 -0
  27. nanover_server-0.1.2958/src/nanover/core/commands.py +222 -0
  28. nanover_server-0.1.2958/src/nanover/core/py.typed +1 -0
  29. nanover_server-0.1.2958/src/nanover/core/simulation.py +12 -0
  30. nanover_server-0.1.2958/src/nanover/core/types.py +28 -0
  31. nanover_server-0.1.2958/src/nanover/essd/__init__.py +30 -0
  32. nanover_server-0.1.2958/src/nanover/essd/client.py +77 -0
  33. nanover_server-0.1.2958/src/nanover/essd/list_cli.py +42 -0
  34. nanover_server-0.1.2958/src/nanover/essd/py.typed +1 -0
  35. nanover_server-0.1.2958/src/nanover/essd/server.py +195 -0
  36. nanover_server-0.1.2958/src/nanover/essd/servicehub.py +226 -0
  37. nanover_server-0.1.2958/src/nanover/essd/utils.py +130 -0
  38. nanover_server-0.1.2958/src/nanover/imd/__init__.py +5 -0
  39. nanover_server-0.1.2958/src/nanover/imd/imd_force.py +407 -0
  40. nanover_server-0.1.2958/src/nanover/imd/imd_state.py +136 -0
  41. nanover_server-0.1.2958/src/nanover/imd/particle_interaction.py +190 -0
  42. nanover_server-0.1.2958/src/nanover/imd/py.typed +1 -0
  43. nanover_server-0.1.2958/src/nanover/jupyter/__init__.py +13 -0
  44. nanover_server-0.1.2958/src/nanover/jupyter/alignment_transform.py +30 -0
  45. nanover_server-0.1.2958/src/nanover/jupyter/controls.py +201 -0
  46. nanover_server-0.1.2958/src/nanover/jupyter/frame_listener.py +66 -0
  47. nanover_server-0.1.2958/src/nanover/jupyter/imd_agent.py +35 -0
  48. nanover_server-0.1.2958/src/nanover/jupyter/nglclient.py +188 -0
  49. nanover_server-0.1.2958/src/nanover/jupyter/py.typed +1 -0
  50. nanover_server-0.1.2958/src/nanover/jupyter/transform_grabbing.py +155 -0
  51. nanover_server-0.1.2958/src/nanover/jupyter/transform_handles.py +60 -0
  52. nanover_server-0.1.2958/src/nanover/jupyter/utilities.py +568 -0
  53. nanover_server-0.1.2958/src/nanover/mdanalysis/__init__.py +13 -0
  54. nanover_server-0.1.2958/src/nanover/mdanalysis/converter.py +328 -0
  55. nanover_server-0.1.2958/src/nanover/mdanalysis/py.typed +1 -0
  56. nanover_server-0.1.2958/src/nanover/mdanalysis/simulation.py +108 -0
  57. nanover_server-0.1.2958/src/nanover/mdanalysis/universe.py +463 -0
  58. nanover_server-0.1.2958/src/nanover/openmm/__init__.py +15 -0
  59. nanover_server-0.1.2958/src/nanover/openmm/converter.py +159 -0
  60. nanover_server-0.1.2958/src/nanover/openmm/imd.py +208 -0
  61. nanover_server-0.1.2958/src/nanover/openmm/potentials.py +79 -0
  62. nanover_server-0.1.2958/src/nanover/openmm/py.typed +1 -0
  63. nanover_server-0.1.2958/src/nanover/openmm/serializer.py +204 -0
  64. nanover_server-0.1.2958/src/nanover/openmm/simulation.py +309 -0
  65. nanover_server-0.1.2958/src/nanover/openmm/thermo.py +60 -0
  66. nanover_server-0.1.2958/src/nanover/recording/__init__.py +3 -0
  67. nanover_server-0.1.2958/src/nanover/recording/cli/dump_cli.py +68 -0
  68. nanover_server-0.1.2958/src/nanover/recording/cli/split_cli.py +220 -0
  69. nanover_server-0.1.2958/src/nanover/recording/playback.py +139 -0
  70. nanover_server-0.1.2958/src/nanover/recording/py.typed +1 -0
  71. nanover_server-0.1.2958/src/nanover/recording/reading.py +345 -0
  72. nanover_server-0.1.2958/src/nanover/recording/writing.py +80 -0
  73. nanover_server-0.1.2958/src/nanover/testing/__init__.py +5 -0
  74. nanover_server-0.1.2958/src/nanover/testing/asserts.py +70 -0
  75. nanover_server-0.1.2958/src/nanover/testing/py.typed +1 -0
  76. nanover_server-0.1.2958/src/nanover/testing/servers.py +94 -0
  77. nanover_server-0.1.2958/src/nanover/testing/strategies.py +177 -0
  78. nanover_server-0.1.2958/src/nanover/testing/utilities.py +19 -0
  79. nanover_server-0.1.2958/src/nanover/trajectory/__init__.py +3 -0
  80. nanover_server-0.1.2958/src/nanover/trajectory/frame_dict.py +98 -0
  81. nanover_server-0.1.2958/src/nanover/trajectory/frame_publisher.py +107 -0
  82. nanover_server-0.1.2958/src/nanover/trajectory/frame_queue.py +27 -0
  83. nanover_server-0.1.2958/src/nanover/trajectory/frame_wrapper.py +176 -0
  84. nanover_server-0.1.2958/src/nanover/trajectory/keys.py +56 -0
  85. nanover_server-0.1.2958/src/nanover/trajectory/py.typed +1 -0
  86. nanover_server-0.1.2958/src/nanover/utilities/__init__.py +0 -0
  87. nanover_server-0.1.2958/src/nanover/utilities/change_buffers.py +244 -0
  88. nanover_server-0.1.2958/src/nanover/utilities/cli.py +57 -0
  89. nanover_server-0.1.2958/src/nanover/utilities/event.py +42 -0
  90. nanover_server-0.1.2958/src/nanover/utilities/intersection.py +41 -0
  91. nanover_server-0.1.2958/src/nanover/utilities/key_lockable_map.py +107 -0
  92. nanover_server-0.1.2958/src/nanover/utilities/network.py +19 -0
  93. nanover_server-0.1.2958/src/nanover/utilities/packing.py +76 -0
  94. nanover_server-0.1.2958/src/nanover/utilities/py.typed +1 -0
  95. nanover_server-0.1.2958/src/nanover/utilities/queues.py +71 -0
  96. nanover_server-0.1.2958/src/nanover/utilities/state_dictionary.py +127 -0
  97. nanover_server-0.1.2958/src/nanover/utilities/timing.py +66 -0
  98. nanover_server-0.1.2958/src/nanover/utilities/transforms.py +199 -0
  99. nanover_server-0.1.2958/src/nanover/websocket/__init__.py +1 -0
  100. nanover_server-0.1.2958/src/nanover/websocket/client/app_client.py +234 -0
  101. nanover_server-0.1.2958/src/nanover/websocket/client/base_client.py +85 -0
  102. nanover_server-0.1.2958/src/nanover/websocket/client/command_client.py +44 -0
  103. nanover_server-0.1.2958/src/nanover/websocket/client/interaction_client.py +115 -0
  104. nanover_server-0.1.2958/src/nanover/websocket/client/playback_client.py +52 -0
  105. nanover_server-0.1.2958/src/nanover/websocket/client/selection_client.py +129 -0
  106. nanover_server-0.1.2958/src/nanover/websocket/client/state_client.py +25 -0
  107. nanover_server-0.1.2958/src/nanover/websocket/discovery.py +44 -0
  108. nanover_server-0.1.2958/src/nanover/websocket/landing.py +26 -0
  109. nanover_server-0.1.2958/src/nanover/websocket/py.typed +1 -0
  110. nanover_server-0.1.2958/src/nanover/websocket/record.py +93 -0
  111. nanover_server-0.1.2958/src/nanover/websocket/server.py +271 -0
  112. nanover_server-0.1.2958/src/nanover_server.egg-info/PKG-INFO +45 -0
  113. nanover_server-0.1.2958/src/nanover_server.egg-info/SOURCES.txt +194 -0
  114. nanover_server-0.1.2958/src/nanover_server.egg-info/dependency_links.txt +1 -0
  115. nanover_server-0.1.2958/src/nanover_server.egg-info/entry_points.txt +6 -0
  116. nanover_server-0.1.2958/src/nanover_server.egg-info/requires.txt +23 -0
  117. nanover_server-0.1.2958/src/nanover_server.egg-info/top_level.txt +1 -0
  118. nanover_server-0.1.2958/tests/test_ase/omm_simulation_utils.py +123 -0
  119. nanover_server-0.1.2958/tests/test_ase/test_ase_converter.py +127 -0
  120. nanover_server-0.1.2958/tests/test_ase/test_imd_calculator.py +144 -0
  121. nanover_server-0.1.2958/tests/test_ase/test_imd_reset.py +323 -0
  122. nanover_server-0.1.2958/tests/test_ase/test_omm_calculator.py +86 -0
  123. nanover_server-0.1.2958/tests/test_ase/test_trajectory_logger.py +167 -0
  124. nanover_server-0.1.2958/tests/test_ase/test_velocity_wall.py +148 -0
  125. nanover_server-0.1.2958/tests/test_ase/util.py +40 -0
  126. nanover_server-0.1.2958/tests/test_cli/__init__.py +0 -0
  127. nanover_server-0.1.2958/tests/test_cli/test_all.py +39 -0
  128. nanover_server-0.1.2958/tests/test_core/__init__.py +81 -0
  129. nanover_server-0.1.2958/tests/test_core/app/__init__.py +0 -0
  130. nanover_server-0.1.2958/tests/test_core/app/test_client_selections.py +227 -0
  131. nanover_server-0.1.2958/tests/test_core/app/test_command_service.py +36 -0
  132. nanover_server-0.1.2958/tests/test_core/app/test_multiuser.py +56 -0
  133. nanover_server-0.1.2958/tests/test_core/app/test_selection.py +136 -0
  134. nanover_server-0.1.2958/tests/test_core/imd/__init__.py +0 -0
  135. nanover_server-0.1.2958/tests/test_core/imd/test_distances.py +169 -0
  136. nanover_server-0.1.2958/tests/test_core/imd/test_imd_force.py +548 -0
  137. nanover_server-0.1.2958/tests/test_core/imd/test_imd_state_wrapper.py +102 -0
  138. nanover_server-0.1.2958/tests/test_core/imd/test_interaction.py +156 -0
  139. nanover_server-0.1.2958/tests/test_core/imd/test_interactions.py +227 -0
  140. nanover_server-0.1.2958/tests/test_core/recording/__init__.py +0 -0
  141. nanover_server-0.1.2958/tests/test_core/recording/nanotube-example-recording.nanover.zip +0 -0
  142. nanover_server-0.1.2958/tests/test_core/recording/sim-switching-test-recording.nanover.zip +0 -0
  143. nanover_server-0.1.2958/tests/test_core/recording/test_reading.py +101 -0
  144. nanover_server-0.1.2958/tests/test_core/recording/test_reading_writing.py +36 -0
  145. nanover_server-0.1.2958/tests/test_core/recording/test_utilities.py +35 -0
  146. nanover_server-0.1.2958/tests/test_core/state/test_state_dictionary.py +144 -0
  147. nanover_server-0.1.2958/tests/test_core/test_autoconnect.py +104 -0
  148. nanover_server-0.1.2958/tests/test_core/test_client.py +255 -0
  149. nanover_server-0.1.2958/tests/test_core/test_frame_server.py +19 -0
  150. nanover_server-0.1.2958/tests/test_core/trajectory/__init__.py +0 -0
  151. nanover_server-0.1.2958/tests/test_core/trajectory/test_frame_publisher.py +86 -0
  152. nanover_server-0.1.2958/tests/test_core/utilities/__init__.py +0 -0
  153. nanover_server-0.1.2958/tests/test_core/utilities/test_change_buffers.py +179 -0
  154. nanover_server-0.1.2958/tests/test_core/utilities/test_event.py +59 -0
  155. nanover_server-0.1.2958/tests/test_core/utilities/test_intersections.py +69 -0
  156. nanover_server-0.1.2958/tests/test_core/utilities/test_key_lockable_map.py +61 -0
  157. nanover_server-0.1.2958/tests/test_core/utilities/test_queues.py +137 -0
  158. nanover_server-0.1.2958/tests/test_core/utilities/test_timing.py +51 -0
  159. nanover_server-0.1.2958/tests/test_core/utilities/test_transforms.py +60 -0
  160. nanover_server-0.1.2958/tests/test_essd/test_essd_client_server.py +173 -0
  161. nanover_server-0.1.2958/tests/test_essd/test_essd_server.py +153 -0
  162. nanover_server-0.1.2958/tests/test_essd/test_essd_service.py +119 -0
  163. nanover_server-0.1.2958/tests/test_jupyter/test_imd_agent.py +110 -0
  164. nanover_server-0.1.2958/tests/test_jupyter/test_transform_utilities.py +28 -0
  165. nanover_server-0.1.2958/tests/test_mdanalysis/17-ala.pdb +177 -0
  166. nanover_server-0.1.2958/tests/test_mdanalysis/2efv_fragment.pdb +402 -0
  167. nanover_server-0.1.2958/tests/test_mdanalysis/test.nanover.zip +0 -0
  168. nanover_server-0.1.2958/tests/test_mdanalysis/test_all_forces.nanover.zip +0 -0
  169. nanover_server-0.1.2958/tests/test_mdanalysis/test_force.nanover.zip +0 -0
  170. nanover_server-0.1.2958/tests/test_mdanalysis/test_mda_converter.py +194 -0
  171. nanover_server-0.1.2958/tests/test_mdanalysis/test_multi.nanover.zip +0 -0
  172. nanover_server-0.1.2958/tests/test_mdanalysis/test_universe.py +243 -0
  173. nanover_server-0.1.2958/tests/test_mdanalysis/test_vel.nanover.zip +0 -0
  174. nanover_server-0.1.2958/tests/test_mdanalysis/test_vel_force.nanover.zip +0 -0
  175. nanover_server-0.1.2958/tests/test_omni/3TI6_ose_wt.pdb +5880 -0
  176. nanover_server-0.1.2958/tests/test_omni/__init__.py +0 -0
  177. nanover_server-0.1.2958/tests/test_omni/common.py +73 -0
  178. nanover_server-0.1.2958/tests/test_omni/hiv1_complex.xml +157374 -0
  179. nanover_server-0.1.2958/tests/test_omni/nanotube-example-recording.nanover.zip +0 -0
  180. nanover_server-0.1.2958/tests/test_omni/openmm_simulation_utils.py +215 -0
  181. nanover_server-0.1.2958/tests/test_omni/ose_wt.dcd +0 -0
  182. nanover_server-0.1.2958/tests/test_omni/test_all.py +219 -0
  183. nanover_server-0.1.2958/tests/test_omni/test_ase.py +384 -0
  184. nanover_server-0.1.2958/tests/test_omni/test_cli.py +40 -0
  185. nanover_server-0.1.2958/tests/test_omni/test_client_simulation.py +29 -0
  186. nanover_server-0.1.2958/tests/test_omni/test_openmm.py +636 -0
  187. nanover_server-0.1.2958/tests/test_omni/test_playback.py +95 -0
  188. nanover_server-0.1.2958/tests/test_omni/test_playback_mda.py +70 -0
  189. nanover_server-0.1.2958/tests/test_openmm/simulation_utils.py +142 -0
  190. nanover_server-0.1.2958/tests/test_openmm/test_converter.py +94 -0
  191. nanover_server-0.1.2958/tests/test_openmm/test_imd.py +72 -0
  192. nanover_server-0.1.2958/tests/test_openmm/test_potentials.py +45 -0
  193. nanover_server-0.1.2958/tests/test_openmm/test_serializer.py +172 -0
  194. nanover_server-0.1.2958/tests/test_websocket/test_convert.py +15 -0
  195. nanover_server-0.1.2958/tests/test_websocket/test_server.py +14 -0
  196. nanover_server-0.1.2958/tests/test_websocket/test_server_client.py +174 -0
@@ -0,0 +1,45 @@
1
+ Metadata-Version: 2.4
2
+ Name: nanover-server
3
+ Version: 0.1.2958
4
+ Summary: Python servers for NanoVer.
5
+ Author: Intangible Realities Lab
6
+ License-Expression: MIT
7
+ Project-URL: homepage, https://github.com/IRL2/nanover-server-py
8
+ Project-URL: source, https://github.com/IRL2/nanover-server-py
9
+ Project-URL: documentation, https://irl2.github.io/nanover-docs/
10
+ Project-URL: issues, https://github.com/IRL2/nanover-server-py/issues
11
+ Project-URL: funding, https://irl2.github.io/nanover-docs/#current-sponsors
12
+ Project-URL: changelog, https://github.com/IRL2/nanover-server-py/commits/main/
13
+ Keywords: molecular dynamics,interactive molecular dynamics,imd,imd-vr,imd-xr,virtual reality,vr,extended reality,xr
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Framework :: Jupyter
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Operating System :: Microsoft :: Windows
18
+ Classifier: Operating System :: MacOS
19
+ Classifier: Operating System :: POSIX
20
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
21
+ Classifier: Topic :: Scientific/Engineering :: Chemistry
22
+ Classifier: Topic :: Scientific/Engineering :: Visualization
23
+ Requires-Python: >=3.12
24
+ Requires-Dist: openmm
25
+ Requires-Dist: MDAnalysis
26
+ Requires-Dist: numpy
27
+ Requires-Dist: nglview>=4.0.1
28
+ Requires-Dist: netifaces
29
+ Requires-Dist: ase>=3.21
30
+ Requires-Dist: websockets>=15.0.0
31
+ Requires-Dist: msgpack>=1.0.0
32
+ Requires-Dist: pooch
33
+ Provides-Extra: dev
34
+ Requires-Dist: pytest; extra == "dev"
35
+ Requires-Dist: pytest-asyncio; extra == "dev"
36
+ Requires-Dist: pytest-cov; extra == "dev"
37
+ Requires-Dist: pytest-timeout; extra == "dev"
38
+ Requires-Dist: pytest-xdist; extra == "dev"
39
+ Requires-Dist: hypothesis; extra == "dev"
40
+ Requires-Dist: python-osc; extra == "dev"
41
+ Requires-Dist: mock; extra == "dev"
42
+ Requires-Dist: mypy; extra == "dev"
43
+ Requires-Dist: typing_extensions; extra == "dev"
44
+ Requires-Dist: nbval; extra == "dev"
45
+ Requires-Dist: types-netifaces; extra == "dev"
@@ -0,0 +1 @@
1
+ 0.1.2958
@@ -0,0 +1,2 @@
1
+ #!/bin/bash
2
+ $PYTHON -m pip install . --no-deps --ignore-installed --no-cache-dir -vvv
@@ -0,0 +1,42 @@
1
+ package:
2
+ name: nanover-server
3
+ version: {{ NANOVER_BUILD_VERSION }}
4
+
5
+ source:
6
+ path: ../
7
+
8
+ build:
9
+ noarch: python
10
+ number: 0
11
+ entry_points:
12
+ - nanover-server = nanover.app.cli.server_cli:main
13
+ - nanover-record = nanover.app.cli.recorder_cli:main
14
+ - nanover-essd-list = nanover.essd.list_cli:main
15
+ - nanover-dump-state = nanover.recording.cli.dump_cli:main
16
+ - nanover-split-recording = nanover.recording.cli.split_cli:main
17
+
18
+ requirements:
19
+ build:
20
+ - python >={{ MIN_PYTHON_VERSION }}
21
+ - setuptools
22
+ run:
23
+ - python >={{ MIN_PYTHON_VERSION }}
24
+ - netifaces
25
+ - numpy
26
+ - openmm
27
+ - ase >=3.21
28
+ - mdanalysis
29
+ - nglview
30
+ - websockets >=15.0.0
31
+ - msgpack-python >=1.0.0
32
+
33
+ about:
34
+ home: {{ NANOVER_DOC_URL }}
35
+ license: MIT
36
+ license_file: {{ NANOVER_LICENSE_PATH }}
37
+ summary: Python servers for NanoVer.
38
+ description: |
39
+ NanoVer is a framework for interactive molecular dynamics simulation in
40
+ virtual reality. This package cause all the python servers to be installed.
41
+ doc_url: {{ NANOVER_DOC_URL }}
42
+ dev_url: {{ NANOVER_REPO_URL }}
@@ -0,0 +1,87 @@
1
+ [build-system]
2
+ requires = ["setuptools", "setuptools-scm"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ dynamic = ["version"]
7
+ name = "nanover-server"
8
+ authors = [
9
+ {name = "Intangible Realities Lab"},
10
+ ]
11
+ description = "Python servers for NanoVer."
12
+ license = "MIT"
13
+ keywords = ["molecular dynamics", "interactive molecular dynamics", "imd", "imd-vr", "imd-xr", "virtual reality", "vr", "extended reality", "xr"]
14
+
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Framework :: Jupyter",
18
+ "Programming Language :: Python :: 3 :: Only",
19
+
20
+ "Operating System :: Microsoft :: Windows",
21
+ "Operating System :: MacOS",
22
+ "Operating System :: POSIX",
23
+
24
+ "Topic :: Scientific/Engineering :: Bio-Informatics",
25
+ "Topic :: Scientific/Engineering :: Chemistry",
26
+ "Topic :: Scientific/Engineering :: Visualization",
27
+ ]
28
+
29
+ requires-python = ">=3.12"
30
+ dependencies = [
31
+ "openmm",
32
+ "MDAnalysis",
33
+ "numpy",
34
+ "nglview>=4.0.1",
35
+ "netifaces",
36
+ "ase >= 3.21",
37
+ "websockets>=15.0.0",
38
+ "msgpack>=1.0.0",
39
+ # mdanalysis will include this soon anyway
40
+ "pooch",
41
+ ]
42
+
43
+ [project.urls]
44
+ homepage = "https://github.com/IRL2/nanover-server-py"
45
+ source = "https://github.com/IRL2/nanover-server-py"
46
+ documentation = "https://irl2.github.io/nanover-docs/"
47
+ issues = "https://github.com/IRL2/nanover-server-py/issues"
48
+ funding = "https://irl2.github.io/nanover-docs/#current-sponsors"
49
+ changelog = "https://github.com/IRL2/nanover-server-py/commits/main/"
50
+
51
+ [project.optional-dependencies]
52
+ dev=[
53
+ # Requirement files for running the tests.
54
+ "pytest",
55
+ "pytest-asyncio",
56
+ "pytest-cov",
57
+ "pytest-timeout",
58
+ "pytest-xdist",
59
+ "hypothesis",
60
+ # python-osc is needed to test an example
61
+ "python-osc",
62
+ # mock is required for some core tests
63
+ "mock",
64
+ # type checking
65
+ "mypy",
66
+ "typing_extensions",
67
+ # jupyter notebooks
68
+ "nbval",
69
+ # ui
70
+ #"gradio>=5.18.0",
71
+ # types
72
+ "types-netifaces",
73
+ ]
74
+
75
+ [project.scripts]
76
+ nanover-server = "nanover.app.cli.server_cli:main"
77
+ nanover-record = "nanover.app.cli.recorder_cli:main"
78
+ nanover-essd-list = "nanover.essd.list_cli:main"
79
+ nanover-dump-state = "nanover.recording.cli.dump_cli:main"
80
+ nanover-split-recording = "nanover.recording.cli.split_cli:main"
81
+
82
+ [tool.setuptools.packages.find]
83
+ where = ["src"] # list of folders that contain the packages (["."] by default)
84
+ include = ["nanover.*"] # package names should match these glob patterns (["*"] by default)
85
+
86
+ [tool.setuptools.dynamic]
87
+ version = {file = "VERSION.txt"}
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,12 @@
1
+ """
2
+ Module providing application level wrappers, orchestrators and managers that can be used to
3
+ easily build and deploy NanoVer services.
4
+ """
5
+
6
+ from .imd_app import NanoverImdApplication as NanoverImdApplication
7
+ from .omni import OmniRunner as OmniRunner
8
+ from .selection import (
9
+ SELECTION_ROOT_ID as SELECTION_ROOT_ID,
10
+ SELECTION_ROOT_NAME as SELECTION_ROOT_NAME,
11
+ RenderingSelection as RenderingSelection,
12
+ )
@@ -0,0 +1,123 @@
1
+ """
2
+ A NanoVer client that records the trajectory and the state updates.
3
+
4
+ Run the script as `nanover-record` to connect to a server running on localhost
5
+ on the default port (38801) and begin recording to uniquely named .traj and
6
+ .state files. Run `nanover-record --help` to find options for connecting to
7
+ specific servers and changing the output filename.
8
+ """
9
+
10
+ import argparse
11
+ import textwrap
12
+ import time
13
+
14
+ from nanover.essd import DiscoveryClient
15
+ from nanover.utilities.cli import suppress_keyboard_interrupt_as_cancellation
16
+ from nanover.websocket.client.app_client import get_websocket_address_from_hub
17
+ from nanover.websocket.record import BackgroundRecordingContext
18
+
19
+
20
+ def handle_user_arguments(args=None) -> argparse.Namespace:
21
+ """
22
+ Parse the arguments from the command line.
23
+
24
+ :return: The namespace of arguments read from the command line.
25
+ """
26
+ description = textwrap.dedent(
27
+ """\
28
+ Recording client for NanoVer
29
+ """
30
+ )
31
+ parser = argparse.ArgumentParser(description=description)
32
+
33
+ parser.add_argument(
34
+ "--path",
35
+ default=".",
36
+ metavar="PATH",
37
+ help="Destination for recording files.",
38
+ )
39
+
40
+ parser.add_argument(
41
+ "--prefix",
42
+ default="recording",
43
+ metavar="PREFIX",
44
+ help="Prefix for the recording filenames.",
45
+ )
46
+
47
+ parser.add_argument(
48
+ "--address",
49
+ metavar="PROTOCOL://HOST:PORT",
50
+ help="Connect to specific host address and port.",
51
+ default="ws://127.0.0.1:38801",
52
+ )
53
+
54
+ parser.add_argument(
55
+ "--autoconnect",
56
+ metavar="QUERY",
57
+ help="Use server discovery and pick a server with name matching the query.",
58
+ )
59
+
60
+ arguments = parser.parse_args(args)
61
+ return arguments
62
+
63
+
64
+ def main():
65
+ """
66
+ Entry point for the command line.
67
+ """
68
+
69
+ arguments = handle_user_arguments()
70
+ address = arguments.address
71
+
72
+ if arguments.autoconnect is not None:
73
+ print(f"Using server discovery to find '{arguments.autoconnect}'")
74
+ with DiscoveryClient() as discovery_client:
75
+ for hub in discovery_client.search_for_services():
76
+ if arguments.autoconnect in hub.name:
77
+ address = get_websocket_address_from_hub(hub)
78
+ print(f"Found '{hub.name}' at {address}.")
79
+ break
80
+
81
+ path = arguments.path
82
+ prefix = arguments.prefix
83
+
84
+ count = 0
85
+
86
+ while True:
87
+ count += 1
88
+ timestamp = time.strftime("%Y%m%d-%H%M%S")
89
+ name = f"{prefix}-{count}-{timestamp}"
90
+
91
+ outfile = f"{path}/{name}.nanover.zip"
92
+
93
+ print(f"Connecting to {address}.")
94
+
95
+ interrupted = False
96
+
97
+ with (
98
+ suppress_keyboard_interrupt_as_cancellation() as cancellation,
99
+ BackgroundRecordingContext.from_address_to_path(
100
+ address=address, path=outfile
101
+ ) as recording,
102
+ ):
103
+ print(f"Recording from server to {outfile}. Press Ctrl-C to stop.")
104
+ recording.future.add_done_callback(lambda _: cancellation.cancel())
105
+ cancellation.wait_cancellation(interval=0.01)
106
+ interrupted = not recording.future.done()
107
+
108
+ if not interrupted:
109
+ print("Recording ended by disconnection.")
110
+ break
111
+
112
+ try:
113
+ input(
114
+ "Recording ended by Ctrl-C. Press Ctrl-C to quit or Return to begin recording again."
115
+ )
116
+ except KeyboardInterrupt:
117
+ break
118
+ except EOFError:
119
+ break
120
+
121
+
122
+ if __name__ == "__main__":
123
+ main()
@@ -0,0 +1,233 @@
1
+ """
2
+ Command line interface for nanover-server.
3
+ """
4
+
5
+ import argparse
6
+ import logging
7
+ import ssl
8
+ import textwrap
9
+ import time
10
+ from collections.abc import Iterable
11
+ from contextlib import contextmanager
12
+ from glob import glob
13
+
14
+ from MDAnalysis import Universe
15
+ from nanover.app import OmniRunner
16
+ from nanover.mdanalysis import UniverseSimulation
17
+ from nanover.openmm import OpenMMSimulation
18
+ from nanover.recording import PlaybackSimulation
19
+ from nanover.utilities.cli import suppress_keyboard_interrupt_as_cancellation
20
+ from nanover.websocket.client.app_client import NanoverImdClient
21
+ from nanover.websocket.discovery import DiscoveryClient
22
+ from nanover.websocket.record import record_from_runner
23
+
24
+
25
+ def handle_user_arguments(args=None) -> argparse.Namespace:
26
+ """
27
+ Parse the arguments from the command line.
28
+
29
+ :return: The namespace of arguments read from the command line.
30
+ """
31
+ description = textwrap.dedent(
32
+ """\
33
+ Multi-simulation server for NanoVer
34
+ """
35
+ )
36
+ parser = argparse.ArgumentParser(description=description)
37
+
38
+ parser.add_argument(
39
+ "--omm",
40
+ dest="openmm_xml_entries",
41
+ action="append",
42
+ nargs="+",
43
+ default=[],
44
+ metavar="PATH",
45
+ help="Simulations to run via OpenMM (XML format)",
46
+ )
47
+
48
+ parser.add_argument(
49
+ "--mda",
50
+ dest="mdanalysis_entries",
51
+ action="append",
52
+ nargs="+",
53
+ default=[],
54
+ metavar="PATH",
55
+ help="Independent structures to load via MDanalysis",
56
+ )
57
+
58
+ parser.add_argument(
59
+ "--playback",
60
+ dest="recording_entries",
61
+ action="append",
62
+ nargs="+",
63
+ default=[],
64
+ metavar="PATH",
65
+ help="Recorded sessions to playback",
66
+ )
67
+
68
+ parser.add_argument(
69
+ "--record",
70
+ dest="record_to_path",
71
+ nargs="?",
72
+ default=None,
73
+ const="",
74
+ metavar="PATH",
75
+ help="Record trajectory and state to files.",
76
+ )
77
+
78
+ parser.add_argument(
79
+ "-q",
80
+ "--include-velocities",
81
+ action="store_true",
82
+ default=False,
83
+ help="Optionally include the particle velocities in the frame data for OMM and ASE simulations.",
84
+ )
85
+ parser.add_argument(
86
+ "-k",
87
+ "--include-forces",
88
+ action="store_true",
89
+ default=False,
90
+ help="Optionally include the particle forces in the frame data for OMM and ASE simulations.",
91
+ )
92
+
93
+ parser.add_argument(
94
+ "-s",
95
+ "--ssl",
96
+ nargs=3,
97
+ metavar=("CERTFILE", "KEYFILE", "PASSWORD"),
98
+ help="Offer SSL in addition to insecure connections.",
99
+ )
100
+
101
+ parser.add_argument(
102
+ "--cloud-discovery",
103
+ dest="cloud_discovery_host",
104
+ metavar="ENDPOINT",
105
+ help="Advertise server on cloud discovery.",
106
+ )
107
+
108
+ parser.add_argument(
109
+ "--remote",
110
+ nargs="?",
111
+ metavar="PROTOCOL://HOST:PORT",
112
+ help="Publish to remote server at specific host address and port.",
113
+ const="ws://localhost:38801",
114
+ )
115
+
116
+ parser.add_argument(
117
+ "-n",
118
+ "--name",
119
+ help="Give a friendly name to the server.",
120
+ )
121
+ parser.add_argument("-p", "--port", type=int, default=None)
122
+ parser.add_argument("-a", "--address", default=None)
123
+
124
+ arguments = parser.parse_args(args)
125
+ return arguments
126
+
127
+
128
+ def get_all_paths(path_sets: Iterable[Iterable[str]]):
129
+ for paths in path_sets:
130
+ for pattern in paths:
131
+ files = list(glob(pattern, recursive=True))
132
+ if files:
133
+ yield from files
134
+ else:
135
+ logging.getLogger(__name__).warning(
136
+ f'Path "{pattern}" yielded 0 files.'
137
+ )
138
+
139
+
140
+ @contextmanager
141
+ def initialise_runner(arguments: argparse.Namespace):
142
+ @contextmanager
143
+ def make_runner():
144
+ if arguments.remote is None:
145
+ with OmniRunner.with_basic_server(
146
+ name=arguments.name,
147
+ address=arguments.address,
148
+ port=arguments.port,
149
+ ssl=initialise_ssl(arguments),
150
+ ) as runner:
151
+ yield runner
152
+ else:
153
+ with NanoverImdClient.from_url(arguments.remote) as client:
154
+ print(f"Serving as client of remote server at {arguments.remote}")
155
+ with OmniRunner.from_client(client) as runner:
156
+ yield runner
157
+
158
+ with make_runner() as runner:
159
+ for path in get_all_paths(arguments.recording_entries):
160
+ runner.add_simulation(PlaybackSimulation.from_path(path=path))
161
+
162
+ for path in get_all_paths(arguments.openmm_xml_entries):
163
+ simulation = OpenMMSimulation.from_xml_path(path)
164
+ simulation.include_velocities = arguments.include_velocities
165
+ simulation.include_forces = arguments.include_forces
166
+ runner.add_simulation(simulation)
167
+
168
+ for path in get_all_paths(arguments.mdanalysis_entries):
169
+ universe = Universe(path)
170
+ simulation = UniverseSimulation.from_universe(universe)
171
+ runner.add_simulation(simulation)
172
+
173
+ if arguments.record_to_path is not None:
174
+ stem = arguments.record_to_path
175
+ if stem == "":
176
+ timestamp = time.strftime("%Y-%m-%d-%H%M-%S", time.gmtime())
177
+ stem = f"omni-recording-{timestamp}"
178
+
179
+ out_path = f"{stem}.nanover.zip"
180
+ print(f"Recording to {out_path}")
181
+
182
+ record_from_runner(runner, out_path)
183
+
184
+ if arguments.cloud_discovery_host:
185
+ with DiscoveryClient.advertise_server(
186
+ arguments.cloud_discovery_host, app_server=runner.app_server
187
+ ):
188
+ yield runner
189
+ else:
190
+ yield runner
191
+
192
+
193
+ def initialise_ssl(arguments: argparse.Namespace):
194
+ if arguments.ssl is None:
195
+ return None
196
+
197
+ certfile, keyfile, password = arguments.ssl
198
+ ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
199
+ ssl_context.load_verify_locations(certfile)
200
+ ssl_context.load_cert_chain(certfile, keyfile=keyfile, password=password)
201
+
202
+ return ssl_context
203
+
204
+
205
+ def main():
206
+ """
207
+ Entry point for the command line.
208
+ """
209
+ # use the nice logger formatting if available
210
+ try:
211
+ from rich.logging import RichHandler
212
+
213
+ logging.basicConfig(handlers=[RichHandler(rich_tracebacks=True)])
214
+ except ImportError:
215
+ logging.basicConfig()
216
+ logging.captureWarnings(True)
217
+
218
+ arguments = handle_user_arguments()
219
+
220
+ with (
221
+ suppress_keyboard_interrupt_as_cancellation() as cancellation,
222
+ initialise_runner(arguments) as runner,
223
+ ):
224
+ if len(runner.simulations) > 0:
225
+ runner.load(0)
226
+
227
+ runner.print_basic_info()
228
+ cancellation.wait_cancellation()
229
+ print("Closing due to KeyboardInterrupt.")
230
+
231
+
232
+ if __name__ == "__main__":
233
+ main()