Skip to content

Commit

Permalink
🔥 time-series annotation example
Browse files Browse the repository at this point in the history
  • Loading branch information
jonasvdd committed May 6, 2022
1 parent 1e80f4e commit 61f46fe
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 8 deletions.
5 changes: 3 additions & 2 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ the [basic example notebook](basic_example.ipynb)

### 0.1 Figurewidget example

The [figurewidget example notebook](figurewidget_example.ipynb) utilizes the `FigureWidgetResampler` wrapper to
create a `go.FigureWidget` with dynamic aggregation functionality. A major advantage of this approach is that this does not create a web application, thus not needing to be able to create / forward a network port.
The [figurewidget example notebook](figurewidget_example.ipynb) utilizes the `FigureWidgetResampler` wrapper to create a `go.FigureWidget` with dynamic aggregation functionality. A major advantage of this approach is that this does not create a web application, thus not needing to be able to create / forward a network port.

Additionally, this notebook highlights how to use the `FigureWidget` its on-click callback to utilize plotly for large **time series annotation**.

## 1. Dash apps

Expand Down
133 changes: 127 additions & 6 deletions examples/figurewidget_example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "c478aeb87d6645319e54ba0c3ef2bb27",
"model_id": "f0b23a98e7a24f64b5d2a8d24ae1e96b",
"version_major": 2,
"version_minor": 0
},
Expand Down Expand Up @@ -121,13 +121,134 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### Adjusting the figure data using the `hf_data` property"
"### time-series **annotation** using the on-click callback"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"from ipywidgets import Dropdown\n",
"from IPython.display import display"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "f3390f396a9d46a088290fb5991f3724",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Dropdown(options=('peak', 'through', 'rise', 'fall'), value='peak')"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "e80c27b76cd54fa3bdfe87bb80035941",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"FigureWidgetResampler({\n",
" 'data': [{'name': '<b style=\"color:sandybrown\">[R]</b> noisy sine <i style=\"color:…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Proxy for a label class\n",
"label_dict = {\n",
" \"peak\": {\n",
" \"type\": \"marker\",\n",
" \"trace_index\": 1,\n",
" \"plt_kwargs\": {\n",
" \"mode\": \"markers\", \"marker_symbol\": \"star\", \"marker_size\": 12, \"marker_color\": \"red\"\n",
" }\n",
" },\n",
" \"through\": {\n",
" \"type\": \"marker\",\n",
" \"trace_index\": 2,\n",
" \"plt_kwargs\": {\n",
" \"mode\": \"markers\", \"marker_symbol\": \"cross\", \"marker_size\": 12, \"line_color\": \"orange\"\n",
" }\n",
" },\n",
" \"rise\": {\n",
" \"type\": \"x-range\",\n",
" \"plt_kwargs\": {\n",
" \"line_width\": 0, \"fillcolor\": \"green\", \"opacity\": 0.3\n",
" }\n",
" },\n",
" \"fall\": {\n",
" \"type\": \"x-range\",\n",
" \"plt_kwargs\": {\n",
" \"line_width\": 0, \"fillcolor\": \"purple\", \"opacity\": 0.3\n",
" }\n",
" }\n",
"}\n",
"\n",
"# Create a label selector\n",
"label_selector = Dropdown()\n",
"label_selector.options = list(label_dict.keys())\n",
"\n",
"# Construct the figure\n",
"fw_fig = FigureWidgetResampler()\n",
"fw_fig.add_trace(go.Scattergl(name=\"noisy sine\", opacity=0.8), hf_x=x, hf_y=y)\n",
"for k, v in label_dict.items():\n",
" if v.get(\"type\", \"\").lower() == 'marker':\n",
" fw_fig.add_trace(go.Scattergl(name=k, **v.get(\"plt_kwargs\", {})))\n",
"\n",
"\n",
"# Update logic\n",
"prev_x = []\n",
"point_list = []\n",
"\n",
"def update_point(trace, points, selector):\n",
" global prev_x, point_list\n",
" config = label_dict[label_selector.value]\n",
"\n",
" if config.get(\"type\", \"\") == 'x-range':\n",
" prev_x.append(points.xs[0])\n",
" if len(prev_x) == 2:\n",
" fw_fig.add_vrect(prev_x[0], prev_x[1], **config.get(\"plt_kwargs\", {}))\n",
" prev_x = []\n",
"\n",
" with fw_fig.batch_update():\n",
" if config.get(\"type\", \"\") == 'marker':\n",
" trace_index = config.get(\"trace_index\")\n",
" fw_fig.data[trace_index].x = list(fw_fig.data[trace_index].x) + points.xs\n",
" fw_fig.data[trace_index].y = list(fw_fig.data[trace_index].y) + points.ys\n",
"\n",
"fw_fig.data[0].on_click(update_point)\n",
"\n",
"display(label_selector)\n",
"fw_fig"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Adjusting the figure data using the `hf_data` property"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
Expand All @@ -140,7 +261,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "ed08193852c147f9b0824e4562b6e28a",
"model_id": "02cc8bd1dcdd44ab946cbfbe78821833",
"version_major": 2,
"version_minor": 0
},
Expand All @@ -163,7 +284,7 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -182,13 +303,13 @@
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "6752cdd8dc52457da48f77aa165b44e4",
"model_id": "549137c024764fadafb5343059def47f",
"version_major": 2,
"version_minor": 0
},
Expand Down

0 comments on commit 61f46fe

Please sign in to comment.