From 7e855f8184364148b6acde6127fcf782cb98a7c6 Mon Sep 17 00:00:00 2001 From: Harry Stroud <75842225+hjstroud@users.noreply.github.com> Date: Fri, 11 Oct 2024 12:56:18 +0200 Subject: [PATCH] Update ASE-OpenMM tutorial notebooks (#255) * Refactor notebook names of ASE examples * Switch from old runner to OmniRunner and ASEOpenMMSimulation * Refactor simulation name and set up interactive buttons to work with OmniRunner and ASEOpenMMSimulation objects * Add OmniRunner and ASEOpenMMSimulation functionality to nanotube notebook * Make notebook print temperature correctly * Correct path to retrieve port * Remove lines pertaining to old runner * Initial changes to neuraminidase notebook for ASE * Fix temperature units and add ASE-type functionality back into notebook * Undo incorrect changes from merge * Update simulation and runner information * Correct typo * Add ASE functionality back into the nanotube notebook * Add note about ASE units * Rerun notebook to update values * Remove unnecessary semicolons and rerun notebook * Update wording of nanotube notebooks to reflect NanoVer NGLView client * Edit introductory paragraph of notebook --- ..._example.ipynb => ase_basic_example.ipynb} | 2 +- ...aphene.ipynb => ase_openmm_graphene.ipynb} | 300 ++++++++++++++---- ...notube.ipynb => ase_openmm_nanotube.ipynb} | 140 ++++---- ...e.ipynb => ase_openmm_neuraminidase.ipynb} | 122 ++++--- examples/openmm/openmm_nanotube.ipynb | 2 +- examples/openmm/openmm_polyalanine.ipynb | 2 +- 6 files changed, 392 insertions(+), 176 deletions(-) rename examples/ase/{basic_example.ipynb => ase_basic_example.ipynb} (99%) rename examples/ase/{openmm_graphene.ipynb => ase_openmm_graphene.ipynb} (67%) rename examples/ase/{openmm_nanotube.ipynb => ase_openmm_nanotube.ipynb} (79%) rename examples/ase/{openmm_neuraminidase.ipynb => ase_openmm_neuraminidase.ipynb} (79%) diff --git a/examples/ase/basic_example.ipynb b/examples/ase/ase_basic_example.ipynb similarity index 99% rename from examples/ase/basic_example.ipynb rename to examples/ase/ase_basic_example.ipynb index 55949862b..9a5ba57a3 100644 --- a/examples/ase/basic_example.ipynb +++ b/examples/ase/ase_basic_example.ipynb @@ -1641,7 +1641,7 @@ "\n", "This notebook showed a toy example with ASE. \n", "\n", - "* Run bigger molecular mechanics simulations with OpenMM. The [nanotube](./openmm_nanotube.ipynb) and [neuraminidase](./openmm_neuraminidase.ipynb) examples show how to set up simulations with OpenMM.\n", + "* Run bigger molecular mechanics simulations with OpenMM. The [nanotube](./ase_openmm_nanotube.ipynb) and [neuraminidase](./ase_openmm_neuraminidase.ipynb) examples show how to set up simulations with OpenMM.\n", "* To understand what's going on under the hood, consider starting with the [NanoVer frame explained](../fundamentals/frame.ipynb) example. " ] }, diff --git a/examples/ase/openmm_graphene.ipynb b/examples/ase/ase_openmm_graphene.ipynb similarity index 67% rename from examples/ase/openmm_graphene.ipynb rename to examples/ase/ase_openmm_graphene.ipynb index 81cfe3b55..b31975bb0 100644 --- a/examples/ase/openmm_graphene.ipynb +++ b/examples/ase/ase_openmm_graphene.ipynb @@ -11,7 +11,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This notebook simulates a graphene sheet with OpenMM, and exposes parameters that can be controlled in real time.\n", + "This notebook simulates a graphene sheet with OpenMM via ASE, and exposes parameters that can be controlled in real time.\n", "Along the way, we'll learn:\n", "\n", "* How to add restraints to OpenMM simulations \n", @@ -30,12 +30,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "First, we set up an OpenMM simulation of graphene. In this case, we've already generated an OpenMM XML file and have a PDB ready to use for the topology. See the [neuraminidase example](./openmm_neuraminidase.ipynb) for a more detailed look at setting up OpenMM simulations. " + "First, we set up an OpenMM simulation of graphene. In this case, we've already generated an OpenMM XML file and have a PDB ready to use for the topology. See the [neuraminidase example](./ase_openmm_neuraminidase.ipynb) for a more detailed look at setting up OpenMM simulations. " ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": { "pycharm": { "is_executing": false, @@ -53,7 +53,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": { "pycharm": { "is_executing": false, @@ -78,7 +78,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -87,7 +87,7 @@ "(3, 680)" ] }, - "execution_count": 4, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -98,7 +98,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -107,7 +107,7 @@ "680" ] }, - "execution_count": 5, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -126,7 +126,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -135,7 +135,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "metadata": { "pycharm": { "is_executing": false, @@ -167,7 +167,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 7, "metadata": { "pycharm": { "is_executing": false, @@ -190,7 +190,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -209,30 +209,81 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We'll use NanoVer's ASEOpenMMRunner to simplify running the server" + "We'll use NanoVer's `OmniRunner` to simplify running the server, passing the simulation as an `ASEOpenMMSimulation`." ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ - "from nanover.ase.openmm.runner import ASEOpenMMRunner, ImdParams" + "# Import the relevant classes\n", + "from nanover.omni import OmniRunner\n", + "from nanover.omni.ase_omm import ASEOpenMMSimulation\n", + "\n", + "# Set up the simulation and define the time step\n", + "graphene_ase_omm_sim = ASEOpenMMSimulation.from_simulation(simulation)\n", + "graphene_ase_omm_sim.time_step = 0.05\n", + "\n", + "# Pass the simulation to the OmniRunner, load the simulation and pause it\n", + "runner = OmniRunner.with_basic_server(graphene_ase_omm_sim, name=\"graphene-ase-omm-server\", port=0)\n", + "runner.next()\n", + "runner.pause()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's run a few steps and check that everything is working as expected." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "graphene_ase_omm_sim.dynamics.run(10)" ] }, { "cell_type": "code", "execution_count": 11, - "metadata": { - "pycharm": { - "is_executing": false, - "name": "#%%\n" + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" } - }, - "outputs": [], + ], + "source": [ + "graphene_ase_omm_sim.dynamics.get_number_of_steps()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, "source": [ - "runner = ASEOpenMMRunner(simulation, ImdParams(port=0, time_step=0.5, verbose=False))" + "Let's check the potential energy too." ] }, { @@ -241,15 +292,25 @@ "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "mark: NanoVer iMD Server: serving on [::]:49544\n" - ] + "data": { + "text/plain": [ + "30.1487298005627" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "print(f'{runner.name}: serving on {runner.address}:{runner.port}')" + "graphene_ase_omm_sim.atoms.get_potential_energy()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we're ready to go! Let's start the simulation and leave it to run in the background." ] }, { @@ -259,28 +320,36 @@ "pycharm": { "is_executing": false, "name": "#%%\n" - }, - "scrolled": true + } }, "outputs": [], "source": [ - "runner.run(20)" + "# Start running the simulation\n", + "runner.play()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Let's leave it running in the background " + "We can print the details of the server by running the following cell:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "graphene-ase-omm-server: serving on [::]:56181\n" + ] + } + ], "source": [ - "runner.run()" + "print(f'{runner.app_server.name}: serving on {runner.app_server.address}:{runner.app_server.port}')" ] }, { @@ -326,7 +395,7 @@ "\n", " if not temp_min_val <= temperature <= temp_max_val:\n", " raise ValueError(f'Temperature must be in range {temp_min_val} - {temp_max_val} Kelvin.')\n", - " runner.dynamics.set_temperature(temperature_K=temperature * units.kB)\n", + " graphene_ase_omm_sim.dynamics.set_temperature(temperature_K=temperature)\n", "\n", "\n", "def set_friction(friction=1):\n", @@ -338,7 +407,7 @@ "\n", " if not friction_min_val <= friction <= friction_max_val:\n", " raise ValueError(f'Friction must be in range {friction_min_val} - {friction_max_val}.')\n", - " runner.dynamics.set_friction(friction / 1000.0)\n", + " graphene_ase_omm_sim.dynamics.set_friction(friction / 1000.0)\n", "\n", "\n", "def set_timestep(timestep=0.5):\n", @@ -351,7 +420,7 @@ " if not timestep_min_val <= timestep <= timestep_max_val:\n", " raise ValueError(f'Timestep must be in range {timestep_min_val} - {timestep_max_val}')\n", " timestep = timestep * units.fs\n", - " runner.dynamics.set_timestep(timestep)" + " graphene_ase_omm_sim.dynamics.set_timestep(timestep)" ] }, { @@ -363,7 +432,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": { "pycharm": { "is_executing": false @@ -379,13 +448,112 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "metadata": { "pycharm": { "is_executing": false } }, - "outputs": [], + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "57687b75fb9c4ced828b6787add3c7b2", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "interactive(children=(IntSlider(value=300, description='temperature', max=10000), Output()), _dom_classes=('wi…" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d51a6b2be6904625a5bfc1bc5034dc94", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "interactive(children=(FloatSlider(value=1.0, description='friction', min=0.01, step=1.0), Output()), _dom_clas…" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "edf4abd82900472a800c5039b4f2d636", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "interactive(children=(FloatSlider(value=0.5, description='timestep', max=1.5, min=0.01, step=0.01), Output()),…" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "60057f97aea545779f736ebb9f5def84", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Button(description='Restart Simulation', style=ButtonStyle())" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4027617f677c49f5b592e4d1464516f2", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "5fae713fc7b049179df8c47dfbf9141a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "ToggleButton(value=False, description='Playing')" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4027617f677c49f5b592e4d1464516f2", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "# Sliders for temperature, friction and timestep\n", "interact(set_temperature, temperature=(temp_min_val,temp_max_val));\n", @@ -401,14 +569,14 @@ "\n", "def on_reset_clicked(b):\n", " with output:\n", - " runner.imd.reset()\n", + " runner.reset()\n", "\n", "def on_play_clicked(obj):\n", " with output:\n", " if obj['new']: \n", - " runner.imd.play()\n", + " runner.play()\n", " else:\n", - " runner.imd.pause()\n", + " runner.pause()\n", "\n", "reset_button.on_click(on_reset_clicked)\n", "play_button.observe(on_play_clicked, 'value')" @@ -441,7 +609,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "metadata": { "pycharm": { "is_executing": false, @@ -476,12 +644,12 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "from nanover.app import NanoverImdClient\n", - "client = NanoverImdClient.connect_to_single_server(port=runner.port) " + "client = NanoverImdClient.connect_to_single_server(port=runner.app_server.port) " ] }, { @@ -493,11 +661,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 20, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "dict_keys(['multiuser/radially-orient-origins', 'playback/load', 'playback/next', 'playback/list', 'playback/reset', 'playback/pause', 'playback/play', 'playback/step', 'sim/timestep', 'sim/temperature', 'sim/friction'])" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "commands = client.update_available_commands();\n", + "commands = client.update_available_commands()\n", "dict(commands).keys()" ] }, @@ -510,13 +689,24 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "199.99999999999997" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "client.run_command('sim/temperature', temperature=200);\n", + "client.run_command('sim/temperature', temperature=200)\n", "# print out the temperature to check it's worked, we have to convert from ASE units to Kelvin\n", - "runner.dynamics.temp / units.kB" + "graphene_ase_omm_sim.dynamics.temp / units.kB" ] }, { @@ -535,7 +725,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 22, "metadata": { "pycharm": { "is_executing": false @@ -580,7 +770,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.5" + "version": "3.12.0" }, "pycharm": { "stem_cell": { diff --git a/examples/ase/openmm_nanotube.ipynb b/examples/ase/ase_openmm_nanotube.ipynb similarity index 79% rename from examples/ase/openmm_nanotube.ipynb rename to examples/ase/ase_openmm_nanotube.ipynb index dd327c7de..5b45f6efc 100644 --- a/examples/ase/openmm_nanotube.ipynb +++ b/examples/ase/ase_openmm_nanotube.ipynb @@ -11,14 +11,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "In this notebook, we run a pre-prepared OpenMM simulation of nanotube with ASE, and serve it for interactive molecular dynamics with NanoVer. \n", + "In this notebook, we run a pre-prepared OpenMM simulation of methane molecule and a carbon nanotube using ASE, serving it for interactive molecular dynamics using NanoVer.\n", "\n", - "We'll then connect a client running NGLView to it and apply some interactive forces directly from the notebook" + "We'll then connect NanoVer's NGLView client to it and apply some interactive forces directly from the notebook" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2019-06-06T16:04:25.392952Z", @@ -40,7 +40,8 @@ }, "outputs": [], "source": [ - "from nanover.ase.openmm import ASEOpenMMRunner" + "from nanover.omni import OmniRunner\n", + "from nanover.omni.ase_omm import ASEOpenMMSimulation" ] }, { @@ -90,14 +91,22 @@ } }, "source": [ - "Let's load in the NanoVer OpenMM XML file - this file is the OpenMM System XML file, with a PDB file added to it so we can have the topology and simulation in one file.\n", + "First, we need to create an `ASEOpenMMSimulation` for our methane and nanotube system. \n", + "\n", + "Let's do so by loading in a pre-prepared NanoVer OpenMM XML file, which contains:\n", + "- the PDB file\n", + "- the OpenMM XML file, containing:\n", + " - the System\n", + " - the Integrator\n", + "\n", + "This format ensures that the whole simulation can be specified in a single file. \n", "\n", - "The `ASEOpenMMRunner` class is designed to take this file and set up interactive molecular dynamics with typical settings (see [the neuraminidase example](./openmm_neuraminidase.ipynb) for an example of more advanced set up)." + "The `ASEOpenMMSimulation` class takes the pre-prepared input file and creates a simulation object that can then be served for interactive molecular dynamics using OpenMM via ASE. For an example of a more advanced setup, see [our neuraminidase notebook](./ase_openmm_neuraminidase.ipynb)." ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2019-06-06T16:04:25.397984Z", @@ -119,12 +128,20 @@ }, "outputs": [], "source": [ - "input_xml = \"openmm_files/nanotube.xml\"" + "input_xml = \"openmm_files/nanotube.xml\"\n", + "nanotube_simulation = ASEOpenMMSimulation.from_xml_path(input_xml)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we have our simulation ready, we can set up our NanoVer server to run the simulation. We run interactive ASE-OpenMM simulations in NanoVer using the `OmniRunner` class, which is in charge of serving and running the simulation." ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 3, "metadata": { "ExecuteTime": { "end_time": "2019-06-06T16:04:25.493146Z", @@ -156,7 +173,9 @@ " imd_runner.close()\n", "except NameError:\n", " pass\n", - "imd_runner = ASEOpenMMRunner.from_xml(input_xml)" + "imd_runner = OmniRunner.with_basic_server(nanotube_simulation, name=\"nanotube-ase-omm-server\")\n", + "imd_runner.next()\n", + "imd_runner.pause()" ] }, { @@ -168,28 +187,39 @@ "name": "stdout", "output_type": "stream", "text": [ - "jon: NanoVer iMD Server: serving at [::]:38801\n" + "nanotube-ase-omm-server: serving at [::]:38801\n" ] } ], "source": [ - "print(f'{imd_runner.name}: serving at {imd_runner.address}:{imd_runner.port}')" + "print(f'{imd_runner.app_server.name}: serving at {imd_runner.app_server.address}:{imd_runner.app_server.port}')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Run a few steps of MD to check it's working" + "As we are running the OpenMM simulation via ASE, we can use the ASE functionality to run a few simulation steps to check that everything is working:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "imd_runner.run(10)" + "nanotube_simulation.dynamics.run(10)" ] }, { @@ -209,7 +239,7 @@ } ], "source": [ - "imd_runner.dynamics.get_number_of_steps()" + "nanotube_simulation.dynamics.get_number_of_steps()" ] }, { @@ -220,7 +250,7 @@ { "data": { "text/plain": [ - "28.868825418945786" + "28.686632914392266" ] }, "execution_count": 7, @@ -229,7 +259,8 @@ } ], "source": [ - "imd_runner.dynamics.atoms.get_potential_energy()" + "# Note that this is the energy in eV, not kJ mol-1 (the standard units of ASE are different to those of OpenMM and NanoVer)\n", + "nanotube_simulation.dynamics.atoms.get_potential_energy()" ] }, { @@ -260,28 +291,10 @@ { "cell_type": "code", "execution_count": 8, - "metadata": { - "ExecuteTime": { - "end_time": "2019-06-06T16:04:25.725110Z", - "start_time": "2019-06-06T16:04:25.701637Z" - }, - "extensions": { - "jupyter_dashboards": { - "version": 1, - "views": { - "grid_default": { - "hidden": true - }, - "report_default": { - "hidden": true - } - } - } - } - }, + "metadata": {}, "outputs": [], "source": [ - "imd_runner.run()" + "imd_runner.play()" ] }, { @@ -314,7 +327,7 @@ { "data": { "text/plain": [ - "29.959219104815393" + "8.840425309617657" ] }, "execution_count": 9, @@ -323,7 +336,7 @@ } ], "source": [ - "imd_runner.dynamics.get_time()" + "nanotube_simulation.dynamics.get_time()" ] }, { @@ -380,7 +393,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "c7e75d687ab54c4fb1a2e8ce7047ffdf", + "model_id": "51e04607053d42eaaad8799b2645d48b", "version_major": 2, "version_minor": 0 }, @@ -390,16 +403,13 @@ "output_type": "display_data" } ], - "source": "from nanover.nglview import NGLClient" + "source": [ + "from nanover.nglview import NGLClient" + ] }, { "cell_type": "code", - "execution_count": null, "metadata": { - "ExecuteTime": { - "end_time": "2019-06-06T16:04:26.572274Z", - "start_time": "2019-06-06T16:04:26.482553Z" - }, "extensions": { "jupyter_dashboards": { "version": 1, @@ -418,34 +428,20 @@ } } }, - "outputs": [], "source": [ - "client = NGLClient.connect_to_single_server(port=imd_runner.port)" - ] + "client = NGLClient.connect_to_single_server(port=imd_runner.app_server.port)" + ], + "outputs": [], + "execution_count": null }, { "cell_type": "code", - "execution_count": 12, "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "c83cd8c75e6a4c30b9d6cfc9828c1352", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "NGLWidget()" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], "source": [ "client.view" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -606,9 +602,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "* The [NGLViewer notebook](../basics/nanover_nglview.ipynb) is a smaller notebook designed for visualizing your own simulations.\n", - "* Set up an OpenMM simulation with an AMBER file for a [protein-ligand system](openmm_neuraminidase.ipynb) and simulate it in NanoVer\n", - "* Set up a simulation of a [graphene sheet](openmm_graphene.ipynb) with parameters than can be controlled from the jupyter notebook. \n", + "* The [NGLViewer notebook](nanover_nglview.ipynb) is a smaller notebook designed for visualizing your own simulations.\n", + "* Set up an OpenMM simulation with an AMBER file for a [protein-ligand system](ase_openmm_neuraminidase.ipynb) and simulate it in NanoVer\n", + "* Set up a simulation of a [graphene sheet](ase_openmm_graphene.ipynb) with parameters than can be controlled from the jupyter notebook.\n", "* Visualize an [LSD receptor in a membrane](../mdanalysis/mdanalysis_lsd.ipynb) structure with MDAnalysis and NanoVer " ] }, @@ -656,7 +652,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.5" + "version": "3.12.0" }, "pycharm": { "stem_cell": { diff --git a/examples/ase/openmm_neuraminidase.ipynb b/examples/ase/ase_openmm_neuraminidase.ipynb similarity index 79% rename from examples/ase/openmm_neuraminidase.ipynb rename to examples/ase/ase_openmm_neuraminidase.ipynb index 326f580a9..5581d2eaf 100644 --- a/examples/ase/openmm_neuraminidase.ipynb +++ b/examples/ase/ase_openmm_neuraminidase.ipynb @@ -106,7 +106,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "/home/jon/.mambaforge/envs/nanover/lib/python3.10/site-packages/openmm/app/internal/amber_file_parser.py:1165: UserWarning: Non-optimal GB parameters detected for GB model OBC2\n", + "/opt/homebrew/Caskroom/miniforge/base/envs/nanover-dev/lib/python3.12/site-packages/openmm/app/internal/amber_file_parser.py:1168: UserWarning: Non-optimal GB parameters detected for GB model OBC2\n", " warnings.warn(\n" ] } @@ -209,23 +209,23 @@ "output_type": "stream", "text": [ "#\"Step\",\"Potential Energy (kJ/mole)\",\"Temperature (K)\"\n", - "100,-39540.22208032991,172.0368640414814\n", - "200,-38037.813714933814,176.83360536377518\n", - "300,-36957.922669540145,186.50658465938525\n", - "400,-36537.67326410094,202.19986509983823\n", - "500,-35849.644951178234,213.220791136058\n", - "600,-35094.31895770768,219.77104104177\n", - "700,-34314.613707171666,224.59222300857243\n", - "800,-33729.39031191092,229.9811264977871\n", - "900,-33440.23194823894,239.22371410931424\n", - "1000,-32960.056166880924,244.41153511927288\n" + "500,-36040.71460745954,211.99360761693245\n", + "1000,-32952.37799857282,245.63783128257157\n", + "1500,-31100.121986609927,265.3944013729671\n", + "2000,-30437.55245230817,277.6407132964383\n", + "2500,-29802.374489051334,286.6963348786343\n", + "3000,-29126.247352820865,287.3089727023475\n", + "3500,-29039.515907508365,287.1444284209067\n", + "4000,-29376.106544715396,293.2596440578256\n", + "4500,-29068.517067176334,302.23661957760527\n", + "5000,-28971.829567176334,294.6464976216505\n" ] } ], "source": [ - "simulation.reporters.append(app.StateDataReporter(sys.stdout, 100, step=True,\n", + "simulation.reporters.append(app.StateDataReporter(sys.stdout, 500, step=True,\n", " potentialEnergy=True, temperature=True))\n", - "simulation.step(1000)" + "simulation.step(5000)" ] }, { @@ -250,15 +250,7 @@ "cell_type": "code", "execution_count": 11, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Warning: importing 'simtk.openmm' is deprecated. Import 'openmm' instead.\n" - ] - } - ], + "outputs": [], "source": [ "from nanover.openmm.serializer import serialize_simulation\n", "\n", @@ -313,9 +305,7 @@ "execution_count": 12, "metadata": {}, "outputs": [], - "source": [ - "from nanover.ase.openmm import OpenMMCalculator" - ] + "source": "from nanover.omni.ase_omm import OpenMMCalculator" }, { "cell_type": "code", @@ -352,7 +342,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now we've got an ASE Atoms object, and a calculator, we can set up NanoVer with ASE as [usual](./basic_example.ipynb). \n", + "Now we've got an ASE Atoms object, and a calculator, we can set up NanoVer with ASE as [usual](./ase_basic_example.ipynb).\n", "The only difference here is that we swap out the default way of sending frames with a specially made one, `openmm_ase_frame_adaptor`, for OpenMM that knows about OpenMM topology" ] }, @@ -373,9 +363,8 @@ "metadata": {}, "outputs": [], "source": [ - "from nanover.ase import NanoverASEDynamics\n", - "from nanover.app import NanoverImdApplication\n", - "from nanover.ase.openmm.runner import openmm_ase_frame_adaptor" + "from nanover.omni import OmniRunner\n", + "from nanover.omni.ase_omm import ASEOpenMMSimulation, openmm_ase_frame_adaptor" ] }, { @@ -384,8 +373,8 @@ "metadata": {}, "outputs": [], "source": [ - "nanover_server = NanoverImdApplication.basic_server(port=0)\n", - "imd = NanoverASEDynamics(nanover_server,dynamics, frame_method=openmm_ase_frame_adaptor)" + "neuraminidase_simulation = ASEOpenMMSimulation.from_simulation(dynamics)\n", + "imd_runner = OmniRunner.with_basic_server(neuraminidase_simulation, name=\"neuraminidase-ase-omm-sim\")" ] }, { @@ -396,7 +385,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 18, @@ -405,7 +394,7 @@ } ], "source": [ - "imd.atoms.get_calculator()" + "neuraminidase_simulation.simulation.atoms.get_calculator()" ] }, { @@ -419,9 +408,21 @@ "cell_type": "code", "execution_count": 19, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "imd.run(10)" + "neuraminidase_simulation.simulation.run(10)\n", + "neuraminidase_simulation.simulation.get_number_of_steps()" ] }, { @@ -432,7 +433,7 @@ { "data": { "text/plain": [ - "-416.8531416057526" + "-391.6982377566493" ] }, "execution_count": 20, @@ -441,7 +442,7 @@ } ], "source": [ - "imd.atoms.get_potential_energy()" + "neuraminidase_simulation.simulation.atoms.get_potential_energy()" ] }, { @@ -453,11 +454,40 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 22, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "exception in simulation\n", + "Traceback (most recent call last):\n", + " File \"/Users/harrystroud/IRL/nanover-protocol/python-libraries/nanover-omni/src/nanover/omni/omni.py\", line 236, in run\n", + " self.simulation.load()\n", + " File \"/Users/harrystroud/IRL/nanover-protocol/python-libraries/nanover-omni/src/nanover/omni/ase_omm.py\", line 98, in load\n", + " self.openmm_calculator = OpenMMCalculator(self.simulation)\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"/Users/harrystroud/IRL/nanover-protocol/python-libraries/nanover-ase/src/nanover/ase/openmm/calculator.py\", line 37, in __init__\n", + " self.context = self.simulation.context\n", + " ^^^^^^^^^^^^^^^^^^^^^^^\n", + "AttributeError: 'Langevin' object has no attribute 'context'\n", + "exception in simulation\n", + "Traceback (most recent call last):\n", + " File \"/Users/harrystroud/IRL/nanover-protocol/python-libraries/nanover-omni/src/nanover/omni/omni.py\", line 236, in run\n", + " self.simulation.load()\n", + " File \"/Users/harrystroud/IRL/nanover-protocol/python-libraries/nanover-omni/src/nanover/omni/ase_omm.py\", line 98, in load\n", + " self.openmm_calculator = OpenMMCalculator(self.simulation)\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"/Users/harrystroud/IRL/nanover-protocol/python-libraries/nanover-ase/src/nanover/ase/openmm/calculator.py\", line 37, in __init__\n", + " self.context = self.simulation.context\n", + " ^^^^^^^^^^^^^^^^^^^^^^^\n", + "AttributeError: 'Langevin' object has no attribute 'context'\n" + ] + } + ], "source": [ - "imd.run()" + "imd_runner.next()" ] }, { @@ -497,7 +527,7 @@ "outputs": [], "source": [ "from nanover.app import NanoverImdClient\n", - "client = NanoverImdClient.connect_to_single_server(port=nanover_server.port)\n", + "client = NanoverImdClient.connect_to_single_server(port=imd_runner.app_server.port)\n", "client.subscribe_to_frames()\n", "client.wait_until_first_frame();" ] @@ -672,12 +702,12 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 31, "metadata": {}, "outputs": [], "source": [ - "imd.close()\n", - "nanover_server.close()" + "imd_runner.close()\n", + "#nanover_server.close()" ] }, { @@ -691,7 +721,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "* Set up an OpenMM simulation of [graphene](./openmm_graphene.ipynb) with restraints and add UI and custom commands in the notebook " + "* Set up an OpenMM simulation of [graphene](./ase_openmm_graphene.ipynb) with restraints and add UI and custom commands in the notebook" ] }, { @@ -738,7 +768,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.12.0" }, "pycharm": { "stem_cell": { diff --git a/examples/openmm/openmm_nanotube.ipynb b/examples/openmm/openmm_nanotube.ipynb index 0cde0c856..47066441b 100644 --- a/examples/openmm/openmm_nanotube.ipynb +++ b/examples/openmm/openmm_nanotube.ipynb @@ -11,7 +11,7 @@ "source": [ "In this notebook, we run a pre-prepared OpenMM simulation of a methane molecule and a carbon nanotube, serving it for interactive molecular dynamics using NanoVer. \n", "\n", - "We'll then connect a client running NGLView to it and apply some interactive forces directly from the notebook" + "We'll then connect a NanoVer's NGLView client to it and apply some interactive forces directly from the notebook" ] }, { diff --git a/examples/openmm/openmm_polyalanine.ipynb b/examples/openmm/openmm_polyalanine.ipynb index eae42ba28..58c1ea71f 100644 --- a/examples/openmm/openmm_polyalanine.ipynb +++ b/examples/openmm/openmm_polyalanine.ipynb @@ -6,7 +6,7 @@ "source": [ "# Run an OpenMM simulation with NanoVer \n", "\n", - "NanoVer can run OpenMM simulations in two ways: either using [ASE as an interface](../ase/openmm_nanotube.ipynb), or directly using [OpenMM mechanisms](./openmm_nanotube.ipynb). Using the ASE interface offers the most flexibility to customise a workflow; in the [ASE OpenMM graphene example](../ase/openmm_graphene.ipynb) we control the physics parameters of a running simulation from a Jupyter notebook. The ASE interface misses some specific OpenMM features, though; one of the most significant being holonomic constraints. Using the OpenMM mechanisms without ASE as an interface gives access to all of OpenMM features, but may require more work for some customisation needs. Here, we demonstrate how to to use the OpenMM mechanisms with NanoVer." + "NanoVer can run OpenMM simulations in two ways: either using [ASE as an interface](../ase/ase_openmm_nanotube.ipynb), or directly using [OpenMM mechanisms](./openmm_nanotube.ipynb). Using the ASE interface offers the most flexibility to customise a workflow; in the [ASE OpenMM graphene example](../ase/ase_openmm_graphene.ipynb) we control the physics parameters of a running simulation from a Jupyter notebook. The ASE interface misses some specific OpenMM features, though; one of the most significant being holonomic constraints. Using the OpenMM mechanisms without ASE as an interface gives access to all of OpenMM features, but may require more work for some customisation needs. Here, we demonstrate how to to use the OpenMM mechanisms with NanoVer." ] }, {