Skip to content

Commit

Permalink
in progress activity
Browse files Browse the repository at this point in the history
  • Loading branch information
ljwoods2 committed Nov 29, 2024
1 parent cdd66e1 commit f4ca34d
Show file tree
Hide file tree
Showing 7 changed files with 476 additions and 129 deletions.
8 changes: 6 additions & 2 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@
"build": { "dockerfile": "Dockerfile" },
"customizations": {
"vscode": {
"extensions": ["ms-python.python", "ms-toolsai.jupyter"]
"extensions": ["ms-python.python", "ms-toolsai.jupyter"],
"settings": {
"python.defaultInterpreterPath": "/opt/conda/envs/workshop/bin/python",
"jupyter.defaultKernel": "workshop"
}
}
},
"postStartCommand": ". /opt/conda/etc/profile.d/conda.sh && conda activate workshop"
"postStartCommand": ". /opt/conda/etc/profile.d/conda.sh && conda activate workshop && python -m ipykernel install --user --name workshop --display-name 'workshop'"
}
250 changes: 142 additions & 108 deletions activity/activity.ipynb

Large diffs are not rendered by default.

48 changes: 48 additions & 0 deletions activity/graph_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import matplotlib.pyplot as plt
from IPython.display import display, clear_output
import numpy as np


class LiveTimeseriesGraph:
def __init__(self, time_window, dt, title="", y_label="", legend_label=""):
plt.ion()
self.time_window = time_window
self.n_times = (int)(time_window / dt)
self.time = np.zeros(self.n_times, dtype=np.float32)
self.vals = np.zeros(self.n_times, dtype=np.float32)
self.dt = dt

self.fig, self.ax = plt.subplots(figsize=(10, 6))
(self.p1,) = self.ax.plot([], [], label=legend_label)
self.ax.set_xlabel("Time (ps)")
self.ax.set_ylabel(y_label)
self.ax.set_xlim(0, time_window)

self.ax.set_title(title)
self.ax.legend()
self.ax.grid(True)

self.i = 0

def update(self, time, val):
self.idx = self.i % self.n_times
self.time[self.idx] = time
self.vals[self.idx] = val

if self.idx == 0:
self.ax.set_xlim(
self.time[self.idx],
self.time[self.idx] + self.n_times * self.dt,
)

valid_indices = range(0, self.idx + 1)

self.ax.set_ylim(
np.min(self.vals[valid_indices]) - 1, np.max(self.vals) + 1
)

self.p1.set_data(self.time[valid_indices], self.vals[valid_indices])
clear_output(wait=True)
display(self.fig)

self.i += 1
23 changes: 20 additions & 3 deletions activity/run.sh
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
#!/bin/bash

## TMP
source /usr/local/gromacs/bin/GMXRC

## WAIT UNTIL PORT IS OPEN
SECONDS=0
while lsof -n -i :8889; do
echo "Waiting for port 8889 to open"
sleep 1

if [ $SECONDS -ge 30 ]; then
echo "Timeout reached. Port 8889 did not open."
exit 1
fi
done

mkdir -p sample_simulation
cd sample_simulation

## RUN GROMPP
if [ ! -f sample_simulation/topol.tpr ]; then
echo "Running grompp"
gmx grompp -f imd.mdp -c start.gro -p topol.top -o >& grompp.out
fi
echo "Starting mdrun"
# modify gromacs execution string according to available resources
# here we use 2 parallel threads
gmx mdrun -v -nt 2 -imdwait -imdport 8889

## START MDRUN
gmx mdrun -v -nt 1 -imdwait -imdport 8889
cd ..
2 changes: 1 addition & 1 deletion activity/sample_simulation/imd.mdp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pbc = xyz ; 3-D PBC
; Velocity generation
gen_vel = no
; IMD group
IMD-group = Protein
IMD-group = System
IMD-version = 3
IMD-nst = 10
IMD-time = yes
Expand Down
15 changes: 0 additions & 15 deletions activity/utils.py

This file was deleted.

