Visual Parity Testing#
EEGPREP aims to keep future desktop UI behavior familiar to EEGLAB users. The visual parity tools capture the same UI state in EEGLAB and EEGPREP, generate a side-by-side image, and write a short review prompt that an agent or human can use to give concrete UI feedback.
The workflow is local and advisory. It is not part of required CI because it depends on a stable desktop session, MATLAB Desktop, fixed fonts, and the optional EEGPREP Qt UI.
Headless MATLAB batch sessions can run structural checks, but they cannot
capture EEGLAB UI controls with getframe unless figure windows are actually
displayed.
EEG Movies and Visual Workflow Boundaries#
EEGLAB’s tutorial movie scripts, such as make_eeg_movie.m, are treated as
visual workflow references for this epic rather than standalone EEGPrep runtime
features. EEGPrep owns static plots, ERP images, time-frequency wrappers, GUI
dialog rendering, and the visual parity capture tooling described here. It does
not currently ship an EEGLAB-compatible EEG movie generator or a persistent
movie-authoring UI. Use the plotting wrappers documented in
Preprocessing Pipeline for analysis figures, and use this page’s capture
tools for reviewable GUI evidence.
Install the optional EEGPREP GUI dependencies before capturing Python dialogs:
uv sync --extra gui --group dev
Start a Virtual Desktop#
MATLAB GUI capture needs an X11 display. Prefer a reusable virtual desktop so
each capture command inherits the same DISPLAY:
Xvfb :99 -screen 0 1920x1080x24 -ac +extension GLX +render -noreset \
> /tmp/xvfb99.log 2>&1 &
export DISPLAY=:99
openbox > /tmp/openbox99.log 2>&1 &
xdpyinfo | head
Some shared servers provide TigerVNC instead of Xvfb. In that case, this is
equivalent for local screenshot capture:
# Terminal 1: keep the virtual X server running.
Xvnc :99 -geometry 1920x1080 -depth 24 -SecurityTypes None -localhost \
-ac -noreset +extension GLX +render
# Terminal 2: run captures against that display.
export DISPLAY=:99
xdpyinfo | head
List Available Cases#
uv run --no-sync python tools/visual_parity/capture.py --list
Capture Screenshots#
Capture both targets for a configured case:
export DISPLAY=:99
uv run --no-sync python tools/visual_parity/capture.py --case main_window --target both
Capture the first pop-function dialog parity case:
export DISPLAY=:99
uv run --no-sync python tools/visual_parity/capture.py \
--case adjust_events_dialog \
--target both
Capture only EEGPREP using a command supplied by the caller:
uv run --no-sync python tools/visual_parity/capture.py \
--case file_menu \
--target eegprep \
--eegprep-command "python -m tools.visual_parity.visual_capture --case {case_id} --output {output}"
Capture commands receive these environment variables:
EEGPREP_VISUAL_CASE_IDEEGPREP_VISUAL_TARGETEEGPREP_VISUAL_ACTIONEEGPREP_VISUAL_OUTPUTEEGPREP_VISUAL_OUTPUT_DIREEGPREP_VISUAL_WINDOW_WIDTHEEGPREP_VISUAL_WINDOW_HEIGHTEEGPREP_REPO_ROOT
Compare Screenshots#
uv run --no-sync python tools/visual_parity/compare.py --case adjust_events_dialog
The comparison writes artifacts under .visual-parity/<case>/:
eeglab.pngandeegprep.pngside_by_side.pngdiff.pngreport.md
Use report.md as the high-signal prompt for a visual review model. The
pixel metrics are useful for spotting large differences, but menu labels,
ordering, enabled state, and dialog layout are more important than exact pixels.
Keep generated screenshots and side-by-side images out of committed docs unless
the project explicitly asks for a durable reference image. For PR reviews, attach
or link the generated side_by_side.png in the PR comment instead.