Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
droumis committed May 30, 2024
1 parent 0277db3 commit 32d3526
Showing 1 changed file with 116 additions and 0 deletions.
116 changes: 116 additions & 0 deletions examples/gallery/demos/bokeh/eeg_viewer.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,122 @@
"Let's start by simulating some EEG data. We'll create a timeseries for each channel using sine waves with varying frequencies. We'll have two groups *A* and *B* of timeseries that have different amplitudes."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6ac3812a",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import holoviews as hv\n",
"from holoviews.operation.normalization import subcoordinate_group_ranges\n",
"from holoviews.plotting.links import RangeToolLink\n",
"from scipy.stats import zscore\n",
"\n",
"hv.extension('bokeh')\n",
"\n",
"GROUP_EEG = 'EEG'\n",
"GROUP_POS = 'Position'\n",
"N_CHANNELS_EEG = 10\n",
"N_CHANNELS_POS = 3\n",
"N_SECONDS = 5\n",
"SAMPLING_RATE_EEG = 200\n",
"SAMPLING_RATE_POS = 25\n",
"INIT_FREQ = 2 # Initial frequency in Hz\n",
"FREQ_INC = 5 # Frequency increment\n",
"AMPLITUDE_EEG = 100 # EEG amplitude in µV\n",
"AMPLITUDE_POS = 10 # Position amplitude in cm\n",
"\n",
"# Generate time for EEG and position data\n",
"total_samples_eeg = N_SECONDS * SAMPLING_RATE_EEG\n",
"total_samples_pos = N_SECONDS * SAMPLING_RATE_POS\n",
"time_eeg = np.linspace(0, N_SECONDS, total_samples_eeg)\n",
"time_pos = np.linspace(0, N_SECONDS, total_samples_pos)\n",
"\n",
"# Generate EEG timeseries data\n",
"def generate_eeg_data(index):\n",
" return AMPLITUDE_EEG * np.sin(2 * np.pi * (INIT_FREQ + index * FREQ_INC) * time_eeg)\n",
"\n",
"eeg_channels = np.arange(N_CHANNELS_EEG)\n",
"eeg_data = np.array([generate_eeg_data(i) for i in eeg_channels])\n",
"eeg_df = pd.DataFrame(eeg_data.T, index=time_eeg, columns=eeg_channels)\n",
"eeg_df.index.name = 'Time'\n",
"\n",
"# Generate position data\n",
"pos_channels = ['x', 'y', 'z']\n",
"pos_data = AMPLITUDE_POS * np.random.randn(N_CHANNELS_POS, total_samples_pos).cumsum(axis=1)\n",
"pos_df = pd.DataFrame(pos_data.T, index=time_pos, columns=pos_channels)\n",
"pos_df.index.name = 'Time'"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b9bae9af",
"metadata": {},
"outputs": [],
"source": [
"# Define hover tool\n",
"hover = HoverTool(tooltips=[\n",
" (\"Info\", \"@info\"),\n",
" (\"Time\", \"$x s\"),\n",
" (\"Value\", \"$y\")\n",
"])\n",
"\n",
"hover_tooltips = [\n",
" (\"Type\", \"@info\"),\n",
" (\"\")\n",
" (\"Time\", \"$x s\"),\n",
" (\"Value\", \"$y\")\n",
"]\n",
"\n",
"\n",
"amp_dim = hv.Dimension(\"Amplitude\", unit=\"µV\")\n",
"time_dim = hv.Dimension(\"Time\", unit=\"s\")\n",
"\n",
"# EEG data visualization\n",
"eeg_curves = []\n",
"for channel, channel_data in enumerate(eeg_data):\n",
" info = f\"EEG {channel}\"\n",
" ds = hv.Dataset((channel_data.index, channel_data, info), [time_dim, amp_dim, \"Type\", \"Channel\"])\n",
" curve = hv.Curve(ds, time_dim, [amp_dim, \"info\"], group='EEG', label=info)\n",
" curve.opts(\n",
" subcoordinate_y=True, color=\"black\", line_width=1, hover_tooltips=hover_tooltips,\n",
" )\n",
" eeg_curves.append(curve)\n",
"\n",
"eeg_overlay = hv.Overlay(eeg_curves, kdims=\"Channel\").opts(\n",
" xlabel=\"Time (s)\", ylabel=\"Channel\", show_legend=False, aspect=3, responsive=True,\n",
")\n",
"\n",
"# Position data visualization\n",
"position_curves = []\n",
"for i, axis in enumerate(['x', 'y', 'z']):\n",
" info = f\"Position {axis.upper()}\"\n",
" ds = hv.Dataset((time_pos, pos_data[i], info), [\"Time\", \"Position\", \"info\"])\n",
" curve = hv.Curve(ds, \"Time\", [\"Position\", \"info\"], group='Position', label=info)\n",
" curve.opts(\n",
" subcoordinate_y=True, color=\"blue\", line_width=1, tools=[hover],\n",
" )\n",
" position_curves.append(curve)\n",
"\n",
"position_overlay = hv.Overlay(position_curves, kdims=\"Axis\").opts(\n",
" xlabel=\"Time (s)\", ylabel=\"Axis\", show_legend=True, aspect=3, responsive=True,\n",
")\n",
"\n",
"# Combine EEG and position visualizations\n",
"combined_overlay = eeg_overlay * position_overlay\n",
"\n",
"# Apply group-wise normalization\n",
"normalized_overlay = subcoordinate_group_ranges(combined_overlay)\n",
"\n",
"# Display the dashboard\n",
"dashboard = normalized_overlay #opts(merge_tools=False)\n",
"dashboard"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down

0 comments on commit 32d3526

Please sign in to comment.