thermokourt.extract

Stage 1 of the pipeline: arena detection, interactive verification, and ffmpeg-based concat + crop. See Pipeline guide for a usage walkthrough.

thermokourt.extract.arena_extractor

.. py:module:: thermokourt.extract.arena_extractor

╔═══════════════════════════════════════════════════════════════════════╗
║   Arena Extractor v1.2                                               ║
║   Detect, verify & extract circular arenas from Motif recordings     ║
║   ── detect. adjust. stitch. crop. science. ──                       ║
╚═══════════════════════════════════════════════════════════════════════╝

Pipeline for Drosophila arena recordings (Motif / FLIR / Basler).

 1. Builds a max-projection image (100 frames, 25-100% of duration)
    to erase dark fly bodies and reveal clean arena boundaries
 2. Detects circles via Hough transform on the max-projection
 3. Opens a fast OpenCV GUI for verification / adjustment
 4. Concatenates .mp4 chunks via ffmpeg concat demuxer
 5. Crops each arena with 10% padding + white corner masks
    (5% triangles to hide neighbouring arenas from the tracker)

Requirements: pip install numpy opencv-python pyyaml ffmpeg on PATH

License: MIT · Author: Bart R.H. Geurten

.. py:class:: Arena(cx: float, cy: float, r: float, idx: int = 0) :module: thermokourt.extract.arena_extractor

Bases: :py:class:object

.. py:attribute:: Arena.cx :module: thermokourt.extract.arena_extractor :type: float

.. py:attribute:: Arena.cy :module: thermokourt.extract.arena_extractor :type: float

.. py:attribute:: Arena.r :module: thermokourt.extract.arena_extractor :type: float

.. py:attribute:: Arena.idx :module: thermokourt.extract.arena_extractor :type: int :value: 0

.. py:method:: Arena.bbox(padding: float = 0.1, frame_w: int = 0, frame_h: int = 0) -> ~typing.Tuple[int, int, int, int] :module: thermokourt.extract.arena_extractor

  (x, y, w, h) with padding, clamped to frame, even dimensions.

.. py:method:: Arena.to_dict() :module: thermokourt.extract.arena_extractor

.. py:method:: Arena.from_dict(d) :module: thermokourt.extract.arena_extractor :classmethod:

.. py:function:: sort_arenas_row_major(arenas: ~typing.List[~thermokourt.extract.arena_extractor.Arena]) -> ~typing.List[~thermokourt.extract.arena_extractor.Arena] :module: thermokourt.extract.arena_extractor

Sort top→bottom, left→right. Re-numbers 0..N-1.

.. py:function:: filter_by_radius(arenas, tol=0.25, keep=5) :module: thermokourt.extract.arena_extractor

.. py:function:: get_mp4_chunks(d) :module: thermokourt.extract.arena_extractor

.. py:function:: extract_frame_at(mp4, t, w, h) :module: thermokourt.extract.arena_extractor

Extract a single RGB frame at time t (seconds).

.. py:function:: build_max_projection(chunks: ~typing.List[str], n_frames: int = 10, start_frac: float = 0.25) -> numpy.ndarray :module: thermokourt.extract.arena_extractor

Build a max-intensity projection across sampled frames.

Samples n_frames evenly from start_frac..1.0 of total duration across all chunks. Because flies are dark and move, the per-pixel maximum recovers the bright, static arena background.

.. py:function:: detect_arenas(frame, n_expected=10, min_r=0, max_r=0) :module: thermokourt.extract.arena_extractor

Hough circle detection on (ideally max-projected) frame.

.. py:function:: corner_mask_triangles(crop_w, crop_h, frac=0.25) :module: thermokourt.extract.arena_extractor

Return 4 triangle vertex arrays for the corners of a crop.

Each triangle has legs of length frac * side_length, measured from the corner along each edge.

Returns list of 4 numpy arrays, each shape (3, 2) int32.

.. py:function:: apply_corner_mask_to_frame(frame, frac=0.25, colour=255) :module: thermokourt.extract.arena_extractor

White-out corner triangles on a frame (in-place).

.. py:class:: ArenaEditorCV2(frame_rgb, arenas, recording_name=’’, json_path=’’) :module: thermokourt.extract.arena_extractor

Bases: :py:class:object

Fast OpenCV-based arena editor.

Controls: Left-drag on centre dot → move arena Left-drag on rim diamond → resize arena Right-click empty → add arena Right-click on centre → delete arena A re-run detection +/= increase all radii - decrease all radii U uniform radii (median) C toggle corner mask preview H toggle help overlay Q / Enter accept Esc abort

.. py:attribute:: ArenaEditorCV2.WIN :module: thermokourt.extract.arena_extractor :value: ‘Arena Extractor’

.. py:attribute:: ArenaEditorCV2.HANDLE_R :module: thermokourt.extract.arena_extractor :value: 12

.. py:method:: ArenaEditorCV2.get_arenas() :module: thermokourt.extract.arena_extractor

.. py:function:: build_concat_file(chunks, tmpdir) :module: thermokourt.extract.arena_extractor

.. py:function:: concat_and_crop(chunks, arenas, output_dir, recording_name, codec=’libx264’, crf=18, frame_height=0, frame_width=0, keep_full=False, corner_frac=0.25, jobs=1) :module: thermokourt.extract.arena_extractor

Concatenate mp4 chunks and crop each arena, with resume + parallelism.

.. py:function:: parse_args() :module: thermokourt.extract.arena_extractor

.. py:function:: load_arenas_json(path) :module: thermokourt.extract.arena_extractor

.. py:function:: main() :module: thermokourt.extract.arena_extractor