cupido/scripts/barrier_picker_app
Giorgio Gilestro 1a7542def2 Add barrier_picker_app — Dockerised web picker for barrier opening
A FastAPI app + plain HTML5 video page that replaces the matplotlib
picker. Browse to http://host:8000/, scrub through each video with
arrow keys (±5 s, ±1 s with Shift, ±0.1 s with Ctrl, ±1 frame with
,/.), and click one of three buttons:
  - All barriers open      — every ROI usable
  - Upper barrier opens    — ROIs 1,3,5 usable; lower row marked bad
  - Lower barrier opens    — ROIs 2,4,6 usable; upper row marked bad

The current playhead time is recorded as opening_s; bad_rois is set
accordingly. Also keyboard shortcuts (1/2/3 for the three modes,
s/u for skip/unusable). Refresh-safe: every submission persists to
data/metadata/barrier_opening.csv before advancing.

Server uses byte-range streaming so seeking inside long videos is
fast. Dockerfile + docker-compose.yml mount the data volume RO and
the metadata folder RW.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 12:33:28 +01:00
..
static Add barrier_picker_app — Dockerised web picker for barrier opening 2026-05-01 12:33:28 +01:00
app.py Add barrier_picker_app — Dockerised web picker for barrier opening 2026-05-01 12:33:28 +01:00
docker-compose.yml Add barrier_picker_app — Dockerised web picker for barrier opening 2026-05-01 12:33:28 +01:00
Dockerfile Add barrier_picker_app — Dockerised web picker for barrier opening 2026-05-01 12:33:28 +01:00
README.md Add barrier_picker_app — Dockerised web picker for barrier opening 2026-05-01 12:33:28 +01:00
requirements.txt Add barrier_picker_app — Dockerised web picker for barrier opening 2026-05-01 12:33:28 +01:00

Cupido — web-based barrier-opening picker

A small FastAPI + HTML5-video app for annotating the barrier-opening moment in each tracked recording. Lives in its own Docker container so it can run on the lab server without polluting any existing environment.

What it does

For every video referenced by all_video_info_merged.tsv that has a tracking DB on disk and isn't yet in barrier_opening.csv, it serves a <video> element pre-loaded with that mp4. The analyst plays / scrubs / pauses at the moment the barrier opens, then clicks one of:

button meaning written to bad_rois
All barriers open every ROI (1..6) is usable post-opening empty
Upper barriers open only the top row opens (ROIs 1, 3, 5) 2,4,6
Lower barriers open only the bottom row opens (ROIs 2, 4, 6) 1,3,5

Plus a Skip (advance without saving) and Unusable (write opening_s = NaN).

Keyboard shortcuts

  • Space — play / pause
  • / — ±5 s
  • Shift+arrows — ±1 s
  • Ctrl+arrows — ±0.1 s
  • , / . — ±1 frame
  • 1 / 2 / 3 — All / Upper / Lower
  • s — skip ; u — unusable

Run locally (docker compose)

cd scripts/barrier_picker_app
docker compose up --build

Then browse to http://localhost:8000/.

The container mounts:

  • /mnt/data/projects/cupido (data volume, read-only)
  • /mnt/ethoscope_data/videos (source mp4s, read-only)
  • data/metadata/ from the repo (read-write — for persisting barrier_opening.csv)

Adjust paths in docker-compose.yml if your layout differs.

Run without Docker (development)

cd scripts/barrier_picker_app
pip install -r requirements.txt
python app.py     # serves on http://localhost:8000

By default it expects:

  • merged TSV at /mnt/data/projects/cupido/all_video_info_merged.tsv
  • inventory at /cupido/data/metadata/video_inventory.csv
  • writes to /cupido/data/metadata/barrier_opening.csv

Override via environment variables:

CUPIDO_DATA_VOLUME=/path/to/data \
CUPIDO_INVENTORY_CSV=$(pwd)/../../data/metadata/video_inventory.csv \
CUPIDO_OUTPUT_CSV=$(pwd)/../../data/metadata/barrier_opening.csv \
python app.py