annie.pages.annotator ===================== .. py:module:: annie.pages.annotator .. autoapi-nested-parse:: Annotator tab — the supervision surface, one task at a time. The Annotator is where the reviewer *inputs* supervision (Browse is a read-only viewer). Which tasks it offers is driven by the sources present on the Dataset tab (see :func:`annie.dataset.sources.task_readiness`): a **task switch** at the top lists only the *ready* tasks, and switching one rebuilds the work area below. Every task persists to the same session review database. The tasks are: * **Protagonist review** (needs a protagonist CSV) — the original per-video track correction, described below; * **Curation** (needs only videos) — like/dislike plus a note per queued video, the supervision that used to live on Browse rows; * **Segment review** (needs a segmentation CSV) — accept/drop over the clips of long videos, one clip at a time: its passthrough tags on top, a lazy-embed ORIGINAL video, then one row per competing start/end band (aligned span facts, span frames, and an on-demand clip cut of that exact span). A top toolbar carries progress, the shortcut legend, and Export; Accept / Undecided / Drop and the step controls close the card, and a decision paints it with a coloured border and a lighter wash of the same hue. * **Event annotation** (needs only videos) — a video-editor timeline for marking labelled time-interval events across parallel tracks, one queued video at a time. It lives in :mod:`annie.pages.event_task` (with :mod:`annie.pages.videoclock` for frame-accurate playback and :mod:`annie.pages.timeline` for the SVG surface); events persist to the review DB's ``event``/``event_track`` tables and export to JSON and CSV. The tab is greyed out until at least one video is queued *or* a queue-free task (segment review) is ready. The protagonist task shows the queued videos in bordered rows; for each video: * an **ORIGINAL** placeholder embeds and plays the clip on click (like Browse), so it is obvious a video starts — while the **five-frame strip** shows the current protagonist track in green; * picking a different track in the **Protagonist** selector re-renders the strip immediately and **saves the choice to this session's review database** — there is no Save button; selection *is* the save. The source ``_manual`` CSV is *not* touched here — that is what the **Export corrected CSV** button (in the jump toolbar) is for; * the option matching the value in the source CSV is marked ``(default)`` so it is obvious which track the heuristic chose; * a **render** box burns the full clip with the chosen track green so the choice can be double-checked across the whole video. * the row's **X** button drops it from the queue once reviewed, so an emptying tab means the backlog is done, and **Clear all** beside the jump box does the same for every row at once. The saved corrections survive either way — only the ``annotate`` flag is cleared. Rows are revealed a page at a time (see :mod:`annie.pages.paging`), which also keeps the tab from decoding five frames for every queued video the moment it opens. **Export corrected CSV** (in the jump toolbar) writes the session's protagonist corrections to the ``_manual`` CSV beside the heuristic source (see :func:`annie.dataset.corrections`). Functions --------- .. autoapisummary:: annie.pages.annotator.set_tab annie.pages.annotator.sync_tab annie.pages.annotator.update_availability annie.pages.annotator.load_segment_clips_async annie.pages.annotator.render annie.pages.annotator.refresh Module Contents --------------- .. py:function:: set_tab(tab: nicegui.ui.tab) -> None Register this page's tab element so availability can be toggled from elsewhere. It is forgotten when the page is gone for good (not on a brief disconnect, after which the same page reconnects). .. py:function:: sync_tab() -> None Enable the tab in every open page when a video is queued or a queue-free task is ready. The queue lives in the shared review database, so every page shows the same state. .. py:function:: update_availability(*, rebuild: bool = False) -> None Sync the Annotator tab's enabled state after the queue changed, in every tab. The queue lives in the review DB, so every open tab must follow. The acting tab's Annotator is rebuilt only with ``rebuild`` (a change made inside it, on screen); otherwise it rebuilds when its tab is next opened. Other tabs are rebuilt now, since one of them may be showing the Annotator. .. py:function:: load_segment_clips_async(state_: _SegmentState) -> bool :async: Read the segmentation source's clips off the event loop, if it changed. :returns: ``True`` if new clips were loaded (the work area should be rebuilt). .. py:function:: render() -> None Build the Annotator tab body; register per-client timer host. .. py:function:: refresh(*, everywhere: bool = False) -> None Rebuild the Annotator body (after queueing changes or a tab open). :param everywhere: Rebuild it in every open tab (the dataset itself changed).