From 0574d085a7917b3498d375158f338ad080438dee Mon Sep 17 00:00:00 2001 From: PythonFZ Date: Wed, 4 Oct 2023 22:46:02 +0200 Subject: [PATCH] load scene when both client and webpage are ready --- examples/md.ipynb | 105 ++++++++++++++++++++++++++++++++++++++++++ zndraw/app.py | 9 ++-- zndraw/static/main.js | 16 ++----- zndraw/zndraw.py | 8 ++-- 4 files changed, 116 insertions(+), 22 deletions(-) create mode 100644 examples/md.ipynb diff --git a/examples/md.ipynb b/examples/md.ipynb new file mode 100644 index 000000000..d75e7f4a9 --- /dev/null +++ b/examples/md.ipynb @@ -0,0 +1,105 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Molecular Dynamics Simulation\n", + "\n", + "In this example we will run an MD simulation using ASE and visualise it using ZnDraw." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from zndraw import ZnDraw\n", + "\n", + "from ase.lattice.cubic import FaceCenteredCubic\n", + "from ase.md.velocitydistribution import MaxwellBoltzmannDistribution\n", + "from ase.md.verlet import VelocityVerlet\n", + "from ase import units\n", + "\n", + "from ase.calculators.emt import EMT\n", + "size = 2\n", + "\n", + "# Set up a crystal\n", + "atoms = FaceCenteredCubic(directions=[[1, 0, 0], [0, 1, 0], [0, 0, 1]],\n", + " symbol=\"Cu\",\n", + " size=(size, size, size),\n", + " pbc=True)\n", + "\n", + "# Describe the interatomic interactions with the Effective Medium Theory\n", + "atoms.calc = EMT()\n", + "\n", + "# Set the momenta corresponding to T=300K\n", + "MaxwellBoltzmannDistribution(atoms, temperature_K=300)\n", + "\n", + "# We want to run MD with constant energy using the VelocityVerlet algorithm.\n", + "dyn = VelocityVerlet(atoms, 5 * units.fs) # 5 fs time step.\n", + "\n", + "\n", + "def printenergy(a=atoms): # store a reference to atoms in the definition.\n", + " \"\"\"Function to print the potential, kinetic and total energy.\"\"\"\n", + " epot = a.get_potential_energy() / len(a)\n", + " ekin = a.get_kinetic_energy() / len(a)\n", + " print('Energy per atom: Epot = %.3feV Ekin = %.3feV (T=%3.0fK) '\n", + " 'Etot = %.3feV' % (epot, ekin, ekin / (1.5 * units.kB), epot + ekin))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "vis = ZnDraw(url=\"http://localhost:1234\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Now run the dynamics\n", + "\n", + "# dyn.attach(printenergy, interval=1)\n", + "dyn.attach(lambda: vis.append(atoms), interval=1)\n", + "printenergy()\n", + "dyn.run(200)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "zndraw", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/zndraw/app.py b/zndraw/app.py index aacc45690..aa4636841 100644 --- a/zndraw/app.py +++ b/zndraw/app.py @@ -56,9 +56,12 @@ def on_join(data): """Join a room.""" try: join_room(session["uuid"]) + print(f"Client for webpage joined room {session['uuid']}") except KeyError: session["uuid"] = data["uuid"] join_room(session["uuid"]) + print(f"Client from 'zndraw.ZnDraw' joined room {session['uuid']}") + emit("join", {}, include_self=False, to=session["uuid"]) @app.route("/exit") @@ -186,12 +189,6 @@ class Scene(BaseModel): return schema -@io.on("atoms:request") -def atoms_request(url): - """Return the atoms.""" - emit("atoms:request", url, include_self=False, to=session["uuid"]) - - @io.on("modifier:run") def modifier_run(data): emit("modifier:run", data, include_self=False, to=session["uuid"]) diff --git a/zndraw/static/main.js b/zndraw/static/main.js index bb1eb65ee..ba3684672 100644 --- a/zndraw/static/main.js +++ b/zndraw/static/main.js @@ -28,23 +28,15 @@ function main() { // creata a function displayIncomingAtoms that calls cache.get_length(), if larger 1 call world.setStep(0), else setTimerout(displayIncomingAtoms, 1000) - const displayIncomingAtoms = () => { - cache.get_length(); - if (cache.get_length() > 0) { - world.setStep(0); - document.getElementById("atom-spinner").style.display = "none"; - } else { - setTimeout(displayIncomingAtoms, 100); - } - }; - - socket.emit("atoms:request", window.location.href, () => { - displayIncomingAtoms(); + socket.on("join", () => { + socket.emit("join", {}); // we send an ACK to the server, so that it can send us the atoms }); socket.on("message:log", (msg) => { console.log(msg); }); + + document.getElementById("atom-spinner").style.display = "none"; } main(); diff --git a/zndraw/zndraw.py b/zndraw/zndraw.py index df3936f57..5092470b5 100644 --- a/zndraw/zndraw.py +++ b/zndraw/zndraw.py @@ -45,7 +45,7 @@ def on_answer(data): @dataclasses.dataclass class FileIO: - name: str + name: str = None start: int = 0 stop: int = None step: int = 1 @@ -59,7 +59,7 @@ class ZnDraw(collections.abc.MutableSequence): bonds_calculator: ASEComputeBonds = dataclasses.field( default_factory=ASEComputeBonds ) - file: FileIO = None + file: FileIO = dataclasses.field(default_factory=FileIO) wait: bool = False token: str = "default" @@ -99,8 +99,8 @@ def __post_init__(self): ) self.socket.on( - "atoms:request", - lambda url: self.read( + "join", + lambda *args: self.read( self.file.name, self.file.start, self.file.stop, self.file.step ), )