Skip to content

Commit 489cc31

Browse files
authored
Clarify TimeIntervals/EventsTable docs and routing (#688)
* Clarify time-anchored data storage: TimeIntervals, EventsTable, and /events placement Fixes #686 and #687. - Harmonize /intervals/* group docstrings (epochs, trials). - Rewrite TimeIntervals and EventsTable type docstrings to describe the type and give a usable decision rule, rather than restating historical use. - Replace the placeholder docstring on the /events group and its inner EventsTable slot. - Add a FAQ entry to format_description.rst covering: trials-table convention; TimeIntervals vs EventsTable; TimeSeries vs EventsTable for digital lines; EventsTable placement (/acquisition, /processing, /events, /analysis); /events vs /processing/behavior disambiguation; borderline edge-times case. - Expand BehavioralEvents and AnnotationSeries deprecation entries in the 2.10.0 release notes with field-level migration guidance. * Update format_release_notes.rst
1 parent 362dfff commit 489cc31

5 files changed

Lines changed: 93 additions & 11 deletions

File tree

core/nwb.epoch.yaml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
groups:
22
- neurodata_type_def: TimeIntervals
33
neurodata_type_inc: DynamicTable
4-
doc: A container for aggregating epoch data and the TimeSeries that each epoch applies
5-
to.
4+
doc: A column-based table to store information about time intervals, one interval
5+
per row. Use `TimeIntervals` when each row naturally has a start and stop time
6+
and represents a contiguous period of time, often encompassing an experimental
7+
condition. Rows can optionally reference `TimeSeries` data via the `timeseries`
8+
column. Examples include trials, epochs, behavioral states (e.g., "running",
9+
"resting"), and invalid recording windows.
610
datasets:
711
- name: start_time
812
neurodata_type_inc: VectorData

core/nwb.event.yaml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,11 @@ datasets:
4343
groups:
4444
- neurodata_type_def: EventsTable
4545
neurodata_type_inc: DynamicTable
46-
doc: A column-based table to store information about events (event instances), one
47-
event per row. Additional columns may be added to store metadata about each event,
48-
such as the duration of the event.
46+
doc: A column-based table to store information about events, one event per row.
47+
Use `EventsTable` when each row is anchored at a single timestamp and duration
48+
is absent, optional, or mixed across rows. Additional columns may be added to
49+
store metadata about each event, such as the duration of the event. Examples
50+
include TTL pulses, licks, rewards, stimulus onsets, and detected ripples.
4951
attributes:
5052
- name: description
5153
dtype: text

core/nwb.file.yaml

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -390,12 +390,13 @@ groups:
390390
groups:
391391
- name: epochs
392392
neurodata_type_inc: TimeIntervals
393-
doc: Divisions in time marking experimental stages or sub-divisions of a single
394-
recording session.
393+
doc: Time intervals marking coarse-grained experimental phases or subdivisions
394+
of a recording session, such as baseline, task, rest, or sleep stages.
395395
quantity: '?'
396396
- name: trials
397397
neurodata_type_inc: TimeIntervals
398-
doc: Repeated experimental events that have a logical grouping.
398+
doc: Time intervals corresponding to repeated experimental units with consistent
399+
structure, such as individual stimulus-response-reward cycles.
399400
quantity: '?'
400401
- name: invalid_times
401402
neurodata_type_inc: TimeIntervals
@@ -405,11 +406,23 @@ groups:
405406
doc: Optional additional table(s) for describing other experimental time intervals.
406407
quantity: '*'
407408
- name: events
408-
doc: Events that occurred during the session.
409+
doc: Primary experimental event tables for the session, stored as `EventsTable`
410+
instances. This location is intended for event data that are ready to be used
411+
in downstream analysis. It replaces the deprecated `BehavioralEvents` placement.
412+
Events emitted directly by the acquisition system (TTL edges, hardware event
413+
channels) belong in `/acquisition/`. Events derived by user processing
414+
(filtering, detection algorithms, annotation with experimental context) belong
415+
in a `ProcessingModule` under `/processing/`. For periods with required start
416+
and stop times, see `/intervals/`. For continuous acquired signals or stimulus
417+
templates from which events may have been derived, see `/acquisition/` or
418+
`/stimulus/`. For more guidance on choosing between `/events/`, `/acquisition/`,
419+
`/processing/`, and `/analysis/`, see the schema docs FAQ.
409420
quantity: '?'
410421
groups:
411422
- neurodata_type_inc: EventsTable
412-
doc: Events that occurred during the session.
423+
doc: An EventsTable holding a collection of event times of a particular type
424+
(e.g., licks, rewards, stimulus presentations) along with their per-event
425+
metadata.
413426
quantity: '*'
414427
- name: units
415428
neurodata_type_inc: Units

docs/format/source/format_description.rst

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,58 @@ time series, such as if timeseries A and timeseries B, each having
347347
different data (or time) share time (or data). This is much more
348348
important information as it shows structural associations in the data.
349349

350+
**How should I store events, intervals, and other time-anchored experimental annotations?**
351+
352+
NWB provides several ways to annotate time-anchored experimental data. The right
353+
choice depends on the structure of the experiment and the shape of the annotations.
354+
355+
*Start with trial structure.* In trial-based experiments, most per-event annotations
356+
(stimulus onsets, stimulus IDs, response times, reward times, etc.) belong as columns
357+
of ``/intervals/trials``, not as separate ``EventsTable`` instances. The trials table
358+
is the organizing unit, and ``DynamicTable``'s sparse-column support is designed
359+
for metadata where some trials have a value and others do not.
360+
361+
*Use TimeIntervals for period-shaped annotations.* When each row naturally has a
362+
start and stop time and represents a contiguous period of time, store the data in
363+
a ``TimeIntervals`` table. Examples include behavioral states ("running", "resting"),
364+
experimental conditions, and invalid recording windows. Place additional
365+
``TimeIntervals`` tables in ``/intervals/`` alongside the predefined ``epochs``,
366+
``trials``, and ``invalid_times`` subgroups.
367+
368+
*Use EventsTable for timestamp-anchored annotations that don't fit a per-trial row.*
369+
``EventsTable`` is the right type when each row is anchored at a single timestamp and
370+
duration is absent, optional, or mixed across rows. Typical cases:
371+
372+
- TTL pulses and event markers from acquisition systems (replaces the deprecated ``AnnotationSeries``).
373+
- Free-behavior events not anchored to trial structure (licks, rewards, detected behaviors in continuous recordings).
374+
- Algorithmically detected events (ripples, sharp waves, spike-of-interest detections).
375+
- Experimenter-added annotations (e.g., "subject was distracted here", "experimenter adjusted the stimulus here").
376+
- Events occurring multiple times per trial with variable count, where ragged trial columns would be awkward.
377+
378+
*Continuous digital traces are TimeSeries, not EventsTable.* A digital line sampled
379+
continuously (e.g., a 30 kHz 0/1 trace of a TTL channel) is a ``TimeSeries``. Edge
380+
times derived from that trace are an ``EventsTable``. The continuous-vs-edges
381+
distinction is independent of where the data is stored in the file hierarchy.
382+
383+
*Place EventsTable instances based on how the data was derived.* ``EventsTable`` is
384+
allowed in multiple groups, mirroring ``TimeSeries`` placement conventions:
385+
386+
- ``/acquisition`` — events emitted directly by the acquisition system (Neuralynx ``.nev``, Open Ephys event channels, TTL edges parsed from a directly-recorded digital line).
387+
- ``/processing/<module>`` — events derived by user processing: filtering, debouncing, detection algorithms, or events annotated with experimental context.
388+
- ``/events`` — primary experimental event tables for the session, ready to be used in downstream analysis. The ``BehavioralEvents`` replacement case from NWBEP001.
389+
- ``/analysis`` — events tied to final scientific analysis.
390+
391+
The ``/events`` versus ``/processing/behavior/`` choice is the most common source of
392+
confusion. Prefer ``/events`` when the table is a top-level experimental annotation
393+
ready for downstream analysis. Prefer ``/processing`` when the table is an
394+
intermediate output consumed by other processing steps.
395+
396+
For the borderline case of edge times derived from a directly-recorded digital line,
397+
default to ``/acquisition``. Edge detection on a binary line is information-preserving
398+
— the events are what the acquisition system would have emitted if configured to do
399+
so. Reserve ``/processing`` for cases involving actual decisions (thresholding analog
400+
signals, debouncing, filtering, selection).
401+
350402

351403
Tables and ragged arrays
352404
------------------------

docs/format/source/format_release_notes.rst

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,15 @@ Major changes
1212
- Incorporated HDMF Common Schema 1.9.0 which added new data types ``MeaningsTable`` and support for ``MeaningsTable`` in ``DynamicTable``.
1313
- Added support for an optional ``HERD`` object at ``/general/external_resources``.
1414
- Deprecated ``BehavioralEvents`` in favor of placing ``EventsTable`` tables in ``NWBFile/events``.
15-
- Deprecated ``AnnotationSeries`` in favor of creating an ``EventsTable`` with an ``annotation`` column.
15+
Each ``TimeSeries`` formerly stored under ``BehavioralEvents`` becomes one ``EventsTable``: the
16+
``timestamps`` field maps to the ``timestamp`` column, and any per-event metadata becomes
17+
additional columns. See the schema docs FAQ for guidance on choosing between ``/events/``,
18+
``/acquisition/``, ``/processing/``, and ``/analysis/``.
19+
- Deprecated ``AnnotationSeries`` in favor of creating an ``EventsTable`` with an ``annotation``
20+
column. The ``timestamps`` field maps to the ``timestamp`` column, and the ``data`` field
21+
(annotation strings) maps to the new ``annotation`` column. Event markers from acquisition systems
22+
that were previously stored as ``AnnotationSeries`` typically belong in ``/acquisition/`` rather
23+
than ``/events/``.
1624

1725
Minor changes
1826
^^^^^^^^^^^^^
@@ -30,6 +38,9 @@ Minor changes
3038
to the session reference time and that values should be stored in ascending order. (#676)
3139
- Improved documentation of ``Units.spike_times.resolution`` to clarify that it represents the temporal resolution
3240
(sampling period) of the spike times. (#666)
41+
- Harmonized ``/intervals/*`` group docstrings; rewrote ``TimeIntervals`` and ``EventsTable`` type
42+
docstrings; replaced the placeholder docstring on the ``/events`` group and its inner
43+
``EventsTable`` slot; added a FAQ entry on routing time-anchored experimental data. (#688)
3344

3445
2.9.0 (June 26, 2025)
3546
---------------------

0 commit comments

Comments
 (0)