Skip to content

Commit

Permalink
Demo widget integration, add notebook
Browse files Browse the repository at this point in the history
  • Loading branch information
rly committed Oct 16, 2023
1 parent 07c5372 commit f6c1c7a
Show file tree
Hide file tree
Showing 7 changed files with 220 additions and 0 deletions.
6 changes: 6 additions & 0 deletions {{ cookiecutter.namespace }}/NEXTSTEPS.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ replaced or removed.
the file, and confirm the read data types are equal to the written data types) is
highly encouraged.

7. Define custom visualization widgets for your new extension data types in
`src/pynwb/widgets` so that the visualizations can be displayed with
[nwbwidgets](https://github.com/NeurodataWithoutBorders/nwbwidgets). Register your widget
with your extension Python class in `src/pynwb/__init__.py` or wherever your extension
Python class is defined.

8. You may need to modify `pyproject.toml` and re-run `python -m pip install -e .` if you
use any dependencies.

Expand Down
165 changes: 165 additions & 0 deletions {{ cookiecutter.namespace }}/notebooks/example.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "174c5018-1c0a-4f55-899d-049bb87f63d5",
"metadata": {},
"source": [
"# Example demonstration of the example TetrodeSeries extension neurodata type\n",
"\n",
"TODO: Update this notebook with an example usage of your extension"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "02798a80-faea-4b75-aa97-70afad90fe27",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"\n",
"from pynwb import NWBHDF5IO, NWBFile\n",
"from pynwb.testing.mock.device import mock_Device\n",
"from pynwb.testing.mock.ecephys import mock_ElectrodeGroup, mock_ElectrodeTable\n",
"from pynwb.testing.mock.file import mock_NWBFile\n",
"\n",
"from {{ cookiecutter.py_pkg_name }} import TetrodeSeries\n",
"\n",
"\n",
"def set_up_nwbfile(nwbfile: NWBFile = None):\n",
" \"\"\"Create an NWBFile with a Device, ElectrodeGroup, and 10 electrodes in the ElectrodeTable.\"\"\"\n",
" nwbfile = nwbfile or mock_NWBFile()\n",
" device = mock_Device(nwbfile=nwbfile)\n",
" electrode_group = mock_ElectrodeGroup(device=device, nwbfile=nwbfile)\n",
" _ = mock_ElectrodeTable(n_rows=10, group=electrode_group, nwbfile=nwbfile)\n",
"\n",
" return nwbfile"
]
},
{
"cell_type": "markdown",
"id": "32be75e4-8fe9-401d-a613-8080f357d5f0",
"metadata": {},
"source": [
"Create an `NWBFile` object and a `TetrodeSeries` object and add the `TetrodeSeries` object to the `NWBFile`"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "dcd2c070-f2c9-4ffc-8637-25ec3e6f7b37",
"metadata": {},
"outputs": [],
"source": [
"nwbfile = set_up_nwbfile()\n",
"\n",
"all_electrodes = nwbfile.create_electrode_table_region(\n",
" region=list(range(0, 10)),\n",
" description=\"all the electrodes\",\n",
")\n",
"\n",
"data = np.random.rand(100, 10)\n",
"tetrode_series = TetrodeSeries(\n",
" name=\"TetrodeSeries\",\n",
" description=\"description\",\n",
" data=data,\n",
" rate=1000.0,\n",
" electrodes=all_electrodes,\n",
" trode_id=1,\n",
")\n",
"\n",
"nwbfile.add_acquisition(tetrode_series)"
]
},
{
"cell_type": "markdown",
"id": "077a8d86-9d03-40e3-b60a-c837ecb643a7",
"metadata": {},
"source": [
"Visualize the TetrodeSeries object with the `nwbwidgets` package using the custom widget defined in the extension"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1363282d-1a32-447d-9ca3-fc2360785cc2",
"metadata": {},
"outputs": [],
"source": [
"from nwbwidgets import nwb2widget, default_neurodata_vis_spec\n",
"vis_spec = default_neurodata_vis_spec\n",
"vis_spec[TetrodeSeries] = TetrodeSeries.widget\n",
"nwb2widget(nwbfile, vis_spec)"
]
},
{
"cell_type": "markdown",
"id": "ac894fae-6c5e-4a3d-be1e-d158aef084a4",
"metadata": {},
"source": [
"Write the file with the extension neurodata type to disk"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2fdaf978-6f95-4871-b26c-dad4bb62da42",
"metadata": {},
"outputs": [],
"source": [
"with NWBHDF5IO(\"test.nwb\", \"w\") as io:\n",
" io.write(nwbfile)"
]
},
{
"cell_type": "markdown",
"id": "a30660a3-8e64-4c5e-963d-6ecd7e31897e",
"metadata": {},
"source": [
"Read the NWB file from disk and print the `TetrodeSeries` object"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "00e38084-b55e-4c7a-ac89-8b10e43f41c1",
"metadata": {},
"outputs": [],
"source": [
"with NWBHDF5IO(\"test.nwb\", \"r\") as io:\n",
" read_nwbfile = io.read()\n",
" print(read_nwbfile.acquisition[\"TetrodeSeries\"])"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b36569b2-09d1-4281-bf4c-fb602e53636c",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.11.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
1 change: 1 addition & 0 deletions {{ cookiecutter.namespace }}/requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ black==23.9.1
codespell==2.2.6
coverage==7.3.2
hdmf-docutils==0.4.5
nwbwidgets==0.11.3
pre-commit==3.4.0
pytest==7.4.2
pytest-cov==4.1.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,22 @@
# `@register_class("TetrodeSeries", "{{ cookiecutter.namespace }}")`
TetrodeSeries = get_class("TetrodeSeries", "{{ cookiecutter.namespace }}")

# If NWBWidgets is installed, create a custom widget for the TetrodeSeries
# neurodata type that displays the trode_id field
# Usage:
# from nwbwidgets import nwb2widget, default_neurodata_vis_spec
# vis_spec = default_neurodata_vis_spec
# vis_spec[TetrodeSeries] = TetrodeSeries.widget
# nwb2widget(nwbfile, vis_spec)
try:
from .widgets import TetrodeSeriesWidget

# add the widget class to the TetrodeSeries class
TetrodeSeries.widget = TetrodeSeriesWidget

except ImportError:
# NWBWidgets is not installed, so we cannot create a new widget
pass

# Remove these functions from the package
del load_namespaces, get_class
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Add widgets that define custom visualizations for your extension, so that
the visualizations can be displayed with
[nwbwidgets](https://github.com/NeurodataWithoutBorders/nwbwidgets).
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .tetrode_series_widget import TetrodeSeriesWidget # noqa: F401
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from nwbwidgets.ecephys import ElectricalSeriesWidget
from ipywidgets import widgets

from .. import TetrodeSeries


class TetrodeSeriesWidget(ElectricalSeriesWidget): # this is an HBox
def __init__(self, tetrode_series: TetrodeSeries, **kwargs):
super().__init__(electrical_series=tetrode_series, **kwargs)
vbox = widgets.VBox(
children=[
self._create_trode_id_box(tetrode_series),
widgets.HBox(children=list(self.children)),
]
)
self.children = [vbox]

def _create_trode_id_box(self, tetrode_series: TetrodeSeries):
field_lay = widgets.Layout(
max_height="40px",
max_width="600px",
min_height="30px",
min_width="130px",
)
key = widgets.Label("trode_id:", layout=field_lay)
val = widgets.Label(str(tetrode_series.trode_id), layout=field_lay)
return widgets.HBox(children=[key, val])

0 comments on commit f6c1c7a

Please sign in to comment.