arrayview 0.31.1__tar.gz → 0.31.2__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.1 → arrayview-0.31.2}/PKG-INFO +1 -1
- {arrayview-0.31.1 → arrayview-0.31.2}/pyproject.toml +1 -1
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_instance_registry.py +6 -0
- arrayview-0.31.2/src/arrayview/_overlays.py +150 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_routes_rendering.py +12 -1
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_routes_websocket.py +15 -1
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_vscode_browser.py +2 -1
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_api.py +51 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_lifecycle_contract.py +6 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_vscode_ack_protocol.py +7 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/uv.lock +1 -1
- {arrayview-0.31.1 → arrayview-0.31.2}/vscode-extension/test_lifecycle_helpers.js +8 -6
- arrayview-0.31.1/src/arrayview/_overlays.py +0 -76
- {arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/frontend-designer/SKILL.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/invocation-consistency/SKILL.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/modes-consistency/SKILL.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/playwright-cli/SKILL.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/playwright-cli/references/element-attributes.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/playwright-cli/references/playwright-tests.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/playwright-cli/references/request-mocking.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/playwright-cli/references/running-code.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/playwright-cli/references/session-management.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/playwright-cli/references/storage-state.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/playwright-cli/references/test-generation.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/playwright-cli/references/tracing.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/playwright-cli/references/video-recording.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/todo-workflow/SKILL.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/ui-consistency-audit/SKILL.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/viewer-ui-checklist/SKILL.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/visual-bug-fixing/SKILL.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.github/copilot-instructions.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.github/workflows/docs.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.github/workflows/launch-contracts.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.github/workflows/python-publish.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.gitignore +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.ignore +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/AGENTS.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/ROUTER.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/SETUP.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/SYNC.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/context/architecture.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/context/conventions.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/context/decisions.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/context/frontend.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/context/lifecycle.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/context/project-state.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/context/render-pipeline.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/context/setup.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/context/stack.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/patterns/INDEX.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/patterns/README.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/patterns/add-file-format.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/patterns/add-server-endpoint.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/patterns/animation-verify.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/patterns/debug-render.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/patterns/debug-vscode-extension-python.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/patterns/extend-compare-mode.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/patterns/extract-server-route-module.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/patterns/frontend-change.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/setup.sh +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.mex/sync.sh +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.opencode/opencode.json +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T18-46-49-737Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T18-48-21-979Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T18-51-35-665Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T19-07-01-393Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T19-14-37-969Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T19-21-30-940Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T19-23-08-126Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T19-29-33-155Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T19-31-25-336Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T19-31-53-789Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T19-39-12-257Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T19-39-16-449Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T20-15-25-513Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T20-25-13-179Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T20-39-01-435Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T21-01-27-659Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T21-01-41-283Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T21-03-00-625Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T21-04-12-887Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T21-33-39-044Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T21-38-01-530Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T21-45-20-383Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T21-55-11-545Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T21-56-03-307Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T21-56-35-733Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T21-57-12-181Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T21-57-37-748Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T21-58-13-679Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-06T22-37-23-895Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T00-39-18-637Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T01-41-46-243Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T04-31-48-472Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T12-14-15-632Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T12-14-47-582Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T12-16-23-471Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T12-17-10-247Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T12-18-24-707Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T12-20-06-164Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T12-20-28-342Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T12-21-54-962Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T12-22-34-666Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T12-23-11-336Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T12-23-36-260Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T12-24-09-267Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T12-24-35-434Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T12-25-57-010Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T12-34-48-823Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T12-46-46-468Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T12-48-17-930Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T12-49-26-400Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T12-50-31-563Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/page-2026-05-07T12-56-45-568Z.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.playwright-cli/theme-dark.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.python-version +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/.vscode/settings.json +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/AGENTS.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/CONTRIBUTING.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/DESIGN.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/LICENSE +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/README.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/docs/comparing.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/docs/configuration.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/docs/display.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/docs/foreign-hosts.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/docs/index.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/docs/launch-routing-refactor.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/docs/lifecycle.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/docs/loading.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/docs/logo.png +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/docs/measurement.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/docs/remote.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/docs/stylesheets/extra.css +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/docs/viewing.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/docs/vscode-window-routing-plan.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/experiments/ws_tunnel_diag/ws_tunnel_diag.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/matlab/arrayview.m +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/mkdocs.yml +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/plans/2026-04-14-immersive-animation.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/plans/2026-05-07-unified-colormap-picker.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/plans/arrayview_tool_menu_fix_prompt.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/plans/arrayview_tool_menu_implementation_plan.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/plans/egg-placement-mockup.html +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/plans/refactoring_plan.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/plans/roi-analysis-requirements.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/plans/webview/LOG.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/scripts/demo.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/scripts/release.sh +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/ARCHITECTURE.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/__init__.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/__main__.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_analysis.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_app.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_codex_open.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_config.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_diff.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_icon.png +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_imaging.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_io.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_launch_plan.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_launcher.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_lifecycle.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_platform.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_render.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_routes_analysis.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_routes_export.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_routes_loading.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_routes_persistence.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_routes_preload.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_routes_query.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_routes_segmentation.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_routes_state.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_routes_vectorfield.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_segmentation.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_server.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_session.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_session_spec.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_shell.html +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_synthetic_mri.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_torch.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_vectorfield.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_viewer.html +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_vscode.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_vscode_extension.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/_vscode_signal.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/arrayview-opener.vsix +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/src/arrayview/gsap.min.js +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/capture_v_animation.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/conftest.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/lifecycle_matrix.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/make_vectorfield_test_arrays.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_backend_shared.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_browser.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_cli.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_colorbar_hover_highlight.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_command_reachability.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_config.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_cross_mode_parametrized.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_display_opener_results.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_doctor_commands.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_instance_registry.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_interactions.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_invocation_contract_matrix.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_io.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_large_arrays.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_launch_diagnostics.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_launch_plan.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_loading_server.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_mode_consistency.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_mode_matrix.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_mode_roundtrip.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_nifti_meta.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_nifti_series.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_rgb_pixel_art.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_safe_server_stop.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_server_identity_status.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_session_spec.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_torch.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_view_component_integration.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_view_component_unit.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_view_handle_lifecycle.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/test_view_launch_execution.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/ui_audit.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/v_anim_frames/.gitkeep +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/tests/visual_smoke.py +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/vscode-extension/AGENTS.md +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/vscode-extension/LICENSE +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/vscode-extension/extension.js +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/vscode-extension/lifecycle_helpers.js +0 -0
- {arrayview-0.31.1 → arrayview-0.31.2}/vscode-extension/package.json +0 -0
|
@@ -115,11 +115,17 @@ def _windows_process_start(pid: int) -> str | None:
|
|
|
115
115
|
handle = kernel32.OpenProcess(0x1000, False, pid)
|
|
116
116
|
if not handle:
|
|
117
117
|
return None
|
|
118
|
+
still_active = 259
|
|
119
|
+
exit_code = ctypes.c_ulong()
|
|
118
120
|
creation = ctypes.c_ulonglong()
|
|
119
121
|
exit_time = ctypes.c_ulonglong()
|
|
120
122
|
kernel = ctypes.c_ulonglong()
|
|
121
123
|
user = ctypes.c_ulonglong()
|
|
122
124
|
try:
|
|
125
|
+
if not kernel32.GetExitCodeProcess(handle, ctypes.byref(exit_code)):
|
|
126
|
+
return None
|
|
127
|
+
if exit_code.value != still_active:
|
|
128
|
+
return None
|
|
123
129
|
ok = kernel32.GetProcessTimes(handle, ctypes.byref(creation),
|
|
124
130
|
ctypes.byref(exit_time), ctypes.byref(kernel),
|
|
125
131
|
ctypes.byref(user))
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"""Shared overlay compositing helpers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
from arrayview._render import (
|
|
8
|
+
_build_mosaic_grid,
|
|
9
|
+
_composite_overlay_mask,
|
|
10
|
+
_extract_overlay_mask,
|
|
11
|
+
_overlay_is_label_map,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _parse_hex_color(hex_str: str) -> np.ndarray | None:
|
|
16
|
+
"""Parse a 6-char hex RGB color."""
|
|
17
|
+
h = hex_str.strip().lstrip("#")
|
|
18
|
+
if len(h) != 6:
|
|
19
|
+
return None
|
|
20
|
+
try:
|
|
21
|
+
return np.array(
|
|
22
|
+
[int(h[0:2], 16), int(h[2:4], 16), int(h[4:6], 16)],
|
|
23
|
+
dtype=np.uint8,
|
|
24
|
+
)
|
|
25
|
+
except ValueError:
|
|
26
|
+
return None
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _composite_overlays(
|
|
30
|
+
rgba: np.ndarray,
|
|
31
|
+
overlay_sid_str: str | None,
|
|
32
|
+
overlay_colors_str: str | None,
|
|
33
|
+
overlay_alpha: float,
|
|
34
|
+
overlay_alphas_str: str | None,
|
|
35
|
+
overlay_outline: bool,
|
|
36
|
+
dim_x: int,
|
|
37
|
+
dim_y: int,
|
|
38
|
+
idx_tuple: tuple[int, ...],
|
|
39
|
+
shape_hw: tuple[int, int],
|
|
40
|
+
base_shape: tuple[int, ...] | None = None,
|
|
41
|
+
) -> np.ndarray:
|
|
42
|
+
"""Composite one or more overlay masks onto RGBA pixels."""
|
|
43
|
+
if not overlay_sid_str:
|
|
44
|
+
return rgba
|
|
45
|
+
sids = [s.strip() for s in overlay_sid_str.split(",") if s.strip()]
|
|
46
|
+
colors_raw = (
|
|
47
|
+
[c.strip() for c in overlay_colors_str.split(",")] if overlay_colors_str else []
|
|
48
|
+
)
|
|
49
|
+
alphas_raw = (
|
|
50
|
+
[a.strip() for a in overlay_alphas_str.split(",")] if overlay_alphas_str else []
|
|
51
|
+
)
|
|
52
|
+
for i, sid in enumerate(sids):
|
|
53
|
+
color = _parse_hex_color(colors_raw[i]) if i < len(colors_raw) else None
|
|
54
|
+
alpha = overlay_alpha
|
|
55
|
+
if i < len(alphas_raw):
|
|
56
|
+
try:
|
|
57
|
+
alpha = float(alphas_raw[i])
|
|
58
|
+
except ValueError:
|
|
59
|
+
alpha = overlay_alpha
|
|
60
|
+
alpha = max(0.0, min(1.0, alpha))
|
|
61
|
+
ov_raw = _extract_overlay_mask(
|
|
62
|
+
sid,
|
|
63
|
+
dim_x,
|
|
64
|
+
dim_y,
|
|
65
|
+
idx_tuple,
|
|
66
|
+
expected_shape=shape_hw,
|
|
67
|
+
base_shape=base_shape,
|
|
68
|
+
)
|
|
69
|
+
rgba = _composite_overlay_mask(
|
|
70
|
+
rgba,
|
|
71
|
+
ov_raw,
|
|
72
|
+
alpha=alpha,
|
|
73
|
+
is_label=_overlay_is_label_map(sid, ov_raw),
|
|
74
|
+
override_color=color,
|
|
75
|
+
outline_only=overlay_outline,
|
|
76
|
+
)
|
|
77
|
+
return rgba
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _composite_mosaic_overlays(
|
|
81
|
+
rgba: np.ndarray,
|
|
82
|
+
overlay_sid_str: str | None,
|
|
83
|
+
overlay_colors_str: str | None,
|
|
84
|
+
overlay_alpha: float,
|
|
85
|
+
overlay_alphas_str: str | None,
|
|
86
|
+
overlay_outline: bool,
|
|
87
|
+
dim_x: int,
|
|
88
|
+
dim_y: int,
|
|
89
|
+
dim_z: int,
|
|
90
|
+
idx_tuple: tuple[int, ...],
|
|
91
|
+
base_shape: tuple[int, ...],
|
|
92
|
+
mosaic_cols: int | None = None,
|
|
93
|
+
) -> np.ndarray:
|
|
94
|
+
"""Composite each overlay as a mosaic using the base mosaic's frame indices.
|
|
95
|
+
|
|
96
|
+
Missing overlay axes are resolved per frame by ``_extract_overlay_mask``.
|
|
97
|
+
That lets a mask omit, for example, an echo axis without materialising a
|
|
98
|
+
repeated full-volume copy.
|
|
99
|
+
"""
|
|
100
|
+
if not overlay_sid_str:
|
|
101
|
+
return rgba
|
|
102
|
+
sids = [sid.strip() for sid in overlay_sid_str.split(",") if sid.strip()]
|
|
103
|
+
colors_raw = (
|
|
104
|
+
[color.strip() for color in overlay_colors_str.split(",")]
|
|
105
|
+
if overlay_colors_str
|
|
106
|
+
else []
|
|
107
|
+
)
|
|
108
|
+
alphas_raw = (
|
|
109
|
+
[alpha.strip() for alpha in overlay_alphas_str.split(",")]
|
|
110
|
+
if overlay_alphas_str
|
|
111
|
+
else []
|
|
112
|
+
)
|
|
113
|
+
tile_shape = (int(base_shape[dim_y]), int(base_shape[dim_x]))
|
|
114
|
+
n_frames = int(base_shape[dim_z])
|
|
115
|
+
|
|
116
|
+
for i, sid in enumerate(sids):
|
|
117
|
+
color = _parse_hex_color(colors_raw[i]) if i < len(colors_raw) else None
|
|
118
|
+
try:
|
|
119
|
+
alpha = float(alphas_raw[i]) if i < len(alphas_raw) else overlay_alpha
|
|
120
|
+
except ValueError:
|
|
121
|
+
alpha = overlay_alpha
|
|
122
|
+
alpha = max(0.0, min(1.0, alpha))
|
|
123
|
+
|
|
124
|
+
frames = []
|
|
125
|
+
for frame in range(n_frames):
|
|
126
|
+
frame_idx = list(idx_tuple)
|
|
127
|
+
frame_idx[dim_z] = frame
|
|
128
|
+
ov_raw = _extract_overlay_mask(
|
|
129
|
+
sid,
|
|
130
|
+
dim_x,
|
|
131
|
+
dim_y,
|
|
132
|
+
tuple(frame_idx),
|
|
133
|
+
expected_shape=tile_shape,
|
|
134
|
+
base_shape=base_shape,
|
|
135
|
+
)
|
|
136
|
+
frames.append(
|
|
137
|
+
ov_raw if ov_raw is not None else np.zeros(tile_shape, dtype=np.float32)
|
|
138
|
+
)
|
|
139
|
+
grid, _, _ = _build_mosaic_grid(frames, n_frames, cols=mosaic_cols)
|
|
140
|
+
# Gaps are transparent, not NaN label values or heatmap samples.
|
|
141
|
+
grid = np.nan_to_num(grid, nan=0.0)
|
|
142
|
+
rgba = _composite_overlay_mask(
|
|
143
|
+
rgba,
|
|
144
|
+
grid,
|
|
145
|
+
alpha=alpha,
|
|
146
|
+
is_label=_overlay_is_label_map(sid, grid),
|
|
147
|
+
override_color=color,
|
|
148
|
+
outline_only=overlay_outline,
|
|
149
|
+
)
|
|
150
|
+
return rgba
|
|
@@ -6,7 +6,7 @@ from fastapi import Depends, Response
|
|
|
6
6
|
from fastapi.responses import JSONResponse
|
|
7
7
|
|
|
8
8
|
from arrayview._diff import _compute_diff, _diff_histogram, _render_diff_rgba
|
|
9
|
-
from arrayview._overlays import _composite_overlays
|
|
9
|
+
from arrayview._overlays import _composite_mosaic_overlays, _composite_overlays
|
|
10
10
|
from arrayview._render import (
|
|
11
11
|
LUTS,
|
|
12
12
|
_build_mosaic_grid,
|
|
@@ -178,6 +178,11 @@ def register_rendering_routes(app, *, get_session_or_404) -> None:
|
|
|
178
178
|
vmin_override=vmin_override,
|
|
179
179
|
vmax_override=vmax_override,
|
|
180
180
|
)
|
|
181
|
+
rgba = _composite_mosaic_overlays(
|
|
182
|
+
rgba, overlay_sid, overlay_colors, overlay_alpha, overlay_alphas,
|
|
183
|
+
overlay_outline, dim_x, dim_y, dim_z, idx_tuple, session.shape,
|
|
184
|
+
mosaic_cols,
|
|
185
|
+
)
|
|
181
186
|
if vmin_override is not None and vmax_override is not None:
|
|
182
187
|
vmin, vmax = float(vmin_override), float(vmax_override)
|
|
183
188
|
else:
|
|
@@ -264,6 +269,12 @@ def register_rendering_routes(app, *, get_session_or_404) -> None:
|
|
|
264
269
|
)
|
|
265
270
|
if qmri_role:
|
|
266
271
|
vmin, vmax = _qmri_adjust_vmin_vmax(vmin, vmax, qmri_role)
|
|
272
|
+
if dim_z >= 0 and qmri_role:
|
|
273
|
+
rgba = _composite_mosaic_overlays(
|
|
274
|
+
rgba, overlay_sid, overlay_colors, overlay_alpha, overlay_alphas,
|
|
275
|
+
overlay_outline, dim_x, dim_y, dim_z, idx_tuple, session.shape,
|
|
276
|
+
mosaic_cols,
|
|
277
|
+
)
|
|
267
278
|
render_ms = (time.perf_counter() - render_t0) * 1000.0
|
|
268
279
|
encode_t0 = time.perf_counter()
|
|
269
280
|
img = _pil_image().fromarray(rgba[:, :, :3], mode="RGB")
|
|
@@ -8,7 +8,7 @@ from starlette.websockets import WebSocketDisconnect
|
|
|
8
8
|
import arrayview._session as _session_mod
|
|
9
9
|
from arrayview._analysis import _build_metadata
|
|
10
10
|
from arrayview._lifecycle import release_session
|
|
11
|
-
from arrayview._overlays import _composite_overlays
|
|
11
|
+
from arrayview._overlays import _composite_mosaic_overlays, _composite_overlays
|
|
12
12
|
from arrayview._render import (
|
|
13
13
|
LUTS,
|
|
14
14
|
_prepare_display,
|
|
@@ -232,6 +232,12 @@ def register_websocket_routes(app) -> None:
|
|
|
232
232
|
vmax_override=vmax_override,
|
|
233
233
|
),
|
|
234
234
|
)
|
|
235
|
+
rgba = _composite_mosaic_overlays(
|
|
236
|
+
rgba, msg.get("overlay_sid"), msg.get("overlay_colors"),
|
|
237
|
+
float(msg.get("overlay_alpha", 0.45)), msg.get("overlay_alphas"),
|
|
238
|
+
bool(msg.get("overlay_outline", False)), dim_x, dim_y, dim_z,
|
|
239
|
+
idx_tuple, session.shape, mosaic_cols,
|
|
240
|
+
)
|
|
235
241
|
h, w = rgba.shape[:2]
|
|
236
242
|
raw = extract_slice(session, dim_x, dim_y, list(idx_tuple))
|
|
237
243
|
_, vmin, vmax = _prepare_display(
|
|
@@ -344,6 +350,14 @@ def register_websocket_routes(app) -> None:
|
|
|
344
350
|
session.shape,
|
|
345
351
|
)
|
|
346
352
|
|
|
353
|
+
if dim_z >= 0 and qmri_role:
|
|
354
|
+
rgba = _composite_mosaic_overlays(
|
|
355
|
+
rgba, msg.get("overlay_sid"), msg.get("overlay_colors"),
|
|
356
|
+
float(msg.get("overlay_alpha", 0.45)), msg.get("overlay_alphas"),
|
|
357
|
+
bool(msg.get("overlay_outline", False)), dim_x, dim_y, dim_z,
|
|
358
|
+
idx_tuple, session.shape, mosaic_cols,
|
|
359
|
+
)
|
|
360
|
+
|
|
347
361
|
render_ms = (time.perf_counter() - render_t0) * 1000.0
|
|
348
362
|
post_t0 = time.perf_counter()
|
|
349
363
|
header = np.array([seq, w, h], dtype=np.uint32).tobytes()
|
|
@@ -4,6 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
6
|
import json
|
|
7
|
+
import platform
|
|
7
8
|
import subprocess
|
|
8
9
|
import sys
|
|
9
10
|
import threading
|
|
@@ -219,7 +220,7 @@ def _open_browser(
|
|
|
219
220
|
port_hint = int(url.split(":")[2].split("/")[0].split("?")[0])
|
|
220
221
|
except Exception:
|
|
221
222
|
port_hint = parsed_port
|
|
222
|
-
hostname =
|
|
223
|
+
hostname = platform.node() or "<this-host>"
|
|
223
224
|
print(
|
|
224
225
|
f"[ArrayView] Plain SSH session detected.\n"
|
|
225
226
|
f"\n"
|
|
@@ -4601,6 +4601,57 @@ class TestCropPersistence:
|
|
|
4601
4601
|
|
|
4602
4602
|
|
|
4603
4603
|
class TestMultipleOverlays:
|
|
4604
|
+
def test_http_mosaic_repeats_overlay_across_missing_dimension(self, client, tmp_path):
|
|
4605
|
+
base_path = tmp_path / "mosaic-base.npy"
|
|
4606
|
+
np.save(base_path, np.zeros((4, 3, 6, 6), dtype=np.float32))
|
|
4607
|
+
base_sid = client.post("/load", json={"filepath": str(base_path)}).json()["sid"]
|
|
4608
|
+
overlay_data = np.zeros((4, 6, 6), dtype=np.uint8)
|
|
4609
|
+
overlay_data[2, 2:4, 2:4] = 1
|
|
4610
|
+
overlay_path = tmp_path / "mosaic-overlay.npy"
|
|
4611
|
+
np.save(overlay_path, overlay_data)
|
|
4612
|
+
overlay_sid = client.post("/load", json={"filepath": str(overlay_path)}).json()["sid"]
|
|
4613
|
+
|
|
4614
|
+
response = client.get(
|
|
4615
|
+
f"/slice/{base_sid}",
|
|
4616
|
+
params={
|
|
4617
|
+
"dim_x": 3,
|
|
4618
|
+
"dim_y": 2,
|
|
4619
|
+
"dim_z": 1,
|
|
4620
|
+
"indices": "2,0,3,3",
|
|
4621
|
+
"overlay_sid": overlay_sid,
|
|
4622
|
+
"overlay_colors": "ff0000",
|
|
4623
|
+
"overlay_alpha": 1.0,
|
|
4624
|
+
},
|
|
4625
|
+
)
|
|
4626
|
+
image = np.asarray(Image.open(io.BytesIO(response.content)))
|
|
4627
|
+
for x0 in (0, 8, 16):
|
|
4628
|
+
tile = image[:, x0 : x0 + 6]
|
|
4629
|
+
assert np.max(tile[:, :, 0].astype(int) - tile[:, :, 1].astype(int)) > 20
|
|
4630
|
+
|
|
4631
|
+
def test_mosaic_overlay_broadcasts_over_missing_mosaic_dimension(self):
|
|
4632
|
+
from arrayview._overlays import _composite_mosaic_overlays
|
|
4633
|
+
from arrayview._render import mosaic_shape
|
|
4634
|
+
from arrayview._session import SESSIONS, Session
|
|
4635
|
+
|
|
4636
|
+
base = Session(np.zeros((4, 3, 6, 6), dtype=np.float32))
|
|
4637
|
+
overlay_data = np.zeros((4, 6, 6), dtype=np.uint8)
|
|
4638
|
+
overlay_data[2, 3, 4] = 1
|
|
4639
|
+
overlay = Session(overlay_data)
|
|
4640
|
+
SESSIONS[overlay.sid] = overlay
|
|
4641
|
+
try:
|
|
4642
|
+
rows, cols = mosaic_shape(3)
|
|
4643
|
+
rgba = np.zeros((rows * 6 + (rows - 1) * 2, cols * 6 + (cols - 1) * 2, 4), dtype=np.uint8)
|
|
4644
|
+
result = _composite_mosaic_overlays(
|
|
4645
|
+
rgba, overlay.sid, "ff0000", 1.0, None, False,
|
|
4646
|
+
dim_x=3, dim_y=2, dim_z=1, idx_tuple=(2, 0, 3, 3),
|
|
4647
|
+
base_shape=base.shape,
|
|
4648
|
+
)
|
|
4649
|
+
for frame in range(3):
|
|
4650
|
+
row, col = divmod(frame, cols)
|
|
4651
|
+
assert result[row * 8 + 3, col * 8 + 4, 0] == 255
|
|
4652
|
+
finally:
|
|
4653
|
+
SESSIONS.pop(overlay.sid, None)
|
|
4654
|
+
|
|
4604
4655
|
def test_overlay_broadcasts_over_missing_base_dimension(self):
|
|
4605
4656
|
from arrayview._render import _extract_overlay_mask
|
|
4606
4657
|
from arrayview._session import SESSIONS, Session
|
|
@@ -163,6 +163,7 @@ def test_vscode_tunnel_without_window_id_uses_focused_window_fallback(
|
|
|
163
163
|
signal_dir = home / ".arrayview"
|
|
164
164
|
signal_dir.mkdir(parents=True)
|
|
165
165
|
monkeypatch.setenv("HOME", str(home))
|
|
166
|
+
monkeypatch.setenv("USERPROFILE", str(home))
|
|
166
167
|
monkeypatch.setattr(signal, "_is_vscode_remote", lambda: True)
|
|
167
168
|
monkeypatch.setattr(signal, "_find_arrayview_window_id", lambda: None)
|
|
168
169
|
monkeypatch.setattr(signal, "_find_current_vscode_window_id", lambda: "100")
|
|
@@ -201,6 +202,7 @@ def test_vscode_tunnel_exact_window_id_is_not_redirected_to_newer_sibling(
|
|
|
201
202
|
signal_dir = home / ".arrayview"
|
|
202
203
|
signal_dir.mkdir(parents=True)
|
|
203
204
|
monkeypatch.setenv("HOME", str(home))
|
|
205
|
+
monkeypatch.setenv("USERPROFILE", str(home))
|
|
204
206
|
monkeypatch.setattr(signal, "_is_vscode_remote", lambda: True)
|
|
205
207
|
monkeypatch.setattr(signal, "_find_arrayview_window_id", lambda: "100")
|
|
206
208
|
|
|
@@ -231,6 +233,7 @@ def test_vscode_local_exact_window_id_is_not_redirected_to_newer_sibling(
|
|
|
231
233
|
signal_dir = home / ".arrayview"
|
|
232
234
|
signal_dir.mkdir(parents=True)
|
|
233
235
|
monkeypatch.setenv("HOME", str(home))
|
|
236
|
+
monkeypatch.setenv("USERPROFILE", str(home))
|
|
234
237
|
monkeypatch.setattr(signal, "_is_vscode_remote", lambda: False)
|
|
235
238
|
monkeypatch.setattr(signal, "_find_arrayview_window_id", lambda: "100")
|
|
236
239
|
|
|
@@ -261,6 +264,7 @@ def test_vscode_local_stale_window_id_with_multiple_windows_fails_closed(
|
|
|
261
264
|
signal_dir = home / ".arrayview"
|
|
262
265
|
signal_dir.mkdir(parents=True)
|
|
263
266
|
monkeypatch.setenv("HOME", str(home))
|
|
267
|
+
monkeypatch.setenv("USERPROFILE", str(home))
|
|
264
268
|
monkeypatch.setattr(signal, "_is_vscode_remote", lambda: False)
|
|
265
269
|
monkeypatch.setattr(signal, "_find_arrayview_window_id", lambda: "stale")
|
|
266
270
|
monkeypatch.setattr(signal, "_find_current_vscode_window_id", lambda: None)
|
|
@@ -290,6 +294,7 @@ def test_vscode_local_missing_window_match_uses_focused_window_fallback(
|
|
|
290
294
|
signal_dir = home / ".arrayview"
|
|
291
295
|
signal_dir.mkdir(parents=True)
|
|
292
296
|
monkeypatch.setenv("HOME", str(home))
|
|
297
|
+
monkeypatch.setenv("USERPROFILE", str(home))
|
|
293
298
|
monkeypatch.setattr(signal, "_is_vscode_remote", lambda: False)
|
|
294
299
|
monkeypatch.setattr(signal, "_find_arrayview_window_id", lambda: None)
|
|
295
300
|
monkeypatch.setattr(signal, "_find_current_vscode_window_id", lambda: None)
|
|
@@ -331,6 +336,7 @@ def test_vscode_local_missing_window_match_with_local_windows_fails_closed(
|
|
|
331
336
|
signal_dir = home / ".arrayview"
|
|
332
337
|
signal_dir.mkdir(parents=True)
|
|
333
338
|
monkeypatch.setenv("HOME", str(home))
|
|
339
|
+
monkeypatch.setenv("USERPROFILE", str(home))
|
|
334
340
|
monkeypatch.setattr(signal, "_is_vscode_remote", lambda: False)
|
|
335
341
|
monkeypatch.setattr(signal, "_find_arrayview_window_id", lambda: None)
|
|
336
342
|
monkeypatch.setattr(signal, "_find_current_vscode_window_id", lambda: None)
|
|
@@ -19,6 +19,7 @@ def _request(tmp_path, **overrides):
|
|
|
19
19
|
|
|
20
20
|
def test_open_request_includes_versioned_ack_metadata(monkeypatch, tmp_path):
|
|
21
21
|
monkeypatch.setenv("HOME", str(tmp_path))
|
|
22
|
+
monkeypatch.setenv("USERPROFILE", str(tmp_path))
|
|
22
23
|
monkeypatch.setattr(signal, "_find_arrayview_window_id", lambda: "window-1")
|
|
23
24
|
captured = []
|
|
24
25
|
monkeypatch.setattr(
|
|
@@ -51,6 +52,7 @@ def test_open_request_includes_versioned_ack_metadata(monkeypatch, tmp_path):
|
|
|
51
52
|
|
|
52
53
|
def test_open_request_reports_failed_legacy_write(monkeypatch, tmp_path):
|
|
53
54
|
monkeypatch.setenv("HOME", str(tmp_path))
|
|
55
|
+
monkeypatch.setenv("USERPROFILE", str(tmp_path))
|
|
54
56
|
monkeypatch.setattr(signal, "_find_arrayview_window_id", lambda: None)
|
|
55
57
|
monkeypatch.setattr(signal, "_write_vscode_signal", lambda *args, **kwargs: False)
|
|
56
58
|
|
|
@@ -62,6 +64,7 @@ def test_open_request_reports_failed_legacy_write(monkeypatch, tmp_path):
|
|
|
62
64
|
|
|
63
65
|
def test_open_request_correlates_ack_to_recovered_live_window(monkeypatch, tmp_path):
|
|
64
66
|
monkeypatch.setenv("HOME", str(tmp_path))
|
|
67
|
+
monkeypatch.setenv("USERPROFILE", str(tmp_path))
|
|
65
68
|
monkeypatch.setattr(signal, "_find_arrayview_window_id", lambda: "stale-window")
|
|
66
69
|
monkeypatch.setattr(signal, "_is_vscode_remote", lambda: False)
|
|
67
70
|
signal_dir = tmp_path / ".arrayview"
|
|
@@ -86,6 +89,7 @@ def test_open_request_correlates_ack_to_recovered_live_window(monkeypatch, tmp_p
|
|
|
86
89
|
|
|
87
90
|
def test_open_request_leaves_broadcast_window_to_claiming_extension(monkeypatch, tmp_path):
|
|
88
91
|
monkeypatch.setenv("HOME", str(tmp_path))
|
|
92
|
+
monkeypatch.setenv("USERPROFILE", str(tmp_path))
|
|
89
93
|
monkeypatch.setattr(signal, "_find_arrayview_window_id", lambda: "stale-window")
|
|
90
94
|
monkeypatch.setattr(signal, "_is_vscode_remote", lambda: True)
|
|
91
95
|
signal_dir = tmp_path / ".arrayview"
|
|
@@ -112,6 +116,7 @@ def test_open_request_leaves_broadcast_window_to_claiming_extension(monkeypatch,
|
|
|
112
116
|
|
|
113
117
|
def test_protocol_requests_get_distinct_queue_files(monkeypatch, tmp_path):
|
|
114
118
|
monkeypatch.setenv("HOME", str(tmp_path))
|
|
119
|
+
monkeypatch.setenv("USERPROFILE", str(tmp_path))
|
|
115
120
|
monkeypatch.setattr(signal, "_is_vscode_remote", lambda: True)
|
|
116
121
|
monkeypatch.setattr(signal, "_find_arrayview_window_id", lambda: "window-1")
|
|
117
122
|
signal_dir = tmp_path / ".arrayview"
|
|
@@ -144,6 +149,7 @@ def test_protocol_requests_get_distinct_queue_files(monkeypatch, tmp_path):
|
|
|
144
149
|
|
|
145
150
|
def test_protocol_uses_fixed_filename_for_running_legacy_extension(monkeypatch, tmp_path):
|
|
146
151
|
monkeypatch.setenv("HOME", str(tmp_path))
|
|
152
|
+
monkeypatch.setenv("USERPROFILE", str(tmp_path))
|
|
147
153
|
monkeypatch.setattr(signal, "_is_vscode_remote", lambda: True)
|
|
148
154
|
monkeypatch.setattr(signal, "_find_arrayview_window_id", lambda: "window-1")
|
|
149
155
|
signal_dir = tmp_path / ".arrayview"
|
|
@@ -240,6 +246,7 @@ def test_wait_rejects_malformed_or_unknown_ack(tmp_path):
|
|
|
240
246
|
|
|
241
247
|
def test_cleanup_removes_only_stale_ack_files(monkeypatch, tmp_path):
|
|
242
248
|
monkeypatch.setenv("HOME", str(tmp_path))
|
|
249
|
+
monkeypatch.setenv("USERPROFILE", str(tmp_path))
|
|
243
250
|
signal_dir = tmp_path / ".arrayview"
|
|
244
251
|
signal_dir.mkdir()
|
|
245
252
|
stale = signal_dir / "open-ack-v0100-stale.json"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const assert = require('assert');
|
|
2
|
+
const path = require('path');
|
|
2
3
|
const {
|
|
3
4
|
collectReleaseSidsFromUrl,
|
|
4
5
|
pingUrlFromViewerUrl,
|
|
@@ -54,18 +55,19 @@ assert.strictEqual(shouldDeferBroadcast(false, true, { broadcast: true }), false
|
|
|
54
55
|
assert.strictEqual(shouldDeferBroadcast(true, false, { broadcast: true }), false);
|
|
55
56
|
assert.strictEqual(shouldDeferBroadcast(false, false, { broadcast: false }), false);
|
|
56
57
|
|
|
57
|
-
const home = '
|
|
58
|
+
const home = path.join(path.parse(process.cwd()).root, 'home', 'tester');
|
|
59
|
+
const ackPath = path.join(home, '.arrayview', 'open-ack-v0100-req-1.json');
|
|
58
60
|
assert.strictEqual(
|
|
59
|
-
validatedAckPath(
|
|
60
|
-
|
|
61
|
+
validatedAckPath(ackPath, 'req-1', home),
|
|
62
|
+
path.resolve(ackPath)
|
|
61
63
|
);
|
|
62
|
-
assert.strictEqual(validatedAckPath('
|
|
64
|
+
assert.strictEqual(validatedAckPath(path.join(path.parse(process.cwd()).root, 'tmp', 'open-ack-v0100-req-1.json'), 'req-1', home), null);
|
|
63
65
|
assert.strictEqual(
|
|
64
|
-
validatedAckPath('
|
|
66
|
+
validatedAckPath(path.join(home, '.arrayview', 'open-ack-v0100-other.json'), 'req-1', home),
|
|
65
67
|
null
|
|
66
68
|
);
|
|
67
69
|
assert.strictEqual(
|
|
68
|
-
validatedAckPath('
|
|
70
|
+
validatedAckPath(path.join(home, '.arrayview', 'sub', 'open-ack-v0100-req-1.json'), 'req-1', home),
|
|
69
71
|
null
|
|
70
72
|
);
|
|
71
73
|
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
"""Shared overlay compositing helpers."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import numpy as np
|
|
6
|
-
|
|
7
|
-
from arrayview._render import (
|
|
8
|
-
_composite_overlay_mask,
|
|
9
|
-
_extract_overlay_mask,
|
|
10
|
-
_overlay_is_label_map,
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def _parse_hex_color(hex_str: str) -> np.ndarray | None:
|
|
15
|
-
"""Parse a 6-char hex RGB color."""
|
|
16
|
-
h = hex_str.strip().lstrip("#")
|
|
17
|
-
if len(h) != 6:
|
|
18
|
-
return None
|
|
19
|
-
try:
|
|
20
|
-
return np.array(
|
|
21
|
-
[int(h[0:2], 16), int(h[2:4], 16), int(h[4:6], 16)],
|
|
22
|
-
dtype=np.uint8,
|
|
23
|
-
)
|
|
24
|
-
except ValueError:
|
|
25
|
-
return None
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def _composite_overlays(
|
|
29
|
-
rgba: np.ndarray,
|
|
30
|
-
overlay_sid_str: str | None,
|
|
31
|
-
overlay_colors_str: str | None,
|
|
32
|
-
overlay_alpha: float,
|
|
33
|
-
overlay_alphas_str: str | None,
|
|
34
|
-
overlay_outline: bool,
|
|
35
|
-
dim_x: int,
|
|
36
|
-
dim_y: int,
|
|
37
|
-
idx_tuple: tuple[int, ...],
|
|
38
|
-
shape_hw: tuple[int, int],
|
|
39
|
-
base_shape: tuple[int, ...] | None = None,
|
|
40
|
-
) -> np.ndarray:
|
|
41
|
-
"""Composite one or more overlay masks onto RGBA pixels."""
|
|
42
|
-
if not overlay_sid_str:
|
|
43
|
-
return rgba
|
|
44
|
-
sids = [s.strip() for s in overlay_sid_str.split(",") if s.strip()]
|
|
45
|
-
colors_raw = (
|
|
46
|
-
[c.strip() for c in overlay_colors_str.split(",")] if overlay_colors_str else []
|
|
47
|
-
)
|
|
48
|
-
alphas_raw = (
|
|
49
|
-
[a.strip() for a in overlay_alphas_str.split(",")] if overlay_alphas_str else []
|
|
50
|
-
)
|
|
51
|
-
for i, sid in enumerate(sids):
|
|
52
|
-
color = _parse_hex_color(colors_raw[i]) if i < len(colors_raw) else None
|
|
53
|
-
alpha = overlay_alpha
|
|
54
|
-
if i < len(alphas_raw):
|
|
55
|
-
try:
|
|
56
|
-
alpha = float(alphas_raw[i])
|
|
57
|
-
except ValueError:
|
|
58
|
-
alpha = overlay_alpha
|
|
59
|
-
alpha = max(0.0, min(1.0, alpha))
|
|
60
|
-
ov_raw = _extract_overlay_mask(
|
|
61
|
-
sid,
|
|
62
|
-
dim_x,
|
|
63
|
-
dim_y,
|
|
64
|
-
idx_tuple,
|
|
65
|
-
expected_shape=shape_hw,
|
|
66
|
-
base_shape=base_shape,
|
|
67
|
-
)
|
|
68
|
-
rgba = _composite_overlay_mask(
|
|
69
|
-
rgba,
|
|
70
|
-
ov_raw,
|
|
71
|
-
alpha=alpha,
|
|
72
|
-
is_label=_overlay_is_label_map(sid, ov_raw),
|
|
73
|
-
override_color=color,
|
|
74
|
-
outline_only=overlay_outline,
|
|
75
|
-
)
|
|
76
|
-
return rgba
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/playwright-cli/references/element-attributes.md
RENAMED
|
File without changes
|
{arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/playwright-cli/references/playwright-tests.md
RENAMED
|
File without changes
|
{arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/playwright-cli/references/request-mocking.md
RENAMED
|
File without changes
|
{arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/playwright-cli/references/running-code.md
RENAMED
|
File without changes
|
{arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/playwright-cli/references/session-management.md
RENAMED
|
File without changes
|
{arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/playwright-cli/references/storage-state.md
RENAMED
|
File without changes
|
{arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/playwright-cli/references/test-generation.md
RENAMED
|
File without changes
|
|
File without changes
|
{arrayview-0.31.1 → arrayview-0.31.2}/.agents/skills/playwright-cli/references/video-recording.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|