arrayview 0.31.2__tar.gz → 0.32.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {arrayview-0.31.2 → arrayview-0.32.0}/.github/workflows/launch-contracts.yml +4 -4
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/context/lifecycle.md +12 -2
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/context/project-state.md +12 -6
- {arrayview-0.31.2 → arrayview-0.32.0}/PKG-INFO +5 -2
- {arrayview-0.31.2 → arrayview-0.32.0}/README.md +4 -1
- {arrayview-0.31.2 → arrayview-0.32.0}/docs/index.md +2 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/docs/loading.md +31 -61
- arrayview-0.32.0/docs/stack-overlays.md +129 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/mkdocs.yml +1 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/pyproject.toml +1 -1
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/__init__.py +1 -3
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_io.py +376 -110
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_launcher.py +286 -153
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_routes_analysis.py +17 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_routes_loading.py +88 -5
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_routes_query.py +59 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_session.py +10 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_session_spec.py +0 -4
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_viewer.html +1016 -128
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_vscode_browser.py +19 -7
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_vscode_extension.py +195 -27
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_vscode_signal.py +55 -1
- arrayview-0.32.0/src/arrayview/arrayview-opener.vsix +0 -0
- arrayview-0.32.0/src/arrayview/todo.md +12 -0
- arrayview-0.32.0/tests/capture_patient_loading.py +120 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_api.py +309 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_browser.py +286 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_cli.py +172 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_command_reachability.py +1 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_display_opener_results.py +20 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_lifecycle_contract.py +270 -4
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_mode_roundtrip.py +183 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_nifti_series.py +235 -70
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_session_spec.py +0 -2
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_vscode_ack_protocol.py +61 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/uv.lock +1 -1
- {arrayview-0.31.2 → arrayview-0.32.0}/vscode-extension/extension.js +465 -104
- {arrayview-0.31.2 → arrayview-0.32.0}/vscode-extension/lifecycle_helpers.js +40 -1
- {arrayview-0.31.2 → arrayview-0.32.0}/vscode-extension/package.json +1 -1
- {arrayview-0.31.2 → arrayview-0.32.0}/vscode-extension/test_lifecycle_helpers.js +24 -1
- arrayview-0.32.0/vscode-extension/test_tunnel_resolution.js +55 -0
- arrayview-0.31.2/src/arrayview/arrayview-opener.vsix +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.agents/skills/frontend-designer/SKILL.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.agents/skills/invocation-consistency/SKILL.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.agents/skills/modes-consistency/SKILL.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.agents/skills/playwright-cli/SKILL.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.agents/skills/playwright-cli/references/element-attributes.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.agents/skills/playwright-cli/references/playwright-tests.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.agents/skills/playwright-cli/references/request-mocking.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.agents/skills/playwright-cli/references/running-code.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.agents/skills/playwright-cli/references/session-management.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.agents/skills/playwright-cli/references/storage-state.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.agents/skills/playwright-cli/references/test-generation.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.agents/skills/playwright-cli/references/tracing.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.agents/skills/playwright-cli/references/video-recording.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.agents/skills/todo-workflow/SKILL.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.agents/skills/ui-consistency-audit/SKILL.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.agents/skills/viewer-ui-checklist/SKILL.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.agents/skills/visual-bug-fixing/SKILL.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.github/copilot-instructions.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.github/workflows/docs.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.github/workflows/python-publish.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.gitignore +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.ignore +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/AGENTS.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/ROUTER.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/SETUP.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/SYNC.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/context/architecture.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/context/conventions.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/context/decisions.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/context/frontend.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/context/render-pipeline.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/context/setup.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/context/stack.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/patterns/INDEX.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/patterns/README.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/patterns/add-file-format.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/patterns/add-server-endpoint.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/patterns/animation-verify.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/patterns/debug-render.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/patterns/debug-vscode-extension-python.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/patterns/extend-compare-mode.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/patterns/extract-server-route-module.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/patterns/frontend-change.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/setup.sh +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.mex/sync.sh +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.opencode/opencode.json +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T18-46-49-737Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T18-48-21-979Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T18-51-35-665Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T19-07-01-393Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T19-14-37-969Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T19-21-30-940Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T19-23-08-126Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T19-29-33-155Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T19-31-25-336Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T19-31-53-789Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T19-39-12-257Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T19-39-16-449Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T20-15-25-513Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T20-25-13-179Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T20-39-01-435Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T21-01-27-659Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T21-01-41-283Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T21-03-00-625Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T21-04-12-887Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T21-33-39-044Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T21-38-01-530Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T21-45-20-383Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T21-55-11-545Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T21-56-03-307Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T21-56-35-733Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T21-57-12-181Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T21-57-37-748Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T21-58-13-679Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-06T22-37-23-895Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T00-39-18-637Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T01-41-46-243Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T04-31-48-472Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T12-14-15-632Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T12-14-47-582Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T12-16-23-471Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T12-17-10-247Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T12-18-24-707Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T12-20-06-164Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T12-20-28-342Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T12-21-54-962Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T12-22-34-666Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T12-23-11-336Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T12-23-36-260Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T12-24-09-267Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T12-24-35-434Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T12-25-57-010Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T12-34-48-823Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T12-46-46-468Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T12-48-17-930Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T12-49-26-400Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T12-50-31-563Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/page-2026-05-07T12-56-45-568Z.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.playwright-cli/theme-dark.yml +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.python-version +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/.vscode/settings.json +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/AGENTS.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/CONTRIBUTING.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/DESIGN.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/LICENSE +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/docs/comparing.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/docs/configuration.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/docs/display.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/docs/foreign-hosts.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/docs/launch-routing-refactor.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/docs/lifecycle.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/docs/logo.png +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/docs/measurement.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/docs/remote.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/docs/stylesheets/extra.css +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/docs/viewing.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/docs/vscode-window-routing-plan.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/experiments/ws_tunnel_diag/ws_tunnel_diag.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/matlab/arrayview.m +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/plans/2026-04-14-immersive-animation.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/plans/2026-05-07-unified-colormap-picker.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/plans/arrayview_tool_menu_fix_prompt.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/plans/arrayview_tool_menu_implementation_plan.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/plans/egg-placement-mockup.html +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/plans/refactoring_plan.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/plans/roi-analysis-requirements.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/plans/webview/LOG.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/scripts/demo.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/scripts/release.sh +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/ARCHITECTURE.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/__main__.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_analysis.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_app.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_codex_open.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_config.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_diff.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_icon.png +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_imaging.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_instance_registry.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_launch_plan.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_lifecycle.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_overlays.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_platform.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_render.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_routes_export.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_routes_persistence.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_routes_preload.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_routes_rendering.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_routes_segmentation.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_routes_state.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_routes_vectorfield.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_routes_websocket.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_segmentation.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_server.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_shell.html +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_synthetic_mri.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_torch.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_vectorfield.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/_vscode.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/src/arrayview/gsap.min.js +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/capture_v_animation.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/conftest.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/lifecycle_matrix.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/make_vectorfield_test_arrays.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_backend_shared.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_colorbar_hover_highlight.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_config.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_cross_mode_parametrized.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_doctor_commands.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_instance_registry.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_interactions.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_invocation_contract_matrix.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_io.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_large_arrays.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_launch_diagnostics.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_launch_plan.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_loading_server.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_mode_consistency.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_mode_matrix.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_nifti_meta.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_rgb_pixel_art.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_safe_server_stop.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_server_identity_status.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_torch.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_view_component_integration.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_view_component_unit.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_view_handle_lifecycle.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/test_view_launch_execution.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/ui_audit.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/v_anim_frames/.gitkeep +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/tests/visual_smoke.py +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/vscode-extension/AGENTS.md +0 -0
- {arrayview-0.31.2 → arrayview-0.32.0}/vscode-extension/LICENSE +0 -0
|
@@ -30,12 +30,12 @@ jobs:
|
|
|
30
30
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
31
31
|
runs-on: ${{ matrix.os }}
|
|
32
32
|
steps:
|
|
33
|
-
- uses: actions/checkout@
|
|
34
|
-
- uses: actions/setup-python@
|
|
33
|
+
- uses: actions/checkout@v7
|
|
34
|
+
- uses: actions/setup-python@v6
|
|
35
35
|
with:
|
|
36
36
|
python-version: "3.12"
|
|
37
|
-
- uses: astral-sh/setup-uv@
|
|
38
|
-
- uses: actions/setup-node@
|
|
37
|
+
- uses: astral-sh/setup-uv@v8
|
|
38
|
+
- uses: actions/setup-node@v6
|
|
39
39
|
with:
|
|
40
40
|
node-version: "22"
|
|
41
41
|
- run: uv sync --frozen --group dev --group test
|
|
@@ -16,7 +16,7 @@ edges:
|
|
|
16
16
|
condition: when component boundaries or display routing need broader context
|
|
17
17
|
- target: context/stack.md
|
|
18
18
|
condition: when VS Code, FastAPI, WebSocket, or packaging details are needed
|
|
19
|
-
last_updated: 2026-
|
|
19
|
+
last_updated: 2026-07-14
|
|
20
20
|
---
|
|
21
21
|
|
|
22
22
|
# Lifecycle
|
|
@@ -60,8 +60,10 @@ This contract describes who owns the backend, when it starts, and what closes it
|
|
|
60
60
|
|
|
61
61
|
- Remote or tunnel launches may persist when `--serve` or tunnel display ownership requires it.
|
|
62
62
|
- VS Code tunnel display uses forwarded localhost URLs; the extension should configure the port, promote privacy when available, and resolve the URL with `asExternalUri`.
|
|
63
|
-
- With multiple registered tunnel windows, a missing
|
|
63
|
+
- With multiple registered tunnel windows, a missing `ARRAYVIEW_WINDOW_ID` first recovers the exact live registration from the terminal's IPC hook. Only when no exact registration exists does it use the shared focused-window broadcast fallback.
|
|
64
64
|
- An exact registered `ARRAYVIEW_WINDOW_ID` wins; do not redirect it to a newer same-parent registration because live tunnel windows can share ancestry.
|
|
65
|
+
- Protocol request claims are atomic across extension hosts. Compatibility queue copies with the same request ID must never open in a sibling window or overwrite a terminal ACK.
|
|
66
|
+
- Tunnel `asExternalUri` results must be non-loopback. Remote-SSH may legitimately resolve to a local forwarded URL and must not be subjected to tunnel-only public-port commands.
|
|
65
67
|
- Plain SSH should use `localhost` forwarding guidance and stay transient unless a shared server was explicitly requested.
|
|
66
68
|
|
|
67
69
|
## Shared Rules
|
|
@@ -70,6 +72,14 @@ This contract describes who owns the backend, when it starts, and what closes it
|
|
|
70
72
|
- `release_session()` is the session-release primitive.
|
|
71
73
|
- Viewer WebSocket connect/disconnect owns active viewer counts.
|
|
72
74
|
- URL panel disposal must release every SID encoded in the URL: `sid`, `compare_sid`, `compare_sids`, and `overlay_sid`.
|
|
75
|
+
- Tunnel panel disposal posts release requests to the local backend immediately;
|
|
76
|
+
the forwarded public URL is display-only and is not the cleanup authority.
|
|
77
|
+
- Reused file and collection sessions acquire one lease per tab, so closing one
|
|
78
|
+
tab cannot invalidate another tab that shares the same SID.
|
|
79
|
+
- A VS Code readiness ACK includes the live opener version and is terminal only
|
|
80
|
+
after the requested SID exists and the viewer reports its first rendered frame.
|
|
81
|
+
- Existing-server tunnel loads publish a pending SID before loading large files, so port resolution can overlap disk I/O. Pending metadata probes return immediately and the WebSocket waits on the shared pending-session event.
|
|
82
|
+
- Older ArrayView packages must not delete or downgrade a newer installed opener.
|
|
73
83
|
- Tunnel registration cleanup must not remove live same-tunnel sibling windows.
|
|
74
84
|
- Explicit cleanup wins over implicit disappearance.
|
|
75
85
|
- Any VS Code extension source change must rebuild `src/arrayview/arrayview-opener.vsix` and keep the packaged version in sync.
|
|
@@ -7,7 +7,7 @@ triggers:
|
|
|
7
7
|
- "recent work"
|
|
8
8
|
- "active feature"
|
|
9
9
|
- "shipped recently"
|
|
10
|
-
last_updated: 2026-
|
|
10
|
+
last_updated: 2026-07-20
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
# Project State
|
|
@@ -20,8 +20,8 @@ last_updated: 2026-06-30
|
|
|
20
20
|
- Rendering pipeline: colormaps, complex modes, mosaic, RGB/RGBA, projections, overlays
|
|
21
21
|
- Backend transport: FastAPI HTTP/WebSocket is the single viewer transport; shared helpers keep route modules small for metadata/analysis, compare/diff, overlay compositing, and vector field layout/arrow sampling.
|
|
22
22
|
- NIfTI spatial metadata, RAS resampling
|
|
23
|
-
- Directory collections are header-scanned and lazy by default: compatible files form a dense virtual stack, mixed shapes use a ragged collection, and `--load lazy|eager` plus `--stack-policy auto|dense|ragged` make both choices explicit.
|
|
24
|
-
- VS Code extension v0.14.
|
|
23
|
+
- Directory collections are header-scanned and lazy by default: compatible files form a dense virtual stack, mixed shapes use a ragged collection, and `--load lazy|eager` plus `--stack-policy auto|dense|ragged` make both choices explicit. Supported 3D `.nii.gz` stacks now return the requested axial plane while the same one-pass decode finishes in the byte-bounded LRU cache; unsupported layouts fall back safely. Patient changes show a centered loading card until the matching frame arrives. `view_dir()` exposes the same collection controls.
|
|
24
|
+
- VS Code extension v0.14.43 — exact tunnel-window recovery from the terminal IPC hook, atomic cross-window request claims, non-loopback tunnel URL enforcement, queued concurrent requests, remote-only tunnel claims, live opener-version ACKs, first-frame readiness, and immediate local-backend session release. Successful port-public promotion is cached per external tunnel URL, and existing-server tunnel loads overlap port setup with pending background data loading.
|
|
25
25
|
- Colorbar refactor: `ColorBar` JS class partially migrated (in progress)
|
|
26
26
|
- Colormap picker: `c` opens an expanded colorbar-island grid without changing the colormap; subsequent `c` taps cycle, hover/hjkl/arrows live-preview, Enter/click commits, Esc cancels, and auto-dismiss pauses while hovered
|
|
27
27
|
- Cold-start loading spinner in VS Code and native shell
|
|
@@ -48,9 +48,10 @@ last_updated: 2026-06-30
|
|
|
48
48
|
patient/modality directory layouts pair automatically. `--case-regex` remains
|
|
49
49
|
an override for unusual layouts. CLI header scans show an in-place file counter
|
|
50
50
|
and elapsed time on interactive terminals.
|
|
51
|
-
- Reused collection sessions are protected by per-tab leases, including
|
|
52
|
-
overlay sessions
|
|
53
|
-
|
|
51
|
+
- Reused file and collection sessions are protected by per-tab leases, including
|
|
52
|
+
collection overlay sessions. The VS Code opener verifies the local SID before
|
|
53
|
+
creating a panel and waits for the viewer's first rendered frame before
|
|
54
|
+
acknowledging `backend_ready`.
|
|
54
55
|
- Filesystem picker endpoint (`GET /fs/list`) clamped to `$HOME`. Accepts `base_sid` + `mode` (`overlay` | `vectorfield`) to filter entries by a cheap header-shape peek (`.npy`, `.nii`/`.nii.gz`, `.h5`, `.zarr`); overlay mode requires identical shape, vectorfield mode requires base shape plus one axis of size 3
|
|
55
56
|
- Island collapse affordance: inline `~` at the island's top-right animates the panel into the bottom-left `~` hint circle; external `~` hint only visible while the island is actually collapsed. New `/` hint circle at bottom-right opens the tool menu
|
|
56
57
|
- Compare center tool menu: `/` now re-opens the last-used compare center mode from the tool menu, while compare pane header buttons select diff / overlay / wipe directly. Eligible two-array compare layouts can switch into a big-left arrangement with a wider center pane, and the diff colorbar now matches that center-pane width.
|
|
@@ -59,6 +60,10 @@ last_updated: 2026-06-30
|
|
|
59
60
|
|
|
60
61
|
## Recently Completed
|
|
61
62
|
|
|
63
|
+
- Jupyter inline viewports automatically fit ortho content and restore the
|
|
64
|
+
normal `height` on exit. `mode_heights` remains available for explicit
|
|
65
|
+
overrides. Direct, proxied, multi-array, and IJulia inline paths share the
|
|
66
|
+
same mode-change bridge.
|
|
62
67
|
- ROI keybind changed from `r` to `Shift+R` (`R`); rotate/flip is now `r`, transpose is `t`
|
|
63
68
|
- Crossfade animation added to rotate/transpose transitions
|
|
64
69
|
- `--version` flag and version string in help overlay
|
|
@@ -85,6 +90,7 @@ last_updated: 2026-06-30
|
|
|
85
90
|
|
|
86
91
|
## In Progress
|
|
87
92
|
|
|
93
|
+
- VS Code tunnel opener v0.14.43 is installed on disk and fully covered by focused lifecycle/ACK tests; active 0.14.42 extension hosts still need one window reload before post-change live timing and multi-window verification.
|
|
88
94
|
- Smooth immersive transition — stale scrub geometry handoff is fixed, immersive overlay fade-in is held until after the class switch, shared slim colorbar returns through `drawSlimColorbar()` on reverse, and active scrub suppresses minimap/overflow/drag side effects. Single-pane scrub now targets the actual centered immersive viewport rect instead of a hardcoded corner box, the dimbar stays above the pane during scrub, the shared colorbar sits behind the growing pane, and the phantom extra `av-view-wrap` footprint in normal mode was removed by rebinding `NormalLayout` to the real `#viewer` canvas. Cross-mode parity and deeper reverse-pinch validation still need manual verification.
|
|
89
95
|
- ROI + qMRI integration refinements: floodfill not yet supported on qMRI panes; per-pane stats are re-fetched on each ROI draw but not updated on slice scroll
|
|
90
96
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: arrayview
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.32.0
|
|
4
4
|
Summary: Fast multi-dimensional array viewer
|
|
5
5
|
Project-URL: Home, https://github.com/oscarvanderheide/arrayview
|
|
6
6
|
Project-URL: Source, https://github.com/oscarvanderheide/arrayview
|
|
@@ -51,7 +51,10 @@ Curious? Give it a try with
|
|
|
51
51
|
uvx arrayview your_array.npy
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
+
Press `v` for the three-plane ortho view. `Shift+3` replaces the current slice,
|
|
55
|
+
or all three ortho panes, with interactive 3D cutaway renders.
|
|
56
|
+
|
|
54
57
|
|
|
55
58
|
Check the [docs](https://oscarvanderheide.github.io/arrayview/) to learn more.
|
|
56
59
|
|
|
57
|
-
**Warning**: Arrayview is still under active development. Things may break or change without warning.
|
|
60
|
+
**Warning**: Arrayview is still under active development. Things may break or change without warning.
|
|
@@ -15,7 +15,10 @@ Curious? Give it a try with
|
|
|
15
15
|
uvx arrayview your_array.npy
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
+
Press `v` for the three-plane ortho view. `Shift+3` replaces the current slice,
|
|
19
|
+
or all three ortho panes, with interactive 3D cutaway renders.
|
|
20
|
+
|
|
18
21
|
|
|
19
22
|
Check the [docs](https://oscarvanderheide.github.io/arrayview/) to learn more.
|
|
20
23
|
|
|
21
|
-
**Warning**: Arrayview is still under active development. Things may break or change without warning.
|
|
24
|
+
**Warning**: Arrayview is still under active development. Things may break or change without warning.
|
|
@@ -30,6 +30,8 @@ MATLAB and Julia setup: [MATLAB and Julia](foreign-hosts.md).
|
|
|
30
30
|
|
|
31
31
|
Remote and tunnel setup: [Remote](remote.md).
|
|
32
32
|
|
|
33
|
+
Stacked patient collections and masks: [Stack and Overlay Collections](stack-overlays.md).
|
|
34
|
+
|
|
33
35
|
## Formats
|
|
34
36
|
|
|
35
37
|
`.npy` `.npz` `.nii` `.nii.gz` `.zarr` `.pt` `.h5` `.tif` `.mat`
|
|
@@ -54,6 +54,8 @@ Key parameters:
|
|
|
54
54
|
| `name` | str | Label shown in the viewer tab |
|
|
55
55
|
| `port` | int | Server port (default 8123 for Python API, 8000 for CLI) |
|
|
56
56
|
| `window` | str \| None | How to open the viewer (see below) |
|
|
57
|
+
| `height` | int | Default inline notebook height in pixels |
|
|
58
|
+
| `mode_heights` | dict | Inline height overrides, e.g. `{"ortho": 360, "qmri": 480}` |
|
|
57
59
|
| `rgb` | bool | Treat last/first axis as RGB/RGBA channels |
|
|
58
60
|
| `overlay` | array or list | Arrays composited as overlays |
|
|
59
61
|
|
|
@@ -67,6 +69,9 @@ Key parameters:
|
|
|
67
69
|
| `"vscode"` | VS Code tab |
|
|
68
70
|
| `"inline"` | Inline IFrame (Jupyter / VS Code notebook) |
|
|
69
71
|
|
|
72
|
+
Inline ortho view automatically removes unused height. `mode_heights` is only
|
|
73
|
+
needed to override the automatic size.
|
|
74
|
+
|
|
70
75
|
## File Picker
|
|
71
76
|
|
|
72
77
|
`Cmd/Ctrl+O` or `P` opens the file picker.
|
|
@@ -85,7 +90,7 @@ Native windows also show a static preview while the live viewer warms up.
|
|
|
85
90
|
```bash
|
|
86
91
|
uvx arrayview base.npy moving.npy # compare mode
|
|
87
92
|
uvx arrayview volume.nii.gz --overlay mask.nii.gz
|
|
88
|
-
uvx arrayview volume.nii.gz --overlay "ground truth=
|
|
93
|
+
uvx arrayview volume.nii.gz --overlay "ground truth=mask_gt.nii.gz" --overlay "prediction=mask_pred.nii.gz"
|
|
89
94
|
```
|
|
90
95
|
|
|
91
96
|
An unnamed overlay uses the filename stem as its display name (`mask` above).
|
|
@@ -99,8 +104,7 @@ shows all overlays at once.
|
|
|
99
104
|
|
|
100
105
|
## Directory Pattern Collections
|
|
101
106
|
|
|
102
|
-
Use `--stack` when reviewing many arrays.
|
|
103
|
-
files recursively; passing patterns keeps the aligned channel/overlay workflow.
|
|
107
|
+
Use `--stack` when reviewing many arrays.
|
|
104
108
|
|
|
105
109
|
```bash
|
|
106
110
|
uvx arrayview --stack scans/
|
|
@@ -115,53 +119,14 @@ dense` requires matching shapes, while `--stack-policy ragged` forces collection
|
|
|
115
119
|
semantics. `--load eager` is intended for small datasets that should be loaded
|
|
116
120
|
up front.
|
|
117
121
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
```bash
|
|
121
|
-
uvx arrayview --stack "data/**/*_0000.nii.gz" "data/**/*_0001.nii.gz"
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
Overlays become named recursive patterns:
|
|
122
|
+
Pattern collections, named overlays, multiple overlays, and `--overlay-dir`:
|
|
123
|
+
[Stack and Overlay Collections](stack-overlays.md).
|
|
125
124
|
|
|
126
|
-
|
|
127
|
-
uvx arrayview --stack \
|
|
128
|
-
"data/**/*_0000.nii.gz" \
|
|
129
|
-
"data/**/*_0001.nii.gz" \
|
|
130
|
-
--overlay "gt=data/**/labels/**/*.nii.gz" \
|
|
131
|
-
--overlay "pred=data/**/pred/**/*.nii.gz"
|
|
132
|
-
```
|
|
125
|
+
## NIfTI Series
|
|
133
126
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
layouts such as `sub-0001/T1_W/` and `sub-0001/masks/`:
|
|
138
|
-
|
|
139
|
-
```bash
|
|
140
|
-
uvx arrayview --stack "data/*/T1_W/*.nii.gz" \
|
|
141
|
-
--overlay-dir "data/*/masks"
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
Repeat `--overlay-dir` to combine masks from multiple per-case directories.
|
|
145
|
-
|
|
146
|
-
ArrayView pairs files by sorted match order. The first match from each pattern
|
|
147
|
-
belongs to the first case, the second match belongs to the second case, and so
|
|
148
|
-
on. Use `--dry-run` to inspect matches without opening a viewer.
|
|
149
|
-
|
|
150
|
-
```bash
|
|
151
|
-
uvx arrayview --stack "data/**/*_0000.nii.gz" --overlay "gt=data/**/labels/*.nii.gz" --dry-run
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
For unusual or ambiguous layouts, pass a regex with a `case` group to override
|
|
155
|
-
automatic directory inference:
|
|
156
|
-
|
|
157
|
-
```bash
|
|
158
|
-
uvx arrayview --stack "data/**/*.nii.gz" --case-regex "(?P<case>patient-[0-9]+)"
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
## NIfTI Series (4D/5D from a directory)
|
|
162
|
-
|
|
163
|
-
Stack a directory of NIfTI files into a single lazy 4D/5D array — only the
|
|
164
|
-
viewed slice is loaded, so RAM stays bounded regardless of series size.
|
|
127
|
+
Stack a directory of NIfTI files into a single lazy 4D/5D array. Patient files
|
|
128
|
+
are loaded only when needed, and the memory cache stays bounded regardless of
|
|
129
|
+
series size.
|
|
165
130
|
|
|
166
131
|
```bash
|
|
167
132
|
uvx arrayview patients/
|
|
@@ -173,27 +138,32 @@ Discovers `.nii`/`.nii.gz` recursively, groups by immediate parent folder
|
|
|
173
138
|
One file per patient → 4D `(*vol, P)`. The viewer opens with X/Y on screen,
|
|
174
139
|
Z as primary scroll, patient index as a slider.
|
|
175
140
|
|
|
176
|
-
|
|
141
|
+
For multiple files per patient, use explicit `--stack` patterns:
|
|
177
142
|
|
|
178
143
|
```bash
|
|
179
|
-
uvx arrayview
|
|
144
|
+
uvx arrayview --stack \
|
|
145
|
+
"patients/*/*t1*.nii.gz" \
|
|
146
|
+
"patients/*/*t2*.nii.gz" \
|
|
147
|
+
"patients/*/*flair*.nii.gz"
|
|
180
148
|
```
|
|
181
149
|
|
|
182
|
-
|
|
183
|
-
Produces 5D `(*vol, P, M)` with modality as the last axis. Every patient
|
|
184
|
-
must match exactly one file per pattern.
|
|
150
|
+
More examples: [Stack and Overlay Collections](stack-overlays.md).
|
|
185
151
|
|
|
186
|
-
|
|
152
|
+
Patient folders with no NIfTI files (e.g. only `.dcm`) raise an error —
|
|
153
|
+
convert DICOM to NIfTI first (e.g. `dcm2niix`).
|
|
187
154
|
|
|
188
|
-
|
|
189
|
-
from arrayview import view_dir
|
|
155
|
+
### First image from compressed patients
|
|
190
156
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
157
|
+
For a normal 3D `.nii.gz` patient, ArrayView shows the requested axial slice as
|
|
158
|
+
soon as that slice has been unpacked. It keeps unpacking the rest of the same
|
|
159
|
+
file in the background and saves the completed volume in the existing memory
|
|
160
|
+
cache. The file is not unpacked a second time.
|
|
194
161
|
|
|
195
|
-
|
|
196
|
-
|
|
162
|
+
This shortens the visible wait, but it does not make gzip random-access. A slice
|
|
163
|
+
near the middle still requires reading roughly the first half of the file.
|
|
164
|
+
Side views, 4D files, and unusual orientations fall back to loading the complete
|
|
165
|
+
volume first so their data remains correct. Moving quickly between patients
|
|
166
|
+
stops outdated background work instead of building a long loading queue.
|
|
197
167
|
|
|
198
168
|
## Zarr
|
|
199
169
|
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Stack and Overlay Collections
|
|
2
|
+
|
|
3
|
+
Review many arrays with aligned image and mask patterns.
|
|
4
|
+
|
|
5
|
+
## Patient Stack
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
uvx arrayview --stack "data/*/T1w.nii.gz"
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`*` matches one path segment. `**` matches recursively:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
uvx arrayview --stack "data/**/*.nii.gz"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
ArrayView sorts matches and adds a collection index dimension. Use `--dry-run`
|
|
18
|
+
to inspect pairings without opening the viewer:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
uvx arrayview --stack "data/*/T1w.nii.gz" --dry-run
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## MR Contrasts
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
uvx arrayview --stack \
|
|
28
|
+
"data/*/T1w.nii.gz" \
|
|
29
|
+
"data/*/T2w.nii.gz" \
|
|
30
|
+
"data/*/FLAIR.nii.gz"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Each positional pattern becomes a contrast dimension. The first `T1w`, first
|
|
34
|
+
`T2w`, and first `FLAIR` belong to patient 1; the second match from each pattern
|
|
35
|
+
belongs to patient 2.
|
|
36
|
+
|
|
37
|
+
For ambiguous layouts, define the patient key:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
uvx arrayview --stack "data/**/*.nii.gz" \
|
|
41
|
+
--case-regex "(?P<case>sub-[0-9]+)"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Ragged Shapes
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
uvx arrayview --stack "data/*/T1w.nii.gz" --stack-policy ragged
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`--stack-policy auto` uses a dense stack when shapes match and ragged mode when
|
|
51
|
+
they do not. `--stack-policy dense` requires matching shapes.
|
|
52
|
+
|
|
53
|
+
## One Overlay
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
uvx arrayview --stack "data/*/T1w.nii.gz" \
|
|
57
|
+
--overlay "lesion=data/*/masks/lesion.nii.gz"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Use `name=pattern` to control the overlay label. Without `name=`, the filename
|
|
61
|
+
stem is used.
|
|
62
|
+
|
|
63
|
+
## Multiple Overlays
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
uvx arrayview --stack "data/*/T1w.nii.gz" \
|
|
67
|
+
--overlay "gt=data/*/masks/gt.nii.gz" \
|
|
68
|
+
--overlay "pred=data/*/masks/pred.nii.gz"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Overlays are paired to cases by sorted match order unless `--case-regex` is
|
|
72
|
+
provided.
|
|
73
|
+
|
|
74
|
+
## Overlay Directories
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
uvx arrayview --stack "data/*/T1w.nii.gz" \
|
|
78
|
+
--overlay-dir "data/*/masks"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`--overlay-dir` creates one overlay role per mask filename inside each matched
|
|
82
|
+
directory. Missing masks are shown as empty overlays.
|
|
83
|
+
|
|
84
|
+
Repeat it to combine mask folders:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
uvx arrayview --stack "data/*/T1w.nii.gz" \
|
|
88
|
+
--overlay-dir "data/*/manual_masks" \
|
|
89
|
+
--overlay-dir "data/*/model_masks"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Complete Example
|
|
93
|
+
|
|
94
|
+
```text
|
|
95
|
+
data/
|
|
96
|
+
sub-001/
|
|
97
|
+
anat/T1w.nii.gz
|
|
98
|
+
anat/T2w.nii.gz
|
|
99
|
+
masks/lesion.nii.gz
|
|
100
|
+
masks/edema.nii.gz
|
|
101
|
+
sub-002/
|
|
102
|
+
anat/T1w.nii.gz
|
|
103
|
+
anat/T2w.nii.gz
|
|
104
|
+
masks/lesion.nii.gz
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
uvx arrayview --stack \
|
|
109
|
+
"data/*/anat/T1w.nii.gz" \
|
|
110
|
+
"data/*/anat/T2w.nii.gz" \
|
|
111
|
+
--overlay-dir "data/*/masks" \
|
|
112
|
+
--stack-policy auto \
|
|
113
|
+
--dry-run
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Remove `--dry-run` to open the viewer.
|
|
117
|
+
|
|
118
|
+
## Compressed NIfTI Performance
|
|
119
|
+
|
|
120
|
+
`.nii.gz` files are lazy through nibabel, but gzip compression limits random
|
|
121
|
+
slice access. Large compressed collections can feel slower when scrolling across
|
|
122
|
+
many patients or contrasts.
|
|
123
|
+
|
|
124
|
+
For repeated review, prefer uncompressed `.nii`, chunked `.zarr`, or a local
|
|
125
|
+
fast disk cache. Use `--load eager` only for small collections that fit in RAM:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
uvx arrayview --stack "data/*/T1w.nii.gz" --load eager
|
|
129
|
+
```
|
|
@@ -7,14 +7,12 @@ __all__ = [
|
|
|
7
7
|
"arrayview",
|
|
8
8
|
"view",
|
|
9
9
|
"view_batch",
|
|
10
|
-
"view_dir",
|
|
11
|
-
"view_dir_patterns",
|
|
12
10
|
"zarr_chunk_preset",
|
|
13
11
|
]
|
|
14
12
|
|
|
15
13
|
|
|
16
14
|
def __getattr__(name: str):
|
|
17
|
-
if name in {"arrayview", "view", "
|
|
15
|
+
if name in {"arrayview", "view", "ViewHandle"}:
|
|
18
16
|
from arrayview import _launcher
|
|
19
17
|
|
|
20
18
|
return getattr(_launcher, name)
|