259 changes: 259 additions & 0 deletions streaming-101/imd-mda/imd-mda.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## IMDClient package architecture\n",
"\n",
"## TODO:\n",
"\n",
"a context manager?\n",
"better error messages\n",
"remove unprofessional log messages\n",
"add docs for some of the messages (timeout at least)\n",
"make a nice diagram"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# ./run.sh \n",
"\n",
"import imdclient\n",
"\n",
"client = imdclient.IMDClient(\"localhost\", 8889, n_atoms=100)\n",
"\n",
"info = client.get_imdsessioninfo()\n",
"## TODO: show what's in dict\n",
"## design principle: reduce redundancy in data entry\n",
"\n",
"client.stop()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"client = imdclient.IMDClient(\"localhost\", 8889, n_atoms=100)\n",
"\n",
"## Design principle: simplest possible API so anyone can use it\n",
"## Even if you hate mdanalysis, you can use this\n",
"\n",
"while True:\n",
" try:\n",
" frame = client.get_imdframe()\n",
" except EOFError:\n",
" break\n",
"\n",
"client.stop()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Options"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"client = imdclient.IMDClient(\"localhost\", 8889, n_atoms=100, timeout=10)\n",
"\n",
"while True:\n",
" try:\n",
" ## Add a little wait time widget\n",
" frame = client.get_imdframe()\n",
" except EOFError:\n",
" break\n",
"\n",
"client.stop()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The buffer size is optional, pausing is automatic"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# ./run.sh\n",
"\n",
"import time\n",
"import logging\n",
"\n",
"logger = logging.getLogger(\"imdclient.IMDClient\")\n",
"# Modify to use \n",
"# file_handler = logging.FileHandler(\"gromacs_test.log\")\n",
"formatter = logging.Formatter(\n",
" \"%(asctime)s - %(name)s - %(levelname)s - %(message)s\"\n",
")\n",
"# file_handler.setFormatter(formatter)\n",
"# logger.addHandler(file_handler)\n",
"# logger.setLevel(logging.DEBUG)\n",
"\n",
"## Show the logs of the client stopping automatically\n",
"\n",
"client = imdclient.IMDClient(\"localhost\", 8889, n_atoms=100, buffer_size=100)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Reader wraps client, handles its limitations"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from imdclient.IMDREADER import IMDReader\n",
"import MDAnalysis as mda\n",
"\n",
"u = mda.Universe(top, \"imd://localhost:8889\")\n",
"\n",
"for ts in u.trajectory[:]:\n",
" pass\n",
"\n",
"try:\n",
" for ts in u.trajectory[:]:\n",
" pass\n",
"except RuntimeError:\n",
" print(\"A stream is not a file!\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Stepping is allowed, but specifying an end frame isn't"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"ename": "NameError",
"evalue": "name 'top' is not defined",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn[1], line 4\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mimdclient\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mIMDREADER\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m IMDReader\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mMDAnalysis\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mmda\u001b[39;00m\n\u001b[0;32m----> 4\u001b[0m u \u001b[38;5;241m=\u001b[39m mda\u001b[38;5;241m.\u001b[39mUniverse(top, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mimd://localhost:8889\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 6\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m ts \u001b[38;5;129;01min\u001b[39;00m u\u001b[38;5;241m.\u001b[39mtrajectory[:]:\n\u001b[1;32m 7\u001b[0m \u001b[38;5;28;01mpass\u001b[39;00m\n",
"\u001b[0;31mNameError\u001b[0m: name 'top' is not defined"
]
}
],
"source": [
"from imdclient.IMDREADER import IMDReader\n",
"import MDAnalysis as mda\n",
"\n",
"u = mda.Universe(top, \"imd://localhost:8889\")\n",
"\n",
"for ts in u.trajectory[::10]:\n",
" pass"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The client works out of the box with MDAnalysis analysis classes"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from imdclient.IMDREADER import IMDReader\n",
"import MDAnalysis as mda\n",
"from MDAnalysis.analysis.rms import RMSF\n",
"\n",
"u = mda.Universe(top, \"imd://localhost:8889\")\n",
"\n",
"imd_rmsf = RMSF(u.atoms).run()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Running multiple analysis classes on the same stream\n",
"\n",
"We showed you examples earlier that look like this:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## But you can also do this:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from imdclient.IMDREADER import IMDReader\n",
"import MDAnalysis as mda\n",
"from MDAnalysis.analysis.rms import RMSF\n",
"\n",
"r1 = RMSF(u.atoms)\n",
"r2 = RMSF(u.atoms)\n",
"imdclient.StackableAnalysis(u.trajectory, [r1, r2]).run()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "imdclient-test",
"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.12.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

0 comments on commit f4ca34d

Please sign in to comment.