annie.dataset.events¶
Event-annotation domain: interval events on tracks, and their export.
The Event-annotation task lets a reviewer mark events — labelled [start, end] frame
intervals — on named tracks (a track is its category) while watching one video. Unlike
the CSV-driven tasks, nothing is loaded from a source file: events are authored from scratch
and persisted to the review database (see annie.dataset.storage.EventRecord). This
module holds the pure pieces around that store:
frame ↔ second conversion, since the database is the source of truth in frames (fps-independent) while humans and exports think in seconds;
interval clamping, so a typed or dragged boundary can never leave the video;
an event’s effective colour and attributes: an event linked to an event category (
annie.dataset.storage.EventType) inherits the category’s colour and default attributes, and its own values win;the export shapes. JSON is nested — one object per video, tracks holding their events with attributes inline — for downstream code. CSV and XLSX are flat — one row per event, attributes flattened into
attr_<key>columns — for a spreadsheet (XLSX opens in Excel with typed numbers, a frozen header and filters). That split is deliberate: nested attributes do not live cleanly in a spreadsheet cell.
Pure domain: no NiceGUI, no torch. The task UI and the store consume it.
Functions¶
|
Convert a frame index to seconds at |
|
Convert seconds to the nearest frame index at |
|
Order and bound an event's frames to a valid interval within the video. |
|
Return the colour an event is drawn and exported with. |
|
Return an event's attributes with its event category's defaults filled in. |
|
Group events into the nested |
|
Render events as nested JSON text (one object per video). |
|
Write events to a nested JSON file (see |
|
Flatten events into spreadsheet rows (one per event), shared by CSV and XLSX. |
|
Render events as flat CSV text (one row per event; columns as |
|
Write events to a flat CSV file (see |
|
Render events as an Excel workbook (same columns as the CSV, see |
|
Write events to an Excel file (see |
Module Contents¶
- annie.dataset.events.frames_to_seconds(frame: int, fps: float) float[source]¶
Convert a frame index to seconds at
fps.- Parameters:
frame – The frame index.
fps – Frames per second (
<= 0is treated as0seconds, since no timebase is known — the caller falls back to frame numbers).
- Returns:
The time in seconds, or
0.0whenfpsis non-positive.
- annie.dataset.events.seconds_to_frame(sec: float, fps: float) int[source]¶
Convert seconds to the nearest frame index at
fps.Rounds to the nearest frame; on constant-fps media this is exact, and on a variable-fps file it may be off by one frame (the documented playback limitation).
- Parameters:
sec – The time in seconds.
fps – Frames per second (
<= 0yields frame0).
- Returns:
The nearest non-negative frame index.
- annie.dataset.events.clamp_event(start: int, end: int, num_frames: int) tuple[int, int][source]¶
Order and bound an event’s frames to a valid interval within the video.
Swaps a reversed pair so
start <= end, then clamps both to[0, last]wherelast = num_frames - 1. A video with no known frame count (num_frames <= 0) is clamped only at the lower bound, so an event can still be authored before metadata loads.- Parameters:
start – The proposed start frame.
end – The proposed end frame.
num_frames – The video’s total frame count (
<= 0if unknown).
- Returns:
The ordered, bounded
(start, end)pair.
- annie.dataset.events.effective_color(event: annie.dataset.storage.EventRecord, types: collections.abc.Mapping[str, annie.dataset.storage.EventType] | None = None, lane_color: str | None = None) str | None[source]¶
Return the colour an event is drawn and exported with.
Its own colour wins, then its event category’s, then the participant lane’s.
- Parameters:
event – The event.
types – Event categories by name (
Nonewhen there are none).lane_color – The participant lane’s colour, the last fallback.
- Returns:
A hex colour, or
Nonewhen nothing sets one.
- annie.dataset.events.effective_attributes(event: annie.dataset.storage.EventRecord, types: collections.abc.Mapping[str, annie.dataset.storage.EventType] | None = None) dict[str, str][source]¶
Return an event’s attributes with its event category’s defaults filled in.
- Parameters:
event – The event.
types – Event categories by name (
Nonewhen there are none).
- Returns:
{**category defaults, **event's own}, so the event’s own values win.
- annie.dataset.events.build_export_tree(events: collections.abc.Iterable[annie.dataset.storage.EventRecord], fps_by_video: collections.abc.Mapping[str, float], meta_by_video: collections.abc.Mapping[str, collections.abc.Mapping[str, str]] | None = None, types: collections.abc.Mapping[str, annie.dataset.storage.EventType] | None = None) dict[str, dict[str, object]][source]¶
Group events into the nested
video_id -> {fps, tracks}export structure.Shared by the JSON export and, indirectly, the CSV export’s row order. Videos and their tracks appear in first-seen order; events keep the order they arrive in (the store hands them back sorted by track then start frame).
- Parameters:
events – The events to export.
fps_by_video – Frames per second per
video_id, for the derived seconds. A video missing here is exported withfps = 0and zero seconds (frames still stand).meta_by_video – Optional per-video metadata (e.g. the fields a nested layout captured from the path), exported as a
"meta"object when a video has any.types – Event categories by name, so linked events export their effective colour and attributes.
- Returns:
A mapping of
video_idto{"fps": float, "tracks": {...}}(plus"meta").
- annie.dataset.events.events_to_json_text(events: collections.abc.Iterable[annie.dataset.storage.EventRecord], fps_by_video: collections.abc.Mapping[str, float], meta_by_video: collections.abc.Mapping[str, collections.abc.Mapping[str, str]] | None = None, types: collections.abc.Mapping[str, annie.dataset.storage.EventType] | None = None) str[source]¶
Render events as nested JSON text (one object per video).
Suits downstream code: attributes stay nested, seconds are derived per video’s fps. A per-video export is this same shape with a single top-level key; a session export has many.
- Parameters:
events – The events to render.
fps_by_video – Frames per second per
video_id.meta_by_video – Optional per-video metadata exported as
"meta".types – Event categories by name (for effective colour and attributes).
- Returns:
The JSON document as a string.
- annie.dataset.events.export_events_json(events: collections.abc.Iterable[annie.dataset.storage.EventRecord], fps_by_video: collections.abc.Mapping[str, float], path: str | pathlib.Path) pathlib.Path[source]¶
Write events to a nested JSON file (see
events_to_json_text()).- Parameters:
events – The events to write.
fps_by_video – Frames per second per
video_id.path – Destination
.jsonpath (parent directories are created).
- Returns:
The path written.
- annie.dataset.events.event_table(events: collections.abc.Iterable[annie.dataset.storage.EventRecord], fps_by_video: collections.abc.Mapping[str, float], meta_by_video: collections.abc.Mapping[str, collections.abc.Mapping[str, str]] | None = None, types: collections.abc.Mapping[str, annie.dataset.storage.EventType] | None = None) tuple[list[str], list[dict[str, object]]][source]¶
Flatten events into spreadsheet rows (one per event), shared by CSV and XLSX.
Fixed columns come first, then one
meta_<key>column per metadata key seen, then oneattr_<key>column per attribute key seen across all events (empty where an event lacks that key), so colleagues can open and sort the file in Excel. Keys are sorted for a stable header. Colour and attributes are the effective ones, so the file is complete without the database.- Parameters:
events – The events to flatten.
fps_by_video – Frames per second per
video_id(for the derived seconds).meta_by_video – Optional per-video metadata.
types – Event categories by name (for effective colour and attributes).
- Returns:
The column names and the rows (frames as ints, seconds as floats, the rest text).
- annie.dataset.events.events_to_csv_text(events: collections.abc.Iterable[annie.dataset.storage.EventRecord], fps_by_video: collections.abc.Mapping[str, float], meta_by_video: collections.abc.Mapping[str, collections.abc.Mapping[str, str]] | None = None, types: collections.abc.Mapping[str, annie.dataset.storage.EventType] | None = None) str[source]¶
Render events as flat CSV text (one row per event; columns as
event_table()).- Parameters:
events – The events to render.
fps_by_video – Frames per second per
video_id(for the derived seconds).meta_by_video – Optional per-video metadata, as
meta_<key>columns.types – Event categories by name (for effective colour and attributes).
- Returns:
The CSV document as a string.
- annie.dataset.events.export_events_csv(events: collections.abc.Iterable[annie.dataset.storage.EventRecord], fps_by_video: collections.abc.Mapping[str, float], path: str | pathlib.Path) pathlib.Path[source]¶
Write events to a flat CSV file (see
events_to_csv_text()).- Parameters:
events – The events to write.
fps_by_video – Frames per second per
video_id(for the derived seconds).path – Destination
.csvpath (parent directories are created).
- Returns:
The path written.
- annie.dataset.events.events_to_xlsx_bytes(events: collections.abc.Iterable[annie.dataset.storage.EventRecord], fps_by_video: collections.abc.Mapping[str, float], meta_by_video: collections.abc.Mapping[str, collections.abc.Mapping[str, str]] | None = None, types: collections.abc.Mapping[str, annie.dataset.storage.EventType] | None = None) bytes[source]¶
Render events as an Excel workbook (same columns as the CSV, see
event_table()).One
Eventssheet: a bold, frozen header with filters, frames and seconds stored as numbers (so Excel sorts and sums them), and columns sized to their content.- Parameters:
events – The events to render.
fps_by_video – Frames per second per
video_id(for the derived seconds).meta_by_video – Optional per-video metadata, as
meta_<key>columns.types – Event categories by name (for effective colour and attributes).
- Returns:
The
.xlsxfile’s bytes.
- annie.dataset.events.export_events_xlsx(events: collections.abc.Iterable[annie.dataset.storage.EventRecord], fps_by_video: collections.abc.Mapping[str, float], path: str | pathlib.Path) pathlib.Path[source]¶
Write events to an Excel file (see
events_to_xlsx_bytes()).- Parameters:
events – The events to write.
fps_by_video – Frames per second per
video_id(for the derived seconds).path – Destination
.xlsxpath (parent directories are created).
- Returns:
The path written.