Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
b52ab4f
Add settings serialization and NWB metadata storage capabilities
Sam-NT Feb 17, 2026
a60dacf
Clarifying settings setting as pipeline_settings
Sam-NT Feb 17, 2026
71e1077
Merge branch 'dev' into nt/write-settings
Sam-NT Feb 27, 2026
3748fb4
NWBSinkConsumer checks for pipeline_settings before attemting to init…
Sam-NT Feb 27, 2026
8382808
writer: first pass at settings logging, works but errors upon shutdown
Sam-NT Mar 23, 2026
8d0a156
refactor(nwb): improve settings interval tracking and table appendabi…
Sam-NT Mar 23, 2026
907c3f7
refactor(nwb): rename settings intervals to table and improve seriali…
Sam-NT Mar 24, 2026
78a9610
refactor(nwb): improve settings serialization and flatten nested stru…
Sam-NT Mar 24, 2026
f43cb7d
feat: rotate NWB files on settings shape changes
Sam-NT Mar 24, 2026
107c3fb
Fixing test_writer edge types for Win
Sam-NT Mar 24, 2026
6a17993
Merge branch 'dev' into nt/write-settings
Sam-NT Apr 27, 2026
1c53e9d
Merge nt/write-settings: pipeline-settings table
cboulay Apr 29, 2026
0dbb741
Merge pull request #5 from ezmsg-org/merge-pipeline-settings
Sam-NT Apr 29, 2026
d6fdce0
removed the duplicate _make_writer_continuous_msg / _make_writer_epoc…
cboulay Apr 29, 2026
875cf92
switched the deprecated AxisArray.Axis.TimeAxis(fs=...) to AxisArray.…
cboulay Apr 29, 2026
391a14a
added a "Pipeline settings logging" bullet to the feature list and a …
cboulay Apr 29, 2026
3b4dc7b
Migrate pipeline settings capture out of ezmsg-nwb and into ezmsg-bas…
cboulay May 1, 2026
f29ac03
Add test for modifying pipeline settings while running and capturing …
cboulay May 1, 2026
ef76723
Properly ignore initial messages when component address is None.
cboulay May 2, 2026
aaffdc5
New pipeline_settings module that extends NWBSink to store typed-colu…
cboulay May 2, 2026
49c6d91
Run tests in parallel and fix bug on _prep_from_meta dtype handling
cboulay May 2, 2026
95bceb3
Merge pull request #7 from ezmsg-org/cboulay/pipeline_settings
Sam-NT May 7, 2026
cbc5f3f
Merge branch 'dev' into nt/write-settings
cboulay May 7, 2026
e39e162
filelock used for tests
cboulay May 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.3
rev: v0.15.12
hooks:
# Run the linter.
- id: ruff
Expand Down
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Key features:
* **NWB Reader** - Stream data from NWB files (local or remote) as AxisArray messages
* **NWB Writer** - Write incoming AxisArray streams to NWB files with automatic container management
* **Flexible clock handling** - Support for system, monotonic, and unknown reference clocks
* **Pipeline settings logging** - Automatically record every component's settings into a `pipeline_settings` intervals table inside the NWB file

## Installation

Expand Down Expand Up @@ -48,6 +49,38 @@ from ezmsg.nwb import NWBIteratorUnit, NWBSink

For general ezmsg tutorials and guides, visit [ezmsg.org](https://www.ezmsg.org).

### Pipeline settings table

When `NWBSink` is used inside an `ez.run` pipeline (with `ezmsg>=3.9.0`), it
opens a `GraphContext` against the running graph server, snapshots the
settings of every component in its session, and subscribes to subsequent
settings change events. Each snapshot is flattened into dotted column names
(e.g. `MY.UNIT.MyUnitSettings.endpoint.host`) and appended as a row to a
`pipeline_settings` `TimeIntervals` table inside the NWB file, alongside an
`updated_component` column identifying which component triggered the
transition. Reading back is straightforward:

```python
from pynwb import NWBHDF5IO

with NWBHDF5IO(path, "r") as io:
nwbfile = io.read()
df = nwbfile.intervals["pipeline_settings"].to_dataframe()
```

Notes:

* Settings logging is best-effort. If the writer cannot connect to the graph
server (e.g. when running the consumer outside of `ez.run`), it logs a
warning and continues writing data without the table.
* Settings values are sanitized for NWB storage: primitives, NumPy scalars,
enums, paths, and fixed-shape sequences/arrays are stored natively;
mappings and irregular structures are JSON-encoded; `None` becomes the
string `"None"`.
* If a settings update changes a column's shape (scalar↔array or rank
change), the writer rotates into a new file segment (`<name>_01.nwb`,
`<name>_02.nwb`, …) so each segment's table stays internally consistent.

## Development

We use [`uv`](https://docs.astral.sh/uv/getting-started/installation/) for development.
Expand Down
5 changes: 4 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ requires-python = ">=3.10"
dynamic = ["version"]
dependencies = [
"ezmsg>=3.9.0",
"ezmsg-baseproc>=1.9.0",
"ezmsg-baseproc>=1.10.2",
"numpy>=1.26.0",
"pynwb",
"h5py",
Expand All @@ -34,6 +34,8 @@ lint = [
test = [
"pytest>=8.0.0",
"pytest-asyncio>=0.24.0",
"pytest-xdist>=3.5.0",
"filelock>=3.0",
]
docs = [
"sphinx>=8.0",
Expand All @@ -59,6 +61,7 @@ packages = ["src/ezmsg"]
[tool.pytest.ini_options]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
addopts = "-n auto --dist=loadfile"

[tool.ruff]
line-length = 120
Expand Down
15 changes: 15 additions & 0 deletions src/ezmsg/nwb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,21 @@
from .iterator import NWBAxisArrayIterator as NWBAxisArrayIterator
from .iterator import NWBIteratorSettings as NWBIteratorSettings
from .iterator import NWBIteratorState as NWBIteratorState
from .pipeline_settings import (
NWBPipelineSettingsSink as NWBPipelineSettingsSink,
)
from .pipeline_settings import (
NWBPipelineSettingsSinkConsumer as NWBPipelineSettingsSinkConsumer,
)
from .pipeline_settings import (
NWBPipelineSettingsSinkSettings as NWBPipelineSettingsSinkSettings,
)
from .pipeline_settings import (
PipelineSettingsTableCollection as PipelineSettingsTableCollection,
)
from .pipeline_settings import (
PipelineSettingsTableCollectionSettings as PipelineSettingsTableCollectionSettings,
)
from .reader import NWBIteratorUnit as NWBIteratorUnit
from .slicer import NWBSlicer as NWBSlicer
from .util import ReferenceClockType as ReferenceClockType
Expand Down
Loading
Loading