Skip to content

video: cross-language symmetry tests and shared example videos - #144

Merged
stevevanhooser merged 1 commit into
mainfrom
claude/clever-bardeen-hf5jgx
Oct 21, 2026
Merged

stevevanhooser merged 1 commit into
mainfrom
claude/clever-bardeen-hf5jgx

Conversation

@stevevanhooser

@stevevanhooser stevevanhooser commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

MATLAB half of the ndr.reader.video symmetry tests. The Python half and the Python port are in VH-Lab/NDR-python#33. Both use branch claude/clever-bardeen-hf5jgx, so NDR-python's test-symmetry.yml checks out this branch.

Changes

  • tools/tests/+ndr/+symmetry/+makeArtifacts/+reader/readVideo.m: runs the frame API on the two example videos and writes metadata.json and readFrames.json. These record:
    • numframes, framesize, dimensionorder, datatype, frametimes, t0_t1, epochclock, channels and image metadata;
    • exact pixels of the first and last RGB frame per channel, a SelectC read, and an out-of-order greyscale read.
  • tools/tests/+ndr/+symmetry/+readArtifacts/+reader/readVideo.m: verifies those artifacts from both sources (matlabArtifacts, pythonArtifacts). It mirrors NDR-python's tests/symmetry/{make,read}_artifacts/reader/test_read_video.py.
  • example_data/example_video.avi: 6-frame 12×16 uncompressed 24-bit RGB, 10 fps. R = 20*frame + col, G = 10*row + frame, B = 200 - 10*frame - col.
  • example_data/example_video_grey.avi: the same layout as 8-bit with a 256-entry grey palette ('Grayscale AVI' storage). Pixel value is 30*frame + 4*row + col.
  • example_data/Readme.md: documents both files. The README stays identical to NDR-python's.

Design notes

  • Shared, byte-identical inputs: the two AVIs are generated by NDR-python's tools/make_example_data.py, like the other synthetic fixtures. That script writes the AVI bytes directly, laid out as VideoWriter writes them: BI_RGB frames stored bottom-up.
  • Uncompressed: VideoReader can read these on every platform (MPEG-4 needs GStreamer on Linux), and since nothing is lossy the two ports must agree pixel for pixel.
  • Time tolerance: frame times are compared to 1e-6 s rather than the 1e-9 the TIFF readers use, because each port measures them through its own decoder rather than reading a sidecar file.
  • Already useful: the bottom-up greyscale fixture exposed a bug on the Python side. MATLAB-written greyscale AVIs came back upside down. It is fixed in NDR-python#33.

Verification

I wrote this without access to MATLAB. NDR-python's cross-language symmetry run on this branch (run 39476490054, attempt 2) is the first time these files ran, and they passed:

  • Stage 1: MATLAB makeArtifacts/readVideo passed (7/7 makeArtifacts tests).
  • Stage 2: Python read the MATLAB artifacts: metadata, image metadata and frames for both videos all passed.
  • Stage 4: MATLAB readArtifacts/readVideo passed for both SourceType=matlabArtifacts and SourceType=pythonArtifacts (14/14 readArtifacts tests).

VideoReader reads the grey-palette AVI as Grayscale (C=1), matching Python pixel for pixel.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QjkvVXsdCVw6NNe5SnGNyX

Adds +makeArtifacts/+reader/readVideo.m and +readArtifacts/+reader/readVideo.m,
mirroring NDR-python's tests/symmetry/{make,read}_artifacts/reader/
test_read_video.py, so the frame API of ndr.reader.video is checked against
the Python port (PyAV/FFmpeg) in both directions: numframes, framesize,
dimensionorder, datatype, frametimes, t0_t1, epochclock, getchannelsepoch,
metadata, and exact pixels of first/last RGB frames per channel, a SelectC
read and an out-of-order greyscale read.

The inputs are two new generated fixtures, byte-identical to NDR-python's
(written by its tools/make_example_data.py):
  example_video.avi       6-frame 12x16 uncompressed 24-bit RGB, 10 frames/s
  example_video_grey.avi  the same as 8-bit with a grey palette
                          ('Grayscale AVI' storage)
Both are stored bottom-up as VideoWriter writes them, and uncompressed so
VideoReader reads them on every platform and the ports must agree pixel for
pixel. Frame times compare to 1e-6 s, since each port measures them
through its own decoder.

Written without access to MATLAB: not run locally. The symmetry workflows
in both repos run it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QjkvVXsdCVw6NNe5SnGNyX
@github-actions

Copy link
Copy Markdown
Contributor

Test Results

415 tests  +3   412 ✅ +3   37s ⏱️ -7s
 54 suites +2     3 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit a07ed0b. ± Comparison against base commit 00cbbf8.

@codecov

codecov Bot commented Oct 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 54.94%. Comparing base (00cbbf8) to head (a07ed0b).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #144      +/-   ##
==========================================
+ Coverage   54.88%   54.94%   +0.06%     
==========================================
  Files         164      164              
  Lines        9598     9598              
==========================================
+ Hits         5268     5274       +6     
+ Misses       4330     4324       -6     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@stevevanhooser
stevevanhooser merged commit a45a4e6 into main Oct 21, 2026
8 checks passed
@stevevanhooser
stevevanhooser deleted the claude/clever-bardeen-hf5jgx branch October 21, 2026 12:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants