Skip to content

Instantly share code, notes, and snippets.

@rly
Created October 9, 2023 21:44
Show Gist options
  • Save rly/be7bee420b482b9ddcd084f57cc4115e to your computer and use it in GitHub Desktop.
Save rly/be7bee420b482b9ddcd084f57cc4115e to your computer and use it in GitHub Desktop.
Tests on what is currently possible for modifying an NWB file using PyNWB and h5py
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"id": "16bb28b1-b0d2-4bbb-b653-5582d2035f1d",
"metadata": {},
"source": [
"# Tests on what is currently possible for modifying an NWB file using PyNWB and h5py\n",
"As of October 9, 2023 (pynwb==2.5.0, h5py==3.9.0)."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "584267c6-26f9-437d-89f4-33468c9471eb",
"metadata": {},
"outputs": [],
"source": [
"from importlib.metadata import version\n",
"import h5py"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "9e381f78-8547-44e4-a5d9-2ec2504aa420",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'2.5.0+0.g68c4f564.dirty'"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"version(\"pynwb\")"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "00481fa7-f067-49cc-b657-a4ce825c1009",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'3.9.0'"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"version(\"h5py\")"
]
},
{
"cell_type": "markdown",
"id": "5ba6045c-a653-4c4f-8654-1d51e0a38251",
"metadata": {},
"source": [
"## Create a test NWB file"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "1e59db94-e8c0-4c91-b0c4-6c253eb0b560",
"metadata": {},
"outputs": [],
"source": [
"from pynwb import NWBFile, NWBHDF5IO, TimeSeries\n",
"import datetime\n",
"import numpy as np"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "d574d3a5-2c64-4fe0-9ee6-ce8cf86d33cd",
"metadata": {},
"outputs": [],
"source": [
"filename = \"test_modify.nwb\"\n",
"def create_test_file(my_filename):\n",
" nwbfile = NWBFile(\n",
" session_description=\"session_description\",\n",
" identifier=\"identifier\",\n",
" session_start_time=datetime.datetime.now(datetime.timezone.utc),\n",
" )\n",
" \n",
" ts = TimeSeries(\n",
" name=\"test_timeseries\",\n",
" data=np.array([1, 2, 3]),\n",
" timestamps=np.array([0.1, 0.2, 0.3]),\n",
" unit=\"m\"\n",
" )\n",
" nwbfile.add_acquisition(ts)\n",
" \n",
" filename = \"test_modify.nwb\"\n",
" \n",
" with NWBHDF5IO(my_filename, \"w\") as io:\n",
" io.write(nwbfile)"
]
},
{
"cell_type": "markdown",
"id": "b1ddf0c7-eb03-4d6b-a13a-08780446cbc7",
"metadata": {},
"source": [
"## Attributes"
]
},
{
"cell_type": "markdown",
"id": "60582875-af8e-45a3-bfac-620228f274d9",
"metadata": {},
"source": [
"### Modify an attribute using PyNWB - not allowed because python object attribute is already set"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "67c0b78a-aad4-47f6-b752-f3e44bb2c5f5",
"metadata": {},
"outputs": [],
"source": [
"create_test_file(filename)\n",
"with NWBHDF5IO(filename, \"a\") as io:\n",
" nwbfile = io.read()\n",
" # raises AttributeError: can't set attribute 'unit' -- already set\n",
" # nwbfile.acquisition[\"test_timeseries\"].unit = \"new unit\"\n",
" # io.write(nwbfile)"
]
},
{
"cell_type": "markdown",
"id": "799df494-5d17-40a7-a012-86f7b55061b8",
"metadata": {},
"source": [
"### Modify an attribute using h5py - allowed"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "99e85ab5-3e15-413b-8114-14a5616b1b8f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"m\n",
"new unit\n"
]
}
],
"source": [
"create_test_file(filename)\n",
"with h5py.File(filename, \"a\") as f:\n",
" print(f[\"/acquisition/test_timeseries/data\"].attrs[\"unit\"])\n",
" f[\"/acquisition/test_timeseries/data\"].attrs[\"unit\"] = \"new unit\"\n",
" print(f[\"/acquisition/test_timeseries/data\"].attrs[\"unit\"])"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "67a79b4e-768d-4a6c-b602-e503daa98991",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"new unit\n"
]
}
],
"source": [
"with NWBHDF5IO(filename, \"r\") as io:\n",
" nwbfile = io.read()\n",
" print(nwbfile.acquisition[\"test_timeseries\"].unit)"
]
},
{
"cell_type": "markdown",
"id": "7fc9abd6-17a4-412a-afd4-46676c760249",
"metadata": {},
"source": [
"### Modify an attribute using h5py and change its dtype - allowed"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "a8d55f6f-148b-4e1d-9969-cfcf2a0ac8e5",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"m\n",
"123\n"
]
}
],
"source": [
"create_test_file(filename)\n",
"with h5py.File(filename, \"a\") as f:\n",
" print(f[\"/acquisition/test_timeseries/data\"].attrs[\"unit\"])\n",
" f[\"/acquisition/test_timeseries/data\"].attrs[\"unit\"] = 123\n",
" print(f[\"/acquisition/test_timeseries/data\"].attrs[\"unit\"])"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "76e91b99-3106-4c95-b62f-50bf8288afa8",
"metadata": {},
"outputs": [],
"source": [
"# this will raise a ConstructError because the dtype of unit is not the expected dtype\n",
"# with NWBHDF5IO(filename, \"r\") as io:\n",
"# nwbfile = io.read()\n",
"# print(nwbfile.acquisition[\"test_timeseries\"].unit)"
]
},
{
"cell_type": "markdown",
"id": "128b36a9-fb19-42e2-85f0-56eb420177c5",
"metadata": {},
"source": [
"### Create a new attribute using PyNWB - no effect"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "47466232-c5f8-4c9d-b877-4fb1637600ce",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"None\n",
"continuous\n"
]
}
],
"source": [
"create_test_file(filename)\n",
"with NWBHDF5IO(filename, \"a\") as io:\n",
" nwbfile = io.read()\n",
" print(nwbfile.acquisition[\"test_timeseries\"].continuity)\n",
" nwbfile.acquisition[\"test_timeseries\"].continuity = \"continuous\"\n",
" print(nwbfile.acquisition[\"test_timeseries\"].continuity)\n",
" nwbfile.acquisition[\"test_timeseries\"].set_modified()\n",
" io.write(nwbfile)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "a380aa86-6214-4585-a88f-203713d6a34e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"None\n"
]
}
],
"source": [
"with NWBHDF5IO(filename, \"r\") as io:\n",
" nwbfile = io.read()\n",
" print(nwbfile.acquisition[\"test_timeseries\"].continuity)"
]
},
{
"cell_type": "markdown",
"id": "66546936-8168-47d3-8e44-2441dd018e9b",
"metadata": {},
"source": [
"### Create a new attribute using h5py - allowed"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "3ee7141f-de85-4ccf-ae67-faa3031b5f49",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"False\n",
"continuous\n"
]
}
],
"source": [
"create_test_file(filename)\n",
"with h5py.File(filename, \"a\") as f:\n",
" print(\"continuity\" in f[\"/acquisition/test_timeseries/data\"].attrs)\n",
" f[\"/acquisition/test_timeseries/data\"].attrs[\"continuity\"] = \"continuous\"\n",
" print(f[\"/acquisition/test_timeseries/data\"].attrs[\"continuity\"])"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "281298af-afb9-4fad-8b0f-b83865f8bc5d",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"continuous\n"
]
}
],
"source": [
"with NWBHDF5IO(filename, \"r\") as io:\n",
" nwbfile = io.read()\n",
" print(nwbfile.acquisition[\"test_timeseries\"].continuity)"
]
},
{
"cell_type": "markdown",
"id": "b7ac9abb-a561-40fe-9b6d-561f4acf45b2",
"metadata": {},
"source": [
"### Delete an attribute using PyNWB - not possible"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "b252b7e8-f9cc-4490-b3c1-684c0e78e892",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"no description\n",
"no description\n"
]
}
],
"source": [
"create_test_file(filename)\n",
"with NWBHDF5IO(filename, \"a\") as io:\n",
" nwbfile = io.read()\n",
" print(nwbfile.acquisition[\"test_timeseries\"].description)\n",
" nwbfile.acquisition[\"test_timeseries\"].description = None\n",
" # del nwbfile.acquisition[\"test_timeseries\"].description # raises AttributeError\n",
" print(nwbfile.acquisition[\"test_timeseries\"].description)\n",
" nwbfile.acquisition[\"test_timeseries\"].set_modified()\n",
" io.write(nwbfile)"
]
},
{
"cell_type": "markdown",
"id": "ce4b67ef-de51-499d-90b0-4061c61f5ac0",
"metadata": {},
"source": [
"### Delete an attribute using h5py - allowed"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "525906a6-cd0b-4ac1-9dfc-184e5cef250a",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"no description\n",
"False\n"
]
}
],
"source": [
"create_test_file(filename)\n",
"with h5py.File(filename, \"a\") as f:\n",
" print(f[\"/acquisition/test_timeseries\"].attrs[\"description\"])\n",
" del f[\"/acquisition/test_timeseries\"].attrs[\"description\"]\n",
" print(\"description\" in f[\"/acquisition/test_timeseries\"].attrs)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "e5b0c3bd-ba99-4f3c-98ec-e3f7a7100be0",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"False\n"
]
}
],
"source": [
"# NOTE: reading the file in PyNWB will see that description is not set and load the default\n",
"# value from the schema \"no description\", so here we read using h5py\n",
"with h5py.File(filename, \"r\") as f:\n",
" print(\"description\" in f[\"/acquisition/test_timeseries\"].attrs)"
]
},
{
"cell_type": "markdown",
"id": "20460697-9dd8-4498-a0c8-0d76d6103b22",
"metadata": {},
"source": [
"## Datasets"
]
},
{
"cell_type": "markdown",
"id": "bcdcf17f-66d6-405e-8580-0763ff9c11fe",
"metadata": {},
"source": [
"## Groups"
]
},
{
"cell_type": "markdown",
"id": "fdcbef92-b1ed-45d3-90db-468bddcce49c",
"metadata": {},
"source": [
"## Links"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bef77b36-307c-45ab-a0e6-4e800fba10d0",
"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.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment