arrayview 0.26.2__tar.gz → 0.27.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.
Files changed (218) hide show
  1. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/AGENTS.md +1 -1
  2. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/ROUTER.md +1 -1
  3. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/SETUP.md +1 -1
  4. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/SYNC.md +1 -1
  5. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/context/conventions.md +1 -1
  6. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/context/decisions.md +1 -1
  7. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/context/lifecycle.md +1 -1
  8. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/context/project-state.md +4 -3
  9. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/context/render-pipeline.md +1 -1
  10. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/context/setup.md +2 -2
  11. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/context/stack.md +1 -1
  12. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/patterns/INDEX.md +2 -0
  13. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/patterns/README.md +1 -1
  14. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/patterns/add-server-endpoint.md +1 -1
  15. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/patterns/animation-verify.md +1 -1
  16. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/patterns/debug-render.md +1 -1
  17. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/patterns/debug-vscode-extension-python.md +1 -1
  18. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/patterns/extend-compare-mode.md +1 -1
  19. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/patterns/extract-server-route-module.md +1 -1
  20. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/patterns/frontend-change.md +1 -1
  21. {arrayview-0.26.2 → arrayview-0.27.0}/PKG-INFO +7 -7
  22. arrayview-0.27.0/README.md +21 -0
  23. arrayview-0.27.0/docs/launch-routing-refactor.md +167 -0
  24. {arrayview-0.26.2 → arrayview-0.27.0}/docs/measurement.md +7 -3
  25. arrayview-0.27.0/plans/roi-analysis-requirements.md +126 -0
  26. {arrayview-0.26.2 → arrayview-0.27.0}/pyproject.toml +1 -1
  27. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_analysis.py +19 -4
  28. arrayview-0.27.0/src/arrayview/_launch_plan.py +285 -0
  29. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_launcher.py +133 -55
  30. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_platform.py +22 -9
  31. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_routes_analysis.py +442 -3
  32. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_server.py +1 -0
  33. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_stdio_server.py +2 -1
  34. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_viewer.html +3065 -576
  35. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_vscode_browser.py +16 -0
  36. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_vscode_extension.py +1 -1
  37. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_vscode_signal.py +31 -57
  38. arrayview-0.27.0/src/arrayview/arrayview-opener.vsix +0 -0
  39. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_api.py +623 -5
  40. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_browser.py +1190 -38
  41. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_cli.py +62 -0
  42. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_interactions.py +5 -5
  43. arrayview-0.27.0/tests/test_launch_plan.py +239 -0
  44. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_lifecycle_contract.py +48 -0
  45. {arrayview-0.26.2 → arrayview-0.27.0}/uv.lock +1 -1
  46. {arrayview-0.26.2 → arrayview-0.27.0}/vscode-extension/extension.js +121 -71
  47. {arrayview-0.26.2 → arrayview-0.27.0}/vscode-extension/package.json +1 -1
  48. arrayview-0.26.2/README.md +0 -21
  49. arrayview-0.26.2/src/arrayview/arrayview-opener.vsix +0 -0
  50. {arrayview-0.26.2 → arrayview-0.27.0}/.agents/skills/frontend-designer/SKILL.md +0 -0
  51. {arrayview-0.26.2 → arrayview-0.27.0}/.agents/skills/invocation-consistency/SKILL.md +0 -0
  52. {arrayview-0.26.2 → arrayview-0.27.0}/.agents/skills/modes-consistency/SKILL.md +0 -0
  53. {arrayview-0.26.2 → arrayview-0.27.0}/.agents/skills/playwright-cli/SKILL.md +0 -0
  54. {arrayview-0.26.2 → arrayview-0.27.0}/.agents/skills/playwright-cli/references/element-attributes.md +0 -0
  55. {arrayview-0.26.2 → arrayview-0.27.0}/.agents/skills/playwright-cli/references/playwright-tests.md +0 -0
  56. {arrayview-0.26.2 → arrayview-0.27.0}/.agents/skills/playwright-cli/references/request-mocking.md +0 -0
  57. {arrayview-0.26.2 → arrayview-0.27.0}/.agents/skills/playwright-cli/references/running-code.md +0 -0
  58. {arrayview-0.26.2 → arrayview-0.27.0}/.agents/skills/playwright-cli/references/session-management.md +0 -0
  59. {arrayview-0.26.2 → arrayview-0.27.0}/.agents/skills/playwright-cli/references/storage-state.md +0 -0
  60. {arrayview-0.26.2 → arrayview-0.27.0}/.agents/skills/playwright-cli/references/test-generation.md +0 -0
  61. {arrayview-0.26.2 → arrayview-0.27.0}/.agents/skills/playwright-cli/references/tracing.md +0 -0
  62. {arrayview-0.26.2 → arrayview-0.27.0}/.agents/skills/playwright-cli/references/video-recording.md +0 -0
  63. {arrayview-0.26.2 → arrayview-0.27.0}/.agents/skills/todo-workflow/SKILL.md +0 -0
  64. {arrayview-0.26.2 → arrayview-0.27.0}/.agents/skills/ui-consistency-audit/SKILL.md +0 -0
  65. {arrayview-0.26.2 → arrayview-0.27.0}/.agents/skills/viewer-ui-checklist/SKILL.md +0 -0
  66. {arrayview-0.26.2 → arrayview-0.27.0}/.agents/skills/visual-bug-fixing/SKILL.md +0 -0
  67. {arrayview-0.26.2 → arrayview-0.27.0}/.github/copilot-instructions.md +0 -0
  68. {arrayview-0.26.2 → arrayview-0.27.0}/.github/workflows/docs.yml +0 -0
  69. {arrayview-0.26.2 → arrayview-0.27.0}/.github/workflows/python-publish.yml +0 -0
  70. {arrayview-0.26.2 → arrayview-0.27.0}/.gitignore +0 -0
  71. {arrayview-0.26.2 → arrayview-0.27.0}/.ignore +0 -0
  72. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/context/architecture.md +0 -0
  73. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/context/frontend.md +0 -0
  74. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/patterns/add-file-format.md +0 -0
  75. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/setup.sh +0 -0
  76. {arrayview-0.26.2 → arrayview-0.27.0}/.mex/sync.sh +0 -0
  77. {arrayview-0.26.2 → arrayview-0.27.0}/.opencode/opencode.json +0 -0
  78. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T18-46-49-737Z.yml +0 -0
  79. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T18-48-21-979Z.yml +0 -0
  80. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T18-51-35-665Z.yml +0 -0
  81. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T19-07-01-393Z.yml +0 -0
  82. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T19-14-37-969Z.yml +0 -0
  83. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T19-21-30-940Z.yml +0 -0
  84. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T19-23-08-126Z.yml +0 -0
  85. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T19-29-33-155Z.yml +0 -0
  86. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T19-31-25-336Z.yml +0 -0
  87. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T19-31-53-789Z.yml +0 -0
  88. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T19-39-12-257Z.yml +0 -0
  89. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T19-39-16-449Z.yml +0 -0
  90. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T20-15-25-513Z.yml +0 -0
  91. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T20-25-13-179Z.yml +0 -0
  92. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T20-39-01-435Z.yml +0 -0
  93. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T21-01-27-659Z.yml +0 -0
  94. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T21-01-41-283Z.yml +0 -0
  95. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T21-03-00-625Z.yml +0 -0
  96. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T21-04-12-887Z.yml +0 -0
  97. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T21-33-39-044Z.yml +0 -0
  98. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T21-38-01-530Z.yml +0 -0
  99. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T21-45-20-383Z.yml +0 -0
  100. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T21-55-11-545Z.yml +0 -0
  101. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T21-56-03-307Z.yml +0 -0
  102. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T21-56-35-733Z.yml +0 -0
  103. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T21-57-12-181Z.yml +0 -0
  104. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T21-57-37-748Z.yml +0 -0
  105. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T21-58-13-679Z.yml +0 -0
  106. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-06T22-37-23-895Z.yml +0 -0
  107. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T00-39-18-637Z.yml +0 -0
  108. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T01-41-46-243Z.yml +0 -0
  109. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T04-31-48-472Z.yml +0 -0
  110. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T12-14-15-632Z.yml +0 -0
  111. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T12-14-47-582Z.yml +0 -0
  112. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T12-16-23-471Z.yml +0 -0
  113. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T12-17-10-247Z.yml +0 -0
  114. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T12-18-24-707Z.yml +0 -0
  115. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T12-20-06-164Z.yml +0 -0
  116. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T12-20-28-342Z.yml +0 -0
  117. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T12-21-54-962Z.yml +0 -0
  118. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T12-22-34-666Z.yml +0 -0
  119. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T12-23-11-336Z.yml +0 -0
  120. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T12-23-36-260Z.yml +0 -0
  121. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T12-24-09-267Z.yml +0 -0
  122. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T12-24-35-434Z.yml +0 -0
  123. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T12-25-57-010Z.yml +0 -0
  124. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T12-34-48-823Z.yml +0 -0
  125. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T12-46-46-468Z.yml +0 -0
  126. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T12-48-17-930Z.yml +0 -0
  127. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T12-49-26-400Z.yml +0 -0
  128. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T12-50-31-563Z.yml +0 -0
  129. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/page-2026-05-07T12-56-45-568Z.yml +0 -0
  130. {arrayview-0.26.2 → arrayview-0.27.0}/.playwright-cli/theme-dark.yml +0 -0
  131. {arrayview-0.26.2 → arrayview-0.27.0}/.python-version +0 -0
  132. {arrayview-0.26.2 → arrayview-0.27.0}/.vscode/settings.json +0 -0
  133. {arrayview-0.26.2 → arrayview-0.27.0}/AGENTS.md +0 -0
  134. {arrayview-0.26.2 → arrayview-0.27.0}/CONTRIBUTING.md +0 -0
  135. {arrayview-0.26.2 → arrayview-0.27.0}/DESIGN.md +0 -0
  136. {arrayview-0.26.2 → arrayview-0.27.0}/LICENSE +0 -0
  137. {arrayview-0.26.2 → arrayview-0.27.0}/docs/comparing.md +0 -0
  138. {arrayview-0.26.2 → arrayview-0.27.0}/docs/configuration.md +0 -0
  139. {arrayview-0.26.2 → arrayview-0.27.0}/docs/display.md +0 -0
  140. {arrayview-0.26.2 → arrayview-0.27.0}/docs/index.md +0 -0
  141. {arrayview-0.26.2 → arrayview-0.27.0}/docs/lifecycle.md +0 -0
  142. {arrayview-0.26.2 → arrayview-0.27.0}/docs/loading.md +0 -0
  143. {arrayview-0.26.2 → arrayview-0.27.0}/docs/logo.png +0 -0
  144. {arrayview-0.26.2 → arrayview-0.27.0}/docs/remote.md +0 -0
  145. {arrayview-0.26.2 → arrayview-0.27.0}/docs/stylesheets/extra.css +0 -0
  146. {arrayview-0.26.2 → arrayview-0.27.0}/docs/viewing.md +0 -0
  147. {arrayview-0.26.2 → arrayview-0.27.0}/matlab/arrayview.m +0 -0
  148. {arrayview-0.26.2 → arrayview-0.27.0}/mkdocs.yml +0 -0
  149. {arrayview-0.26.2 → arrayview-0.27.0}/plans/2026-04-14-immersive-animation.md +0 -0
  150. {arrayview-0.26.2 → arrayview-0.27.0}/plans/2026-05-07-unified-colormap-picker.md +0 -0
  151. {arrayview-0.26.2 → arrayview-0.27.0}/plans/arrayview_tool_menu_fix_prompt.md +0 -0
  152. {arrayview-0.26.2 → arrayview-0.27.0}/plans/arrayview_tool_menu_implementation_plan.md +0 -0
  153. {arrayview-0.26.2 → arrayview-0.27.0}/plans/egg-placement-mockup.html +0 -0
  154. {arrayview-0.26.2 → arrayview-0.27.0}/plans/refactoring_plan.md +0 -0
  155. {arrayview-0.26.2 → arrayview-0.27.0}/plans/webview/LOG.md +0 -0
  156. {arrayview-0.26.2 → arrayview-0.27.0}/scripts/demo.py +0 -0
  157. {arrayview-0.26.2 → arrayview-0.27.0}/scripts/release.sh +0 -0
  158. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/ARCHITECTURE.md +0 -0
  159. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/__init__.py +0 -0
  160. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/__main__.py +0 -0
  161. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_app.py +0 -0
  162. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_codex_open.py +0 -0
  163. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_config.py +0 -0
  164. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_diff.py +0 -0
  165. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_icon.png +0 -0
  166. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_imaging.py +0 -0
  167. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_io.py +0 -0
  168. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_lifecycle.py +0 -0
  169. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_overlays.py +0 -0
  170. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_render.py +0 -0
  171. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_routes_export.py +0 -0
  172. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_routes_loading.py +0 -0
  173. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_routes_persistence.py +0 -0
  174. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_routes_preload.py +0 -0
  175. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_routes_query.py +0 -0
  176. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_routes_rendering.py +0 -0
  177. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_routes_segmentation.py +0 -0
  178. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_routes_state.py +0 -0
  179. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_routes_vectorfield.py +0 -0
  180. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_routes_websocket.py +0 -0
  181. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_segmentation.py +0 -0
  182. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_session.py +0 -0
  183. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_shell.html +0 -0
  184. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_synthetic_mri.py +0 -0
  185. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_torch.py +0 -0
  186. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_vectorfield.py +0 -0
  187. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_vscode.py +0 -0
  188. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/_vscode_shm.py +0 -0
  189. {arrayview-0.26.2 → arrayview-0.27.0}/src/arrayview/gsap.min.js +0 -0
  190. {arrayview-0.26.2 → arrayview-0.27.0}/tests/capture_v_animation.py +0 -0
  191. {arrayview-0.26.2 → arrayview-0.27.0}/tests/conftest.py +0 -0
  192. {arrayview-0.26.2 → arrayview-0.27.0}/tests/lifecycle_matrix.py +0 -0
  193. {arrayview-0.26.2 → arrayview-0.27.0}/tests/make_vectorfield_test_arrays.py +0 -0
  194. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_backend_shared.py +0 -0
  195. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_colorbar_hover_highlight.py +0 -0
  196. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_command_reachability.py +0 -0
  197. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_config.py +0 -0
  198. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_cross_mode_parametrized.py +0 -0
  199. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_io.py +0 -0
  200. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_large_arrays.py +0 -0
  201. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_loading_server.py +0 -0
  202. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_mode_consistency.py +0 -0
  203. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_mode_entry_batching.py +0 -0
  204. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_mode_matrix.py +0 -0
  205. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_mode_roundtrip.py +0 -0
  206. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_nifti_meta.py +0 -0
  207. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_rgb_pixel_art.py +0 -0
  208. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_stdio_server.py +0 -0
  209. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_torch.py +0 -0
  210. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_view_component_integration.py +0 -0
  211. {arrayview-0.26.2 → arrayview-0.27.0}/tests/test_view_component_unit.py +0 -0
  212. {arrayview-0.26.2 → arrayview-0.27.0}/tests/ui_audit.py +0 -0
  213. {arrayview-0.26.2 → arrayview-0.27.0}/tests/v_anim_frames/.gitkeep +0 -0
  214. {arrayview-0.26.2 → arrayview-0.27.0}/tests/visual_smoke.py +0 -0
  215. {arrayview-0.26.2 → arrayview-0.27.0}/vscode-extension/AGENTS.md +0 -0
  216. {arrayview-0.26.2 → arrayview-0.27.0}/vscode-extension/LICENSE +0 -0
  217. {arrayview-0.26.2 → arrayview-0.27.0}/vscode-extension/lifecycle_helpers.js +0 -0
  218. {arrayview-0.26.2 → arrayview-0.27.0}/vscode-extension/test_lifecycle_helpers.js +0 -0
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agents
3
3
  description: Lightweight pointer to ROUTER.md for task routing.
4
- last_updated: 2026-05-16
4
+ last_updated: 2026-06-19
5
5
  ---
6
6
 
7
7
  # arrayview
@@ -24,7 +24,7 @@ edges:
24
24
  condition: when starting a task — check the pattern index for a matching pattern file
25
25
  - target: ../DESIGN.md
26
26
  condition: when the task touches design philosophy — new features, UI changes, mode additions, or interaction model decisions
27
- last_updated: 2026-06-05
27
+ last_updated: 2026-06-19
28
28
  ---
29
29
 
30
30
  # arrayview — Router
@@ -1,6 +1,6 @@
1
1
  # Setup — Populate This Scaffold
2
2
 
3
- Last reviewed: 2026-05-16
3
+ Last reviewed: 2026-06-19
4
4
 
5
5
  This file contains the prompts to populate the scaffold. It is NOT the dev environment setup — for that, see `context/setup.md` after population.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Sync — Realign This Scaffold
2
2
 
3
- Last reviewed: 2026-05-16
3
+ Last reviewed: 2026-06-19
4
4
 
5
5
  ## Recommended: Use sync.sh
6
6
 
@@ -18,7 +18,7 @@ edges:
18
18
  condition: when applying frontend conventions (section separators, reconcilers, command registry)
19
19
  - target: context/render-pipeline.md
20
20
  condition: when applying render pipeline conventions (pipeline order, cache patterns, LUT usage)
21
- last_updated: 2026-05-16
21
+ last_updated: 2026-06-19
22
22
  ---
23
23
 
24
24
  # Conventions
@@ -14,7 +14,7 @@ edges:
14
14
  condition: when a decision relates to technology choice
15
15
  - target: context/frontend.md
16
16
  condition: when a decision relates to the frontend architecture or viewer modes
17
- last_updated: 2026-05-16
17
+ last_updated: 2026-06-19
18
18
  ---
19
19
 
20
20
  # Decisions
@@ -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-06-05
19
+ last_updated: 2026-06-19
20
20
  ---
21
21
 
22
22
  # Lifecycle
@@ -25,8 +25,9 @@ last_updated: 2026-06-05
25
25
  - 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
26
26
  - Cold-start loading spinner in VS Code and native shell
27
27
  - Tool menu (`/` menu) supports multi-select where allowed: spacebar toggles tools, Enter applies selection. Mutual exclusion enforced (ROI ↔ Segmentation, and overlay/vectorfield ↔ everything else). Cursor indicator shows focused tile via yellow background + left accent bar
28
- - Dynamic island renders sections for all active plugins simultaneously (qMRI pills + ROI shapes/stats separated by divider), replacing the old single-plugin priority chain
29
- - ROI mode works alongside qMRI: drawing on any pane mirrors the ROI to all panes in real-time via per-pane overlay canvases; stats fetched per parameter map and shown as sub-rows in the island
28
+ - Dynamic island renders sections for active plugins such as qMRI and segmentation, replacing the old single-plugin priority chain
29
+ - ROI mode is a lightweight measurement tool: `Shift+R` shows/hides session ROIs, defaults to true circles, uses slim colorbar controls for shape/stats/hide/clear, and manages stats/rename/delete/export from the ROI manager modal
30
+ - ROI mode works alongside qMRI: drawing on any pane mirrors the ROI to all panes in real-time via per-pane overlay canvases; stats are fetched per visible parameter map and shown in the ROI manager
30
31
  - qMRI map toggle (`_islandToggleQmriMap`) fade animation now covers dimbar and array-name in addition to panes and colorbars
31
32
  - Segmentation menu shares the ROI layout (yellow accent, magnifier action icon, common `#export-overlay` modal). Pre-activation shows a pulsing "nnInteractive · connecting" row that morphs into the normal shape toolbar once `/seg/activate` resolves
32
33
  - Overlays are a plugin tile (`OV`): per-overlay row with colour swatch, editable label, eye toggle, × delete; shared opacity slider; `+ add overlay` opens a filesystem picker rooted at the launched file's directory
@@ -44,7 +45,7 @@ last_updated: 2026-06-05
44
45
  - Crossfade animation added to rotate/transpose transitions
45
46
  - `--version` flag and version string in help overlay
46
47
  - In-viewer array picker for multi-array `.mat` and `.npz` files
47
- - ROI stats tooltips for qMRI canvases (per-parameter-map sub-rows in the island)
48
+ - ROI manager modal for qMRI canvases (per-parameter-map stats rows, CSV export, label-mask export)
48
49
  - Invocation lifecycle contract defined and hardened: local VS Code CLI launches use transient daemon shutdown, remote/tunnel launches remain persistent only where transport requires it, URL webview backend checks run in the extension host against `/ping`, URL panel disposal releases all sessions encoded in the viewer URL, quick viewer connect/disconnect races detected by monotonic connection counter, ambiguous multi-window tunnel routing fails closed, stale viewer SID retry state cleared on WebSocket disconnect, bundled opener extension rebuilt as v0.14.12
49
50
  - Hover info wrong values fixed
50
51
  - Native launcher startup restored
@@ -20,7 +20,7 @@ edges:
20
20
  condition: when writing new render functions or extending the pipeline
21
21
  - target: patterns/debug-render.md
22
22
  condition: when a render produces wrong output or the wrong cache is hit
23
- last_updated: 2026-05-16
23
+ last_updated: 2026-06-19
24
24
  ---
25
25
 
26
26
  # Render Pipeline
@@ -13,7 +13,7 @@ edges:
13
13
  condition: when specific technology versions or library details are needed
14
14
  - target: context/architecture.md
15
15
  condition: when understanding how components connect during setup
16
- last_updated: 2026-05-16
16
+ last_updated: 2026-06-19
17
17
  ---
18
18
 
19
19
  # Setup
@@ -62,7 +62,7 @@ No `.env` file is needed. All env vars are optional overrides; the server runs w
62
62
 
63
63
  **Port already in use:** The server binds to a random free port by default. If you see a port conflict, check for orphan `uvicorn` processes: `lsof -i :<port>`. Kill with `kill -9 <PID>`. The server is supposed to shut down automatically when all viewer windows close.
64
64
 
65
- **VS Code extension not loading:** Signal-file IPC can fail if the extension version is mismatched. Check `_VSCODE_EXT_VERSION` in `_vscode.py` matches the installed extension.
65
+ **VS Code extension not loading:** Signal-file IPC can fail if the extension version is mismatched. Check `_VSCODE_EXT_VERSION` in `_vscode_extension.py` matches the installed extension.
66
66
 
67
67
  **Playwright tests fail on CI:** Ensure `uv run playwright install chromium` has been run. Browser tests require a display; on headless servers they need `DISPLAY=:0` or Xvfb.
68
68
 
@@ -14,7 +14,7 @@ edges:
14
14
  condition: when understanding how to use a technology in this codebase
15
15
  - target: context/architecture.md
16
16
  condition: when understanding how a library fits into the overall system
17
- last_updated: 2026-04-29
17
+ last_updated: 2026-06-19
18
18
  ---
19
19
 
20
20
  # Stack
@@ -1,5 +1,7 @@
1
1
  # Pattern Index
2
2
 
3
+ Last reviewed: 2026-06-19
4
+
3
5
  Lookup table for all pattern files in this directory. Check here before starting any task — if a pattern exists, follow it.
4
6
 
5
7
  <!-- This file is populated during setup (Pass 2) and updated whenever patterns are added.
@@ -1,6 +1,6 @@
1
1
  # Patterns
2
2
 
3
- Last reviewed: 2026-05-16
3
+ Last reviewed: 2026-06-19
4
4
 
5
5
  This folder contains task-specific guidance — the things you would tell your agent if you were sitting next to it. Not generic instructions. Project-specific accumulated wisdom.
6
6
 
@@ -16,7 +16,7 @@ edges:
16
16
  condition: when the endpoint triggers a render (slice, mosaic, projection)
17
17
  - target: context/conventions.md
18
18
  condition: for lazy import rules and Verify Checklist
19
- last_updated: 2026-05-16
19
+ last_updated: 2026-06-19
20
20
  ---
21
21
 
22
22
  # Add Server Endpoint
@@ -16,7 +16,7 @@ triggers:
16
16
  edges:
17
17
  - target: patterns/frontend-change.md
18
18
  condition: always — animation changes are always frontend changes
19
- last_updated: 2026-05-16
19
+ last_updated: 2026-06-19
20
20
  ---
21
21
 
22
22
  # Animation Verify
@@ -22,7 +22,7 @@ edges:
22
22
  condition: only after Step 1 points to `_viewer.html` rather than the Python pipeline
23
23
  - target: context/conventions.md
24
24
  condition: for the Verify Checklist after fixing
25
- last_updated: 2026-05-16
25
+ last_updated: 2026-06-19
26
26
  ---
27
27
 
28
28
  # Debug Render
@@ -12,7 +12,7 @@ triggers:
12
12
  edges:
13
13
  - target: context/conventions.md
14
14
  condition: when making code changes after confirming the failure mode
15
- last_updated: 2026-05-16
15
+ last_updated: 2026-06-19
16
16
  ---
17
17
 
18
18
  # Debug VS Code Extension Python
@@ -13,7 +13,7 @@ edges:
13
13
  condition: when the work is primarily a local `_viewer.html` edit
14
14
  - target: context/render-pipeline.md
15
15
  condition: when compare changes require backend render or diff parameter changes
16
- last_updated: 2026-05-13
16
+ last_updated: 2026-06-19
17
17
  ---
18
18
 
19
19
  # Extend Compare Mode
@@ -11,7 +11,7 @@ edges:
11
11
  condition: when deciding whether `_server.py` should keep or delegate a route cluster
12
12
  - target: context/project-state.md
13
13
  condition: when the extraction changes the active architecture workstream
14
- last_updated: 2026-05-16
14
+ last_updated: 2026-06-19
15
15
  ---
16
16
 
17
17
  # Extract Server Route Module
@@ -16,7 +16,7 @@ edges:
16
16
  condition: for shared conventions and the Verify Checklist
17
17
  - target: patterns/debug-render.md
18
18
  condition: when the change produces wrong visual output
19
- last_updated: 2026-05-16
19
+ last_updated: 2026-06-19
20
20
  ---
21
21
 
22
22
  # Frontend Change
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arrayview
3
- Version: 0.26.2
3
+ Version: 0.27.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
@@ -38,20 +38,20 @@ Description-Content-Type: text/markdown
38
38
 
39
39
  _This is my array viewer. There are many like it, but this one is mine._
40
40
 
41
- And I think you might like it too. Fast, responsive scrolling
42
- through slices of multi-dimensional arrays. Feature rich with a modern, minimal UI that only shows what needs to be shown.
41
+ Arrayview lets you scroll through multi-dimensional arrays.
43
42
 
44
- It works wherever you work. The shell, scripts (Python/Julia/Matlab), or Jupyter notebooks. Local or remote. Easy to install.
43
+ Open it from the shell, from Python, Julia, or Matlab, or inside a Jupyter notebook. Use it locally or over SSH.
45
44
 
46
- VS Code users can even open the viewer just by clicking an array in the explorer tab.
45
+ If you work in VS Code, you can open arrays directly from the explorer; with Remote SSH, it works the same way.
47
46
 
48
- And if you're using the VS Code remote extension to connect to a remote, it just works—no additional setup required.
47
+ It is meant to feel simple but there's more to it than meets the eye.
49
48
 
50
49
  Curious? Give it a try with
51
50
  ```bash
52
51
  uvx arrayview your_array.npy
53
52
  ```
54
- Explore, there's more to it than meets the eye.
53
+
55
54
 
56
55
  Check the [docs](https://oscarvanderheide.github.io/arrayview/) to learn more.
57
56
 
57
+ **Warning**: Arrayview is still under active development. Things may break or change without warning.
@@ -0,0 +1,21 @@
1
+ # <img src="docs/logo.png" height="36"> arrayview
2
+
3
+ _This is my array viewer. There are many like it, but this one is mine._
4
+
5
+ Arrayview lets you scroll through multi-dimensional arrays.
6
+
7
+ Open it from the shell, from Python, Julia, or Matlab, or inside a Jupyter notebook. Use it locally or over SSH.
8
+
9
+ If you work in VS Code, you can open arrays directly from the explorer; with Remote SSH, it works the same way.
10
+
11
+ It is meant to feel simple but there's more to it than meets the eye.
12
+
13
+ Curious? Give it a try with
14
+ ```bash
15
+ uvx arrayview your_array.npy
16
+ ```
17
+
18
+
19
+ Check the [docs](https://oscarvanderheide.github.io/arrayview/) to learn more.
20
+
21
+ **Warning**: Arrayview is still under active development. Things may break or change without warning.
@@ -0,0 +1,167 @@
1
+ # Launch Routing Refactor
2
+
3
+ ArrayView currently opens displays through several partially overlapping paths:
4
+ CLI, `view()`, Jupyter, Julia, VS Code local, VS Code tunnel, SSH, native
5
+ pywebview, browser fallback, and stdio/direct webview mode. The same policy is
6
+ encoded in multiple places, so fixes in one path can leave another path broken.
7
+
8
+ This refactor makes launch routing explicit, shared, and inspectable.
9
+
10
+ ## Problem
11
+
12
+ The brittle behavior comes from policy being split across:
13
+
14
+ - environment detection in `_platform.py`
15
+ - CLI planning in `_launcher.py`
16
+ - Python `view()` planning in `_launcher.py`
17
+ - VS Code signal/direct-mode fallback in `_vscode_browser.py` and `_vscode_signal.py`
18
+ - separate HTTP and stdio session registration paths
19
+
20
+ Symptoms seen recently:
21
+
22
+ - CLI diagnose says native pywebview should open, but runtime falls back to a browser.
23
+ - Linux native detection allows GTK systems while native launch forced Qt.
24
+ - `view()` and CLI had different native readiness checks.
25
+ - Existing-server remote behavior can accidentally switch from registered URL mode to direct stdio mode.
26
+
27
+ ## Target Model
28
+
29
+ Create a single launch plan used by both CLI and `view()`.
30
+
31
+ The plan should be data-only:
32
+
33
+ ```python
34
+ Invocation = "cli" | "python" | "jupyter" | "julia" | "stdio" | "codex"
35
+ Environment = "terminal" | "vscode_local" | "vscode_remote" | "ssh" | "jupyter" | "julia"
36
+ Transport = "http" | "stdio_file" | "stdio_shm" | "none"
37
+ ServerOwner = "existing" | "spawned_daemon" | "in_process" | "persistent" | "external"
38
+ Display = "native" | "browser" | "vscode" | "inline" | "none"
39
+ Registration = "http_load" | "daemon_startup" | "in_process_session" | "stdio_register" | "relay"
40
+ ```
41
+
42
+ Executors may perform work, but should not invent policy. Browser fallback,
43
+ VS Code direct mode, native readiness, and remote behavior must be selected by
44
+ the plan.
45
+
46
+ ## Phase 1: Snapshot And Diagnose
47
+
48
+ Add a launch environment snapshot:
49
+
50
+ ```python
51
+ snapshot_launch_environment(port, invocation, requested_window)
52
+ ```
53
+
54
+ It should capture:
55
+
56
+ - platform
57
+ - relevant environment variables
58
+ - config default
59
+ - native backend: `qt`, `gtk`, `""`, or `None`
60
+ - port busy / ArrayView server alive / server PID / hostname
61
+ - VS Code local vs remote/tunnel
62
+ - SSH state
63
+ - Jupyter and Julia state
64
+
65
+ `arrayview --diagnose` must print the same snapshot and plan used by real launch.
66
+
67
+ ## Phase 2: Shared Planner
68
+
69
+ Add:
70
+
71
+ ```python
72
+ plan_launch(invocation, request, env) -> LaunchPlan
73
+ ```
74
+
75
+ The planner decides:
76
+
77
+ - transport: HTTP, stdio file, stdio SHM, or none
78
+ - display: native, browser, vscode, inline, none
79
+ - server owner: existing, spawned daemon, in-process, persistent, external
80
+ - registration: HTTP load, daemon startup, in-process session, stdio register, relay
81
+ - fallback policy: whether fallback is allowed and where it goes
82
+
83
+ CLI and `view()` should both call this planner.
84
+
85
+ ## Phase 3: Native Readiness
86
+
87
+ Use one native readiness primitive everywhere:
88
+
89
+ ```python
90
+ open_native_shell(...)
91
+ wait_native_ready(shell_socket=True, viewer_socket=True, process_alive=True)
92
+ ```
93
+
94
+ Rules:
95
+
96
+ - process crash is native launch failure
97
+ - shell WebSocket means the native window is usable
98
+ - viewer WebSocket means the content loaded
99
+ - missing viewer WebSocket alone is not native failure
100
+ - browser fallback happens only after native process/shell failure
101
+
102
+ ## Phase 4: Remote Existing-Server Fix
103
+
104
+ Separate these cases explicitly:
105
+
106
+ - `Display=vscode`, `Transport=http`: open the registered HTTP URL in VS Code
107
+ - `Display=vscode`, `Transport=stdio_file`: open direct stdio file session
108
+
109
+ Do not let `_open_browser(..., filepath=...)` implicitly switch an existing
110
+ registered URL into direct stdio mode.
111
+
112
+ ## Phase 5: VS Code Direct Mode
113
+
114
+ Consolidate SHM/direct mode:
115
+
116
+ - one `_open_direct_via_shm()` implementation
117
+ - one SHM wait loop
118
+ - Julia remote, Python remote, and tunnel notebook paths call the same helper
119
+
120
+ Remove or clearly deprecate duplicate direct-mode helpers.
121
+
122
+ ## Phase 6: Registration Semantics
123
+
124
+ Align HTTP `/load` and stdio registration:
125
+
126
+ - shared file/key selection behavior
127
+ - shared RAM guard behavior where possible
128
+ - shared RGB/vectorfield/overlay/compare semantics where possible
129
+ - documented differences where transports genuinely diverge
130
+
131
+ ## Contract Tests
132
+
133
+ Prefer contract tests over broad visual smoke for launch routing:
134
+
135
+ - macOS terminal CLI native
136
+ - Linux Qt native
137
+ - Linux GTK native
138
+ - Linux no display browser fallback
139
+ - plain SSH guidance
140
+ - VS Code local tab
141
+ - VS Code remote direct stdio
142
+ - VS Code remote existing HTTP URL
143
+ - Jupyter inline
144
+ - VS Code remote notebook direct
145
+ - Julia subprocess/direct
146
+
147
+ Execution contracts:
148
+
149
+ - existing server native shell does not fall back only because viewer socket is late
150
+ - spawned daemon native shell does not fall back only because viewer socket is late
151
+ - `view()` native shell does not fall back only because viewer socket is late
152
+ - remote existing server opens registered URL, not direct stdio
153
+ - GTK-only Linux passes `gui="gtk"` to pywebview
154
+
155
+ ## Migration Order
156
+
157
+ 1. Add launch data model and environment snapshot without behavior changes.
158
+ 2. Make `--diagnose` use the snapshot and shared planner.
159
+ 3. Move CLI planning into `plan_launch()`.
160
+ 4. Move `view()` planning into `plan_launch()`.
161
+ 5. Unify native readiness for CLI and `view()`.
162
+ 6. Fix remote existing-server URL/direct ambiguity.
163
+ 7. Consolidate SHM direct mode.
164
+ 8. Align HTTP and stdio registration semantics.
165
+
166
+ Each step should have focused invocation tests and should avoid unrelated UI or
167
+ rendering changes.
@@ -2,15 +2,19 @@
2
2
 
3
3
  ## ROI
4
4
 
5
- `Shift+R` opens ROI options. Draw on the canvas to measure a region — live stats (mean, std, min, max) appear in the floating panel.
5
+ `Shift+R` shows or hides ROI mode. Hiding ROI mode keeps the session's ROIs.
6
6
 
7
- Shapes: rectangle, ellipse, freehand, flood fill. Switch via the shape icons in the panel.
7
+ Draw on the canvas to measure a region. The default shape is a circle.
8
+
9
+ Shapes: circle, rectangle, freehand, flood fill. Switch via the colorbar controls.
8
10
 
9
11
  For flood fill, `[` / `]` adjusts tolerance.
10
12
 
11
13
  Click an existing ROI to select it. `Delete` / `Backspace` removes it.
12
14
 
13
- `N` exports the ROI mask as `.npy`.
15
+ `Stats` opens the ROI manager: rename/delete ROIs, adjust extent, export CSV, or export a label mask.
16
+
17
+ `N` exports the active ROI or segmentation mask as `.npy`.
14
18
 
15
19
  ## Ruler
16
20
 
@@ -0,0 +1,126 @@
1
+ # ROI Analysis Requirements
2
+
3
+ ## Purpose
4
+
5
+ ROI analysis should be a lightweight MRI/qMRI measurement tool. It should make
6
+ quick measurements easy, support repeated phantom-well measurements, and export
7
+ the resulting statistics and label masks.
8
+
9
+ ROI analysis is not a replacement for segmentation. Full white matter / gray
10
+ matter segmentation, voxel-label editing, automatic well detection, and mask
11
+ roundtripping belong outside ROI v1.
12
+
13
+ The current uncommitted ROI upgrade work is superseded by this document. Useful
14
+ backend or mask-export ideas may be reused, but the UI and interaction model
15
+ should restart from these requirements.
16
+
17
+ ## Primary Use Cases
18
+
19
+ - Draw a quick circular or freehand ROI in in-vivo MRI data to inspect mean,
20
+ standard deviation, minimum, and maximum values.
21
+ - Draw multiple true circular ROIs inside cylindrical gel phantoms in transverse
22
+ slices and compare their measurements.
23
+ - In qMRI mode, draw one ROI and measure the same region across visible
24
+ parameter maps.
25
+ - Export ROI statistics as CSV.
26
+ - Export a single integer `.npy` label mask matching the source array shape.
27
+
28
+ ## Interaction Model
29
+
30
+ - `Shift+R` toggles ROI mode visibility and interaction.
31
+ - When ROI mode turns off, ROI shapes, buttons, and hover affordances disappear.
32
+ - Turning ROI mode back on restores the session's existing ROI shapes.
33
+ - ROI geometry persists only for the current viewer session.
34
+ - The default ROI shape is a true circle.
35
+ - Additional ROI shapes are rectangle/square, freehand, and flood fill.
36
+ - Click an existing ROI to select it.
37
+ - `Delete` or `Backspace` deletes the selected ROI.
38
+ - No automatic or suggest-only circle detection in ROI v1.
39
+
40
+ ## UI Model
41
+
42
+ - Everyday ROI controls live on a colorbar flip surface, not in the right tool
43
+ drawer.
44
+ - The colorbar flip should expose only the common drawing controls: shape
45
+ picker, stats popup button, and minimal clear/hide actions if needed.
46
+ - Statistics open in a popup/modal.
47
+ - The stats popup is the ROI manager for v1:
48
+ - one row per ROI by default
49
+ - qMRI rows expand or reveal per-map measurements
50
+ - rename ROI
51
+ - delete ROI
52
+ - export CSV
53
+ - export label mask `.npy`
54
+ - advanced dimensional extent controls
55
+ - Do not put rename/delete controls directly on the canvas in v1.
56
+ - Keep the canvas visually quiet; ROI outlines and labels are the only persistent
57
+ ROI marks while ROI mode is active.
58
+
59
+ ## Statistics and Dimensional Scope
60
+
61
+ - Normal mode default: a new ROI applies only to the current displayed slice.
62
+ - qMRI default: a new ROI applies to the visible qMRI parameter maps.
63
+ - Advanced dimensional extent controls live in the stats popup per ROI.
64
+ - Advanced controls must use plain-language labels, not debug-like labels such
65
+ as `d2:135` or `d3:all`.
66
+ - Stats should report at least count, mean, standard deviation, minimum, and
67
+ maximum.
68
+ - CSV export should include ROI name, shape, dimensional extent, and qMRI map
69
+ labels where applicable.
70
+
71
+ ## Masks and Segmentation Boundary
72
+
73
+ - ROI mask export writes one `.npy` integer label mask matching the source array
74
+ shape.
75
+ - Label `0` is background.
76
+ - ROI labels are `1..N` in list order.
77
+ - ROI mask loading and roundtrip editing are out of scope for ROI v1.
78
+ - Segmentation remains the tool for voxel-label editing, external segmentation
79
+ workflows, brush/lasso editing, and future mask roundtripping.
80
+
81
+ ## Visibility and Color
82
+
83
+ - ROI outlines must remain visible across colormaps, themes, and local image
84
+ brightness.
85
+ - Keep per-ROI identity colors, but do not rely on color alone for visibility.
86
+ - Use an adaptive high-contrast halo or dual-outline rendering for ROI borders.
87
+ - ROI labels should use contrast-aware text/halo rendering.
88
+
89
+ ## Implementation Direction
90
+
91
+ - Rebuild ROI around a small session-local model:
92
+ `id`, `name`, `shape`, `geometry`, `scope`, `visible`, `selected`.
93
+ - Use true shape masks for stats and export. Do not fall back to bounding boxes
94
+ for circle, freehand, or flood fill.
95
+ - Route ROI visibility through existing UI reconcilers and colorbar flip
96
+ patterns.
97
+ - Update the command registry and `GUIDE_TABS` when finalizing shortcuts and
98
+ help text.
99
+ - Update `docs/measurement.md` only after implementation matches this spec.
100
+
101
+ ## Test Plan
102
+
103
+ - Spec review first: confirm this document captures the intended ROI direction
104
+ before rebuilding the implementation.
105
+ - Backend tests:
106
+ - true circle mask stats
107
+ - freehand and floodfill mask stats
108
+ - qMRI per-map stats
109
+ - `.npy` label mask shape and label values
110
+ - Browser tests:
111
+ - `Shift+R` hide/show preserves session ROIs
112
+ - default drawing shape is circle
113
+ - stats popup supports rename, delete, CSV export, and mask export
114
+ - qMRI mode shows per-map stats
115
+ - ROI outlines remain readable across themes/colormaps
116
+ - Regression tests:
117
+ - simple ROI drawing does not require the right drawer
118
+ - no circle suggestion UI or API
119
+ - no cryptic dimensional labels
120
+
121
+ ## Assumptions
122
+
123
+ - ROI and segmentation remain separate tools.
124
+ - ROI v1 prioritizes fast measurement and export over full mask management.
125
+ - Session-only ROI geometry is acceptable.
126
+ - Exported CSV and `.npy` masks are the persistence boundary for ROI v1.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "arrayview"
7
- version = "0.26.2"
7
+ version = "0.27.0"
8
8
  description = "Fast multi-dimensional array viewer"
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  requires-python = ">=3.12"