NWB alignment#
The NWB alignment file (<project>/.ethograph/alignment.nwb) stores trial
timing, media file paths, and stream offsets. It is the single source of
truth for “what file corresponds to what trial, and when did it start”.
See Pairing and alignment for the user-facing walkthrough.
At runtime the same interface is available via dt.nwb_alignment on a
loaded TrialTree.
Pairing media files#
- class ethograph.io.pairing.SourceSpec(stream, folder=None, files=(), pattern=None, device=None, software=None)[source]#
One media source of a rig: where its files are and how they map to trials/devices.
- ethograph.io.pairing.discover_media(session_dir, sources)[source]#
The pairing table:
trial+ one{stream}_{device}column per source/device, basenames only.pattern
None: files natsorted; row i is trial i+1; device fromdeviceor the default.pattern set: every file must match; named groups build trial + device columns.
Extensions: only those in
ethograph.io.validationVIDEO_/AUDIO_/POSE_EXTENSIONSfor the source’s stream.Fail fast: two pattern-less sources with different file counts ->
ValueErrornaming both counts; a pattern that fails to match a file ->ValueErrornaming the file; an empty folder ->ValueError.A trial present in one source but not another leaves
""in the missing cell (like the current template).
- Return type:
- ethograph.io.pairing.pair_media(trial_table, stream_rates=None, session_wide=None, output_path=None, media_root=None, pose_fps=None)[source]#
Write
.ethograph/alignment.nwbfrom a pairing table.Each per-trial
{stream}_{device}column becomes a trials-table column plus oneImageSerieswhose segments start at the trial starts;session_widestreams each get oneImageSerieswith astarting_time.start_time/stop_timeare optional — omitted, they are inferred from the media (needsmedia_root).If
output_pathis an existing NWB that already has a trials table (a neuroconv-written source), the streams are added to that file in place throughedit_nwb(), never rebuilt: per-trial columns from trial_table are written as new trial columns (row count must equal the file’s trials, elseValueError) andsession_widestreams as acquisitionImageSeries. Existing acquisition names are left alone.- Parameters:
trial_table (
DataFrame) –trial+{stream}_{device}filename columns (asdiscover_media()returns).start_time/stop_timeoptional.stream_rates (
dict[str,float] |None) – Sampling rate per stream, e.g.{"video": 30.0, "audio": 48000.0}; a{stream}_{device}key ("video_cam-2": 60.0) overrides its stream’s rate.session_wide (
dict[str,tuple[str,float,float]] |None) –{"{stream}_{device}": (file, rate_hz, starting_time_s)}for streams that are one file spanning the whole session rather than one file per trial.output_path (
str|Path|None) – Where to write (or, for an existing NWB with a trials table, extend) the.nwbfile.media_root (
str|Path|None) – Folder the filename columns are relative to; only needed when times are inferred.pose_fps (
float|None) – Frame rate for probing pose files, when inferring times from a table whose only media columns arepose_*.
- Return type:
The in-memory
NWBFile.
Creating alignment files#
- ethograph.io.nwb_alignment.make_nwb_alignment(nwb_path=None)[source]#
Create a EmpytAlignment from an NWB path, falling back to base EmpytAlignment.
- ethograph.io.nwb_alignment.discover_nwb(nc_path)[source]#
Find an NWB session file near a data file.
Search order: 1.
<dir>/.ethograph/alignment.nwb2. Any.nwbfile in<dir>/.ethograph/
- ethograph.io.nwb_alignment.sync_acquisition_for_streams(nwbfile, stream_rates)[source]#
Create ImageSeries acquisition items for ALL external media streams.
Reads the trials table to discover
{stream}_{device}columns. For each stream+device pair, creates anImageSeriesinnwbfile.acquisitionwithexternal_file,starting_frame, andrate(ortimestampsif offsets are present).
Reading alignment metadata#
- class ethograph.io.nwb_alignment.NWBAlignment(nwb_path)[source]#
Session metadata backed by an NWB file.
All external media (video, audio, pose) are stored as ImageSeries in acquisition with
{stream}_{device}naming. Timing comes fromrateortimestampson the ImageSeries.- devices(stream)[source]#
Discover devices from trials table columns AND acquisition items.
Three sources, checked in order:
Trials table columns (
video_cam_1-> devicecam_1).Acquisition ImageSeries following
{stream}_{device}naming.Acquisition ImageSeries whose
external_fileextensions match known media types (e.g..mp4-> video,.wav-> audio).
- electrical_series()[source]#
Discover ElectricalSeries in acquisition. Returns list of {name, path, n_channels, rate}.
- get_media(trial, stream, device=None)[source]#
Return the trial table’s media filename for stream/device.
A stored value that is an absolute local path (e.g. baked in by a template authored on a different machine) is reduced to its basename, so callers can always safely join it onto their own video/audio/pose folder instead of resolving to a path that only existed on the authoring machine.
- get_stream_rate(stream, device=None)[source]#
Read the sampling rate for a stream from its acquisition ImageSeries.
- property has_real_timing: bool#
Whether the trials table has meaningful start/stop times.
Returns False when all trials have identical placeholder timing (e.g. start=0.0, stop=1.0 for every row), which indicates the NWB was generated without real session timing.
- resolve_media_path(trial, stream, device=None, fallback_folder=None)[source]#
Resolve the full path for a media file.
Try the ImageSeries
external_filepath for this trial (if on disk).Fallback: trial table filename +
fallback_folder.Returns
Noneif unresolvable.
- stream_offset_for_trial(trial, stream, device=None)[source]#
Trial-relative time of sample 0 of the file that holds trial.
0.0 for per-trial files, negative for a session-wide file that started before the trial. The file is found by time (the trial’s start falls in its span), never by position – see
_file_for_trial.- Return type: