Skip to content

feat: headless batch mode for PNG sequence rendering#12

Open
001TMF wants to merge 15 commits intomasterfrom
feat/batch-mode
Open

feat: headless batch mode for PNG sequence rendering#12
001TMF wants to merge 15 commits intomasterfrom
feat/batch-mode

Conversation

@001TMF
Copy link
Copy Markdown
Owner

@001TMF 001TMF commented Apr 30, 2026

Summary

  • Adds --batch <CONFIG_JSON> mode that renders deterministic PNG sequences without entering the TUI
  • New BatchConfig JSON schema with camera waypoints (linearly interpolated across frames), hotspot residue highlights, and color/viz mode selection
  • New render::draw_protein() wrapper around hd::render_hd_framebuffer — TUI render path untouched
  • New ColorScheme::with_highlights() builder threads per-residue color overrides through the renderer
  • Reference example at examples/batch_demo.json (60-frame 360° rotation @ 1920×1080 of histone nucleosome 1AOI)

Use cases

Animation frames for video editing, automated CI screenshots, headless rendering for scripted pipelines.

Test plan

  • cargo test — 142/142 passing (141 unit + 1 integration test)
  • cargo fmt --check clean
  • cargo build --release clean
  • Manual: proteinview --batch examples/batch_demo.json renders 60 PNGs at 1920×1080 in ~2.6s
  • TUI path verified unchanged
  • Hotspot residue highlighting end-to-end test passes (hotspot_residues_are_visibly_recolored)

Architecture note

The TUI's render orchestration in App is coupled with Picker, Sixel encoding, frame-skip logic, and auto-rotate. Rather than disentangle those for shared use with batch mode, this PR introduces a thin wrapper render::draw_protein that batch calls directly while the TUI continues to call hd::render_hd_framebuffer directly. Documented in a NOTE comment in src/render/mod.rs. A future cleanup could unify the paths.

Known follow-ups

  • BatchConfig.render_mode field is parsed but only the FullHD path is honored. Other modes accepted for forward compatibility but no-op. TODO comment in code.
  • Ribbon mesh is rebuilt per frame in draw_protein (TUI caches it in App.mesh_cache). For scripted multi-frame rendering, hoist mesh construction into batch::run to cache once per protein.
  • Test coverage gaps: bad JSON input path, missing input file, frames=0 edge case.

001TMF added 15 commits April 29, 2026 20:08
Adds render_frame() to batch.rs backed by a new render::draw_protein()
wrapper around the existing hd::render_hd_framebuffer() pipeline.
Extracts parse_color_scheme() into render::color and VizMode::parse()
into app, and adds build_highlight_map() for future hotspot integration.
- Replace float-equality sentinel (cam.zoom == 1.0) with Option A:
  always auto-fit to protein extent, treat waypoint zoom as a multiplier
  (zoom:1.0 = fill frame, zoom:2.0 = 2x zoomed in). Eliminates
  interpolated-value misfire hazard entirely.
- Remove misleading `highlight_map` parameter reference from draw_protein
  doc; replace with Task 6 forward-reference note.
- Add "not yet consumed by draw_protein; wired in Task 6" note to
  build_highlight_map doc so callers don't assume it has effect.
- Add `use crate::model::protein::Protein` import; shorten render_frame
  signature from full crate path to bare `Protein`.
Implements `run()` as the top-level batch entrypoint: loads the protein,
iterates frames 1..=N computing t via (i-1)/max(1,frames-1), interpolates
camera via `camera_at`, renders via `render_frame`, and writes each frame
as `frame_NNNN.png` to `output_dir` (created with `create_dir_all`).

Adds `writes_png_sequence_to_output_dir` test: 5-frame sequence over a
160×120 render of 1UBQ.pdb, verifying all five PNGs land in a tempdir.
140/140 tests pass.
Add highlight_overrides field to ColorScheme with a with_highlights()
builder method. residue_color() checks overrides first before the
normal scheme logic, covering all render modes (cartoon via ribbon
mesh, backbone, wireframe). render_frame() now converts HighlightMap
into the ColorScheme override table instead of discarding it.

Adds hotspot_residues_are_visibly_recolored test confirming red pixel
count increases when hotspot covers first 20 residues of ubiquitin.
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.

1 participant