Data pipeline: fix pvio import break + loader resolution guard (I1-C) + extraction script (I2-C)#51
Open
sibocw wants to merge 2 commits into
Open
Data pipeline: fix pvio import break + loader resolution guard (I1-C) + extraction script (I2-C)#51sibocw wants to merge 2 commits into
sibocw wants to merge 2 commits into
Conversation
… + extraction script (I2-C) Fixes the pvio private-symbol import break and two data-pipeline footguns identified in audit issue #48. pvio import break (atomic_batch.py): - The module imported pvio's private `_default_ffmpeg_params_for_video_writing` and mutated it in place. The installed pvio no longer exports that internal default, so the import raised ImportError and broke the entire `pose.data.synthetic` and `pose.contrast` packages. Define the ffmpeg params locally (mirroring pvio's documented high-quality H.264 defaults, with `-level` bumped to 5.0 for larger frames) and pass them through the public `write_frames_to_video(..., ffmpeg_params=)` API instead. I1-C loader resolution guard (atomic_batch.py): - `load_atomic_batch_frames` reconstructs each per-variant tile via a top-left crop assuming the stored tile width equals `image_size`. The old assertion only caught tiles that were too narrow; tiles extracted at a larger resolution were silently mis-sliced (wrong columns, clipped fly) while labels stayed at the stored resolution. Add a loud guard that reconstructs the storage geometry (`round_up_16(V*n_cols + (V-1)*spacing)` width and `round_up_16(n_rows)` height) and raises a clear, actionable error on any mismatch instead of silently corrupting data. I2-C extraction script (extract_dataset_bodypart.py): - `list_nmf_simulations_and_num_frames` is now called with the required `num_workers` arg (threaded through `main()`), fixing the TypeError on launch. - The hardcoded `SCALING = 900.0/256.0` for spotlight keypoint coords is parameterized: `build_endpoints` takes an explicit `scaling`, and the spotlight path derives it from the actual saved-frame width and a configurable `pred_coord_resolution`. Adds tests/test_atomic_batch_guards.py: loads a real 256-tiled atomic batch (asserts correct load) and asserts the new guard raises on a mismatched image_size. Refs #48 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
sibocw
added a commit
that referenced
this pull request
Jun 24, 2026
scripts/verify_ik_selfconsistency.py unprojects the stored atomic-batch keypoint_pos to 3D, runs the IK, and compares recovered joint angles to the stored ground-truth dof_angles (matched BY NAME, wrapping-aware) -- validating I3-A (DOF map / save path), I1-A (camera sensor size), and the IK solve. Also has a flygym-free --emit-bounds mode that regenerates the I3-B data-derived nmf_bounds. Full run needs flygym + seqikpy (and PR #51's pvio fix); --emit-bounds runs standalone. Refs #48. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The atomic batches were reorganized under a `4variants/` subfolder; the test still pointed at `atomic_batches/BO_Gal4_fly1_trial001/` (gone) and errored at collection. Repointed to `atomic_batches/4variants/BO_Gal4_fly1_trial001/`. Combined with the pvio import fix in this PR, this test now passes. Refs #48. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This work was implemented by Claude Code (Opus 4.8) upon user instruction.
Addresses audit issue #48: a
pvioimport break plus two data-pipeline footguns (I1-C and I2-C).pvio private-symbol import break (the package-breaking bug)
src/poseforge/pose/data/synthetic/atomic_batch.pyimported pvio's private_default_ffmpeg_params_for_video_writing, then mutated its-levelentry in place to allow higher-resolution (900x900) videos:The installed pvio no longer exports that internal default, so this raised
ImportError: cannot import name '_default_ffmpeg_params_for_video_writing'at import time — which broke the entireposeforge.pose.data.syntheticandposeforge.pose.contrastpackages (anything importing them failed at collection/startup).Fix (public API): pvio's
write_frames_to_video(video_path, frames, fps, codec='libx264', ffmpeg_params: list[str] | None = None, ...)acceptsffmpeg_params. We now define the params as a module-level constant mirroring pvio's documented high-quality H.264 defaults (["-crf", "15", "-preset", "slow", "-profile:v", "high", "-level", "4.0"]) but with-levelbumped to5.0, drop the private import, and pass the constant throughwrite_frames_to_video(..., ffmpeg_params=...). Behavior is preserved; no private symbol is touched.This unblocks importing the
pose.data.syntheticandpose.contrastpackages (verified below).I1-C: loader resolution guard (
load_atomic_batch_frames)The loader reconstructs each per-variant tile via a top-left crop
frame[:n_rows, start_col:end_col], where(n_rows, n_cols) = image_sizeand the column stride isn_cols + spacing. This is correct only if each on-disk tile was serialized at exactlyimage_size. If an atomic batch were extracted at a larger per-variant resolution, the crop would silently grab the wrong columns (slicing across tile boundaries) and clip the fly, while the stored labels (keypoints / segmentation maps) remained at the extraction resolution — silently corrupted training data. The previous assertion only caught tiles that were too narrow; it happily accepted tiles that were too wide. On the currently shipped data the tiles are 256, so this was latent, but it is an unguarded footgun that blocks higher-resolution work.Fix: add a loud guard that reconstructs the geometry
save_atomic_batch_frameswould have produced — widthround_up_16(V * n_cols + (V-1) * spacing)for someV >= n_variants, and heightround_up_16(n_rows)— and raises a clear, actionableValueErroron any mismatch, naming the stored-vs-expected sizes and how to fix it. The check correctly accounts for the<16pxencoder padding thatsave_atomic_batch_framesapplies (so it does not false-positive on the real 256 data, whose 4-variant width is 1056, not the naive 1054). It also still recovers the true stored variant count to drive the existing "extra variants" warning. We intentionally do not silently resize, since that would not rescale the stored labels; a clear error is the safe fix.I2-C: broken extraction script (
extract_dataset_bodypart.py)main()calledlist_nmf_simulations_and_num_frames(nmf_rendering_dir, video_filename), but that function (inextract_dataset.py) requires a thirdnum_workers: intargument. We add anum_workersconfig inmain()(defaulting toos.cpu_count()) and thread it through.build_endpointshardcodedSCALING = 900.0/256.0for spotlight keypoint coords, silently wrong if either resolution changes. We replace theis_spotlightflag with an explicitscalingparameter; the synthetic path passes1.0, and the spotlight path derivesscaling = saved_image_width / pred_coord_resolutionfrom the actual saved-frame size and a configurablepred_coord_resolution(default 256), with a guard that the spotlight frame is square.Findings from #48 (Refs #48)
pviobreak is package-level: it was anImportErrorat module import, not a runtime error, so it took down all ofpose.data.syntheticandpose.contrast— including the existing test suite, which couldn't even be collected.bulk_data/pose_estimation/atomic_batches/4variants/...; the pre-existingtests/test_atomic_batch_dataset.pystill points at the oldatomic_batches/BO_Gal4_fly1_trial001/path (see test results).extract_dataset.py's ownmain()already passednum_workerscorrectly — only the bodypart script had the missing-arg bug.Test results
Import verification (worktree source):
(Note:
load_atomic_batch_framesis a@staticmethodofAtomicBatchDataset, not a module-level function, so importing the bare name is expected to fail — importing the module and the class succeeds.)Before the pvio fix, the existing suite could not even be collected:
After the fix,
pytest tests/test_atomic_batch_dataset.py tests/test_synthetic_data_sampler.py tests/test_atomic_batch_guards.py:tests/test_atomic_batch_guards.py: 3 passed — real 256-tiled batch loads correctly atimage_size=(256,256); the guard raises a clearValueErroratimage_size=(512,512); geometry-inversion unit checks pass.tests/test_synthetic_data_sampler.py: 2 passed.tests/test_atomic_batch_dataset.py::test_atomic_batch_dataset_loading: 1 failed, but only due to a stale hardcoded data path predating the4variants/reorg (ValueError: Provided path bulk_data/pose_estimation/atomic_batches/BO_Gal4_fly1_trial001 is not a directory). This is unrelated to the changes here — the pvio fix made the module importable, so the failure is now a clean missing-directory error rather than anImportErrorat collection. Updating that test's data path is out of scope for the files this PR is allowed to touch.🤖 Generated with Claude Code
Update (Claude Code, upon user instruction)
Also repointed the stale data path in
tests/test_atomic_batch_dataset.py(atomic_batches/BO_Gal4_fly1_trial001/→atomic_batches/4variants/BO_Gal4_fly1_trial001/). Combined with the pvio import fix in this PR, that test now passes (it previously errored at collection). Human verification:pytest tests/test_atomic_batch_dataset.pywith the data present.