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.
- nanover_server-0.1.2958/PKG-INFO +45 -0
- nanover_server-0.1.2958/VERSION.txt +1 -0
- nanover_server-0.1.2958/conda/build.sh +2 -0
- nanover_server-0.1.2958/conda/meta.yaml +42 -0
- nanover_server-0.1.2958/pyproject.toml +87 -0
- nanover_server-0.1.2958/setup.cfg +4 -0
- nanover_server-0.1.2958/src/nanover/app/__init__.py +12 -0
- nanover_server-0.1.2958/src/nanover/app/cli/recorder_cli.py +123 -0
- nanover_server-0.1.2958/src/nanover/app/cli/server_cli.py +233 -0
- nanover_server-0.1.2958/src/nanover/app/imd_app.py +310 -0
- nanover_server-0.1.2958/src/nanover/app/multiuser.py +66 -0
- nanover_server-0.1.2958/src/nanover/app/omni.py +379 -0
- nanover_server-0.1.2958/src/nanover/app/py.typed +1 -0
- nanover_server-0.1.2958/src/nanover/app/selection.py +312 -0
- nanover_server-0.1.2958/src/nanover/ase/__init__.py +6 -0
- nanover_server-0.1.2958/src/nanover/ase/converter.py +353 -0
- nanover_server-0.1.2958/src/nanover/ase/imd_calculator.py +399 -0
- nanover_server-0.1.2958/src/nanover/ase/null_calculator.py +26 -0
- nanover_server-0.1.2958/src/nanover/ase/omm_calculator.py +161 -0
- nanover_server-0.1.2958/src/nanover/ase/py.typed +1 -0
- nanover_server-0.1.2958/src/nanover/ase/simulation.py +290 -0
- nanover_server-0.1.2958/src/nanover/ase/thermo.py +39 -0
- nanover_server-0.1.2958/src/nanover/ase/trajectory_logger.py +198 -0
- nanover_server-0.1.2958/src/nanover/ase/wall_constraint.py +44 -0
- nanover_server-0.1.2958/src/nanover/core/__init__.py +7 -0
- nanover_server-0.1.2958/src/nanover/core/app_server.py +91 -0
- nanover_server-0.1.2958/src/nanover/core/commands.py +222 -0
- nanover_server-0.1.2958/src/nanover/core/py.typed +1 -0
- nanover_server-0.1.2958/src/nanover/core/simulation.py +12 -0
- nanover_server-0.1.2958/src/nanover/core/types.py +28 -0
- nanover_server-0.1.2958/src/nanover/essd/__init__.py +30 -0
- nanover_server-0.1.2958/src/nanover/essd/client.py +77 -0
- nanover_server-0.1.2958/src/nanover/essd/list_cli.py +42 -0
- nanover_server-0.1.2958/src/nanover/essd/py.typed +1 -0
- nanover_server-0.1.2958/src/nanover/essd/server.py +195 -0
- nanover_server-0.1.2958/src/nanover/essd/servicehub.py +226 -0
- nanover_server-0.1.2958/src/nanover/essd/utils.py +130 -0
- nanover_server-0.1.2958/src/nanover/imd/__init__.py +5 -0
- nanover_server-0.1.2958/src/nanover/imd/imd_force.py +407 -0
- nanover_server-0.1.2958/src/nanover/imd/imd_state.py +136 -0
- nanover_server-0.1.2958/src/nanover/imd/particle_interaction.py +190 -0
- nanover_server-0.1.2958/src/nanover/imd/py.typed +1 -0
- nanover_server-0.1.2958/src/nanover/jupyter/__init__.py +13 -0
- nanover_server-0.1.2958/src/nanover/jupyter/alignment_transform.py +30 -0
- nanover_server-0.1.2958/src/nanover/jupyter/controls.py +201 -0
- nanover_server-0.1.2958/src/nanover/jupyter/frame_listener.py +66 -0
- nanover_server-0.1.2958/src/nanover/jupyter/imd_agent.py +35 -0
- nanover_server-0.1.2958/src/nanover/jupyter/nglclient.py +188 -0
- nanover_server-0.1.2958/src/nanover/jupyter/py.typed +1 -0
- nanover_server-0.1.2958/src/nanover/jupyter/transform_grabbing.py +155 -0
- nanover_server-0.1.2958/src/nanover/jupyter/transform_handles.py +60 -0
- nanover_server-0.1.2958/src/nanover/jupyter/utilities.py +568 -0
- nanover_server-0.1.2958/src/nanover/mdanalysis/__init__.py +13 -0
- nanover_server-0.1.2958/src/nanover/mdanalysis/converter.py +328 -0
- nanover_server-0.1.2958/src/nanover/mdanalysis/py.typed +1 -0
- nanover_server-0.1.2958/src/nanover/mdanalysis/simulation.py +108 -0
- nanover_server-0.1.2958/src/nanover/mdanalysis/universe.py +463 -0
- nanover_server-0.1.2958/src/nanover/openmm/__init__.py +15 -0
- nanover_server-0.1.2958/src/nanover/openmm/converter.py +159 -0
- nanover_server-0.1.2958/src/nanover/openmm/imd.py +208 -0
- nanover_server-0.1.2958/src/nanover/openmm/potentials.py +79 -0
- nanover_server-0.1.2958/src/nanover/openmm/py.typed +1 -0
- nanover_server-0.1.2958/src/nanover/openmm/serializer.py +204 -0
- nanover_server-0.1.2958/src/nanover/openmm/simulation.py +309 -0
- nanover_server-0.1.2958/src/nanover/openmm/thermo.py +60 -0
- nanover_server-0.1.2958/src/nanover/recording/__init__.py +3 -0
- nanover_server-0.1.2958/src/nanover/recording/cli/dump_cli.py +68 -0
- nanover_server-0.1.2958/src/nanover/recording/cli/split_cli.py +220 -0
- nanover_server-0.1.2958/src/nanover/recording/playback.py +139 -0
- nanover_server-0.1.2958/src/nanover/recording/py.typed +1 -0
- nanover_server-0.1.2958/src/nanover/recording/reading.py +345 -0
- nanover_server-0.1.2958/src/nanover/recording/writing.py +80 -0
- nanover_server-0.1.2958/src/nanover/testing/__init__.py +5 -0
- nanover_server-0.1.2958/src/nanover/testing/asserts.py +70 -0
- nanover_server-0.1.2958/src/nanover/testing/py.typed +1 -0
- nanover_server-0.1.2958/src/nanover/testing/servers.py +94 -0
- nanover_server-0.1.2958/src/nanover/testing/strategies.py +177 -0
- nanover_server-0.1.2958/src/nanover/testing/utilities.py +19 -0
- nanover_server-0.1.2958/src/nanover/trajectory/__init__.py +3 -0
- nanover_server-0.1.2958/src/nanover/trajectory/frame_dict.py +98 -0
- nanover_server-0.1.2958/src/nanover/trajectory/frame_publisher.py +107 -0
- nanover_server-0.1.2958/src/nanover/trajectory/frame_queue.py +27 -0
- nanover_server-0.1.2958/src/nanover/trajectory/frame_wrapper.py +176 -0
- nanover_server-0.1.2958/src/nanover/trajectory/keys.py +56 -0
- nanover_server-0.1.2958/src/nanover/trajectory/py.typed +1 -0
- nanover_server-0.1.2958/src/nanover/utilities/__init__.py +0 -0
- nanover_server-0.1.2958/src/nanover/utilities/change_buffers.py +244 -0
- nanover_server-0.1.2958/src/nanover/utilities/cli.py +57 -0
- nanover_server-0.1.2958/src/nanover/utilities/event.py +42 -0
- nanover_server-0.1.2958/src/nanover/utilities/intersection.py +41 -0
- nanover_server-0.1.2958/src/nanover/utilities/key_lockable_map.py +107 -0
- nanover_server-0.1.2958/src/nanover/utilities/network.py +19 -0
- nanover_server-0.1.2958/src/nanover/utilities/packing.py +76 -0
- nanover_server-0.1.2958/src/nanover/utilities/py.typed +1 -0
- nanover_server-0.1.2958/src/nanover/utilities/queues.py +71 -0
- nanover_server-0.1.2958/src/nanover/utilities/state_dictionary.py +127 -0
- nanover_server-0.1.2958/src/nanover/utilities/timing.py +66 -0
- nanover_server-0.1.2958/src/nanover/utilities/transforms.py +199 -0
- nanover_server-0.1.2958/src/nanover/websocket/__init__.py +1 -0
- nanover_server-0.1.2958/src/nanover/websocket/client/app_client.py +234 -0
- nanover_server-0.1.2958/src/nanover/websocket/client/base_client.py +85 -0
- nanover_server-0.1.2958/src/nanover/websocket/client/command_client.py +44 -0
- nanover_server-0.1.2958/src/nanover/websocket/client/interaction_client.py +115 -0
- nanover_server-0.1.2958/src/nanover/websocket/client/playback_client.py +52 -0
- nanover_server-0.1.2958/src/nanover/websocket/client/selection_client.py +129 -0
- nanover_server-0.1.2958/src/nanover/websocket/client/state_client.py +25 -0
- nanover_server-0.1.2958/src/nanover/websocket/discovery.py +44 -0
- nanover_server-0.1.2958/src/nanover/websocket/landing.py +26 -0
- nanover_server-0.1.2958/src/nanover/websocket/py.typed +1 -0
- nanover_server-0.1.2958/src/nanover/websocket/record.py +93 -0
- nanover_server-0.1.2958/src/nanover/websocket/server.py +271 -0
- nanover_server-0.1.2958/src/nanover_server.egg-info/PKG-INFO +45 -0
- nanover_server-0.1.2958/src/nanover_server.egg-info/SOURCES.txt +194 -0
- nanover_server-0.1.2958/src/nanover_server.egg-info/dependency_links.txt +1 -0
- nanover_server-0.1.2958/src/nanover_server.egg-info/entry_points.txt +6 -0
- nanover_server-0.1.2958/src/nanover_server.egg-info/requires.txt +23 -0
- nanover_server-0.1.2958/src/nanover_server.egg-info/top_level.txt +1 -0
- nanover_server-0.1.2958/tests/test_ase/omm_simulation_utils.py +123 -0
- nanover_server-0.1.2958/tests/test_ase/test_ase_converter.py +127 -0
- nanover_server-0.1.2958/tests/test_ase/test_imd_calculator.py +144 -0
- nanover_server-0.1.2958/tests/test_ase/test_imd_reset.py +323 -0
- nanover_server-0.1.2958/tests/test_ase/test_omm_calculator.py +86 -0
- nanover_server-0.1.2958/tests/test_ase/test_trajectory_logger.py +167 -0
- nanover_server-0.1.2958/tests/test_ase/test_velocity_wall.py +148 -0
- nanover_server-0.1.2958/tests/test_ase/util.py +40 -0
- nanover_server-0.1.2958/tests/test_cli/__init__.py +0 -0
- nanover_server-0.1.2958/tests/test_cli/test_all.py +39 -0
- nanover_server-0.1.2958/tests/test_core/__init__.py +81 -0
- nanover_server-0.1.2958/tests/test_core/app/__init__.py +0 -0
- nanover_server-0.1.2958/tests/test_core/app/test_client_selections.py +227 -0
- nanover_server-0.1.2958/tests/test_core/app/test_command_service.py +36 -0
- nanover_server-0.1.2958/tests/test_core/app/test_multiuser.py +56 -0
- nanover_server-0.1.2958/tests/test_core/app/test_selection.py +136 -0
- nanover_server-0.1.2958/tests/test_core/imd/__init__.py +0 -0
- nanover_server-0.1.2958/tests/test_core/imd/test_distances.py +169 -0
- nanover_server-0.1.2958/tests/test_core/imd/test_imd_force.py +548 -0
- nanover_server-0.1.2958/tests/test_core/imd/test_imd_state_wrapper.py +102 -0
- nanover_server-0.1.2958/tests/test_core/imd/test_interaction.py +156 -0
- nanover_server-0.1.2958/tests/test_core/imd/test_interactions.py +227 -0
- nanover_server-0.1.2958/tests/test_core/recording/__init__.py +0 -0
- nanover_server-0.1.2958/tests/test_core/recording/nanotube-example-recording.nanover.zip +0 -0
- nanover_server-0.1.2958/tests/test_core/recording/sim-switching-test-recording.nanover.zip +0 -0
- nanover_server-0.1.2958/tests/test_core/recording/test_reading.py +101 -0
- nanover_server-0.1.2958/tests/test_core/recording/test_reading_writing.py +36 -0
- nanover_server-0.1.2958/tests/test_core/recording/test_utilities.py +35 -0
- nanover_server-0.1.2958/tests/test_core/state/test_state_dictionary.py +144 -0
- nanover_server-0.1.2958/tests/test_core/test_autoconnect.py +104 -0
- nanover_server-0.1.2958/tests/test_core/test_client.py +255 -0
- nanover_server-0.1.2958/tests/test_core/test_frame_server.py +19 -0
- nanover_server-0.1.2958/tests/test_core/trajectory/__init__.py +0 -0
- nanover_server-0.1.2958/tests/test_core/trajectory/test_frame_publisher.py +86 -0
- nanover_server-0.1.2958/tests/test_core/utilities/__init__.py +0 -0
- nanover_server-0.1.2958/tests/test_core/utilities/test_change_buffers.py +179 -0
- nanover_server-0.1.2958/tests/test_core/utilities/test_event.py +59 -0
- nanover_server-0.1.2958/tests/test_core/utilities/test_intersections.py +69 -0
- nanover_server-0.1.2958/tests/test_core/utilities/test_key_lockable_map.py +61 -0
- nanover_server-0.1.2958/tests/test_core/utilities/test_queues.py +137 -0
- nanover_server-0.1.2958/tests/test_core/utilities/test_timing.py +51 -0
- nanover_server-0.1.2958/tests/test_core/utilities/test_transforms.py +60 -0
- nanover_server-0.1.2958/tests/test_essd/test_essd_client_server.py +173 -0
- nanover_server-0.1.2958/tests/test_essd/test_essd_server.py +153 -0
- nanover_server-0.1.2958/tests/test_essd/test_essd_service.py +119 -0
- nanover_server-0.1.2958/tests/test_jupyter/test_imd_agent.py +110 -0
- nanover_server-0.1.2958/tests/test_jupyter/test_transform_utilities.py +28 -0
- nanover_server-0.1.2958/tests/test_mdanalysis/17-ala.pdb +177 -0
- nanover_server-0.1.2958/tests/test_mdanalysis/2efv_fragment.pdb +402 -0
- nanover_server-0.1.2958/tests/test_mdanalysis/test.nanover.zip +0 -0
- nanover_server-0.1.2958/tests/test_mdanalysis/test_all_forces.nanover.zip +0 -0
- nanover_server-0.1.2958/tests/test_mdanalysis/test_force.nanover.zip +0 -0
- nanover_server-0.1.2958/tests/test_mdanalysis/test_mda_converter.py +194 -0
- nanover_server-0.1.2958/tests/test_mdanalysis/test_multi.nanover.zip +0 -0
- nanover_server-0.1.2958/tests/test_mdanalysis/test_universe.py +243 -0
- nanover_server-0.1.2958/tests/test_mdanalysis/test_vel.nanover.zip +0 -0
- nanover_server-0.1.2958/tests/test_mdanalysis/test_vel_force.nanover.zip +0 -0
- nanover_server-0.1.2958/tests/test_omni/3TI6_ose_wt.pdb +5880 -0
- nanover_server-0.1.2958/tests/test_omni/__init__.py +0 -0
- nanover_server-0.1.2958/tests/test_omni/common.py +73 -0
- nanover_server-0.1.2958/tests/test_omni/hiv1_complex.xml +157374 -0
- nanover_server-0.1.2958/tests/test_omni/nanotube-example-recording.nanover.zip +0 -0
- nanover_server-0.1.2958/tests/test_omni/openmm_simulation_utils.py +215 -0
- nanover_server-0.1.2958/tests/test_omni/ose_wt.dcd +0 -0
- nanover_server-0.1.2958/tests/test_omni/test_all.py +219 -0
- nanover_server-0.1.2958/tests/test_omni/test_ase.py +384 -0
- nanover_server-0.1.2958/tests/test_omni/test_cli.py +40 -0
- nanover_server-0.1.2958/tests/test_omni/test_client_simulation.py +29 -0
- nanover_server-0.1.2958/tests/test_omni/test_openmm.py +636 -0
- nanover_server-0.1.2958/tests/test_omni/test_playback.py +95 -0
- nanover_server-0.1.2958/tests/test_omni/test_playback_mda.py +70 -0
- nanover_server-0.1.2958/tests/test_openmm/simulation_utils.py +142 -0
- nanover_server-0.1.2958/tests/test_openmm/test_converter.py +94 -0
- nanover_server-0.1.2958/tests/test_openmm/test_imd.py +72 -0
- nanover_server-0.1.2958/tests/test_openmm/test_potentials.py +45 -0
- nanover_server-0.1.2958/tests/test_openmm/test_serializer.py +172 -0
- nanover_server-0.1.2958/tests/test_websocket/test_convert.py +15 -0
- nanover_server-0.1.2958/tests/test_websocket/test_server.py +14 -0
- 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,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,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()
|