arrayview 0.24.0__tar.gz → 0.25.1__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 (212) hide show
  1. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/ROUTER.md +4 -1
  2. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/context/architecture.md +3 -1
  3. arrayview-0.25.1/.mex/context/lifecycle.md +92 -0
  4. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/context/project-state.md +1 -0
  5. {arrayview-0.24.0 → arrayview-0.25.1}/PKG-INFO +1 -1
  6. arrayview-0.25.1/docs/lifecycle.md +6 -0
  7. {arrayview-0.24.0 → arrayview-0.25.1}/pyproject.toml +1 -1
  8. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/__init__.py +1 -1
  9. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_analysis.py +12 -7
  10. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_io.py +49 -3
  11. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_launcher.py +201 -31
  12. arrayview-0.25.1/src/arrayview/_lifecycle.py +39 -0
  13. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_routes_loading.py +44 -26
  14. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_routes_websocket.py +13 -8
  15. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_server.py +1 -0
  16. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_session.py +3 -0
  17. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_viewer.html +35 -15
  18. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_vscode_extension.py +1 -1
  19. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_vscode_signal.py +67 -74
  20. arrayview-0.25.1/src/arrayview/arrayview-opener.vsix +0 -0
  21. arrayview-0.25.1/tests/lifecycle_matrix.py +391 -0
  22. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_api.py +162 -20
  23. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_browser.py +31 -0
  24. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_cli.py +67 -0
  25. arrayview-0.25.1/tests/test_lifecycle_contract.py +477 -0
  26. {arrayview-0.24.0 → arrayview-0.25.1}/uv.lock +1 -1
  27. {arrayview-0.24.0 → arrayview-0.25.1}/vscode-extension/extension.js +153 -11
  28. arrayview-0.25.1/vscode-extension/lifecycle_helpers.js +49 -0
  29. {arrayview-0.24.0 → arrayview-0.25.1}/vscode-extension/package.json +2 -1
  30. arrayview-0.25.1/vscode-extension/test_lifecycle_helpers.js +41 -0
  31. arrayview-0.24.0/src/arrayview/arrayview-opener.vsix +0 -0
  32. {arrayview-0.24.0 → arrayview-0.25.1}/.agents/skills/frontend-designer/SKILL.md +0 -0
  33. {arrayview-0.24.0 → arrayview-0.25.1}/.agents/skills/invocation-consistency/SKILL.md +0 -0
  34. {arrayview-0.24.0 → arrayview-0.25.1}/.agents/skills/modes-consistency/SKILL.md +0 -0
  35. {arrayview-0.24.0 → arrayview-0.25.1}/.agents/skills/playwright-cli/SKILL.md +0 -0
  36. {arrayview-0.24.0 → arrayview-0.25.1}/.agents/skills/playwright-cli/references/element-attributes.md +0 -0
  37. {arrayview-0.24.0 → arrayview-0.25.1}/.agents/skills/playwright-cli/references/playwright-tests.md +0 -0
  38. {arrayview-0.24.0 → arrayview-0.25.1}/.agents/skills/playwright-cli/references/request-mocking.md +0 -0
  39. {arrayview-0.24.0 → arrayview-0.25.1}/.agents/skills/playwright-cli/references/running-code.md +0 -0
  40. {arrayview-0.24.0 → arrayview-0.25.1}/.agents/skills/playwright-cli/references/session-management.md +0 -0
  41. {arrayview-0.24.0 → arrayview-0.25.1}/.agents/skills/playwright-cli/references/storage-state.md +0 -0
  42. {arrayview-0.24.0 → arrayview-0.25.1}/.agents/skills/playwright-cli/references/test-generation.md +0 -0
  43. {arrayview-0.24.0 → arrayview-0.25.1}/.agents/skills/playwright-cli/references/tracing.md +0 -0
  44. {arrayview-0.24.0 → arrayview-0.25.1}/.agents/skills/playwright-cli/references/video-recording.md +0 -0
  45. {arrayview-0.24.0 → arrayview-0.25.1}/.agents/skills/todo-workflow/SKILL.md +0 -0
  46. {arrayview-0.24.0 → arrayview-0.25.1}/.agents/skills/ui-consistency-audit/SKILL.md +0 -0
  47. {arrayview-0.24.0 → arrayview-0.25.1}/.agents/skills/viewer-ui-checklist/SKILL.md +0 -0
  48. {arrayview-0.24.0 → arrayview-0.25.1}/.agents/skills/visual-bug-fixing/SKILL.md +0 -0
  49. {arrayview-0.24.0 → arrayview-0.25.1}/.github/copilot-instructions.md +0 -0
  50. {arrayview-0.24.0 → arrayview-0.25.1}/.github/workflows/docs.yml +0 -0
  51. {arrayview-0.24.0 → arrayview-0.25.1}/.github/workflows/python-publish.yml +0 -0
  52. {arrayview-0.24.0 → arrayview-0.25.1}/.gitignore +0 -0
  53. {arrayview-0.24.0 → arrayview-0.25.1}/.ignore +0 -0
  54. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/AGENTS.md +0 -0
  55. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/SETUP.md +0 -0
  56. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/SYNC.md +0 -0
  57. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/context/conventions.md +0 -0
  58. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/context/decisions.md +0 -0
  59. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/context/frontend.md +0 -0
  60. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/context/render-pipeline.md +0 -0
  61. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/context/setup.md +0 -0
  62. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/context/stack.md +0 -0
  63. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/patterns/INDEX.md +0 -0
  64. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/patterns/README.md +0 -0
  65. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/patterns/add-file-format.md +0 -0
  66. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/patterns/add-server-endpoint.md +0 -0
  67. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/patterns/animation-verify.md +0 -0
  68. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/patterns/debug-render.md +0 -0
  69. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/patterns/debug-vscode-extension-python.md +0 -0
  70. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/patterns/extend-compare-mode.md +0 -0
  71. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/patterns/extract-server-route-module.md +0 -0
  72. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/patterns/frontend-change.md +0 -0
  73. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/setup.sh +0 -0
  74. {arrayview-0.24.0 → arrayview-0.25.1}/.mex/sync.sh +0 -0
  75. {arrayview-0.24.0 → arrayview-0.25.1}/.opencode/opencode.json +0 -0
  76. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T18-46-49-737Z.yml +0 -0
  77. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T18-48-21-979Z.yml +0 -0
  78. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T18-51-35-665Z.yml +0 -0
  79. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T19-07-01-393Z.yml +0 -0
  80. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T19-14-37-969Z.yml +0 -0
  81. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T19-21-30-940Z.yml +0 -0
  82. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T19-23-08-126Z.yml +0 -0
  83. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T19-29-33-155Z.yml +0 -0
  84. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T19-31-25-336Z.yml +0 -0
  85. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T19-31-53-789Z.yml +0 -0
  86. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T19-39-12-257Z.yml +0 -0
  87. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T19-39-16-449Z.yml +0 -0
  88. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T20-15-25-513Z.yml +0 -0
  89. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T20-25-13-179Z.yml +0 -0
  90. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T20-39-01-435Z.yml +0 -0
  91. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T21-01-27-659Z.yml +0 -0
  92. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T21-01-41-283Z.yml +0 -0
  93. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T21-03-00-625Z.yml +0 -0
  94. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T21-04-12-887Z.yml +0 -0
  95. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T21-33-39-044Z.yml +0 -0
  96. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T21-38-01-530Z.yml +0 -0
  97. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T21-45-20-383Z.yml +0 -0
  98. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T21-55-11-545Z.yml +0 -0
  99. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T21-56-03-307Z.yml +0 -0
  100. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T21-56-35-733Z.yml +0 -0
  101. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T21-57-12-181Z.yml +0 -0
  102. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T21-57-37-748Z.yml +0 -0
  103. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T21-58-13-679Z.yml +0 -0
  104. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-06T22-37-23-895Z.yml +0 -0
  105. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T00-39-18-637Z.yml +0 -0
  106. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T01-41-46-243Z.yml +0 -0
  107. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T04-31-48-472Z.yml +0 -0
  108. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T12-14-15-632Z.yml +0 -0
  109. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T12-14-47-582Z.yml +0 -0
  110. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T12-16-23-471Z.yml +0 -0
  111. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T12-17-10-247Z.yml +0 -0
  112. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T12-18-24-707Z.yml +0 -0
  113. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T12-20-06-164Z.yml +0 -0
  114. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T12-20-28-342Z.yml +0 -0
  115. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T12-21-54-962Z.yml +0 -0
  116. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T12-22-34-666Z.yml +0 -0
  117. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T12-23-11-336Z.yml +0 -0
  118. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T12-23-36-260Z.yml +0 -0
  119. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T12-24-09-267Z.yml +0 -0
  120. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T12-24-35-434Z.yml +0 -0
  121. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T12-25-57-010Z.yml +0 -0
  122. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T12-34-48-823Z.yml +0 -0
  123. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T12-46-46-468Z.yml +0 -0
  124. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T12-48-17-930Z.yml +0 -0
  125. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T12-49-26-400Z.yml +0 -0
  126. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T12-50-31-563Z.yml +0 -0
  127. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/page-2026-05-07T12-56-45-568Z.yml +0 -0
  128. {arrayview-0.24.0 → arrayview-0.25.1}/.playwright-cli/theme-dark.yml +0 -0
  129. {arrayview-0.24.0 → arrayview-0.25.1}/.python-version +0 -0
  130. {arrayview-0.24.0 → arrayview-0.25.1}/.vscode/settings.json +0 -0
  131. {arrayview-0.24.0 → arrayview-0.25.1}/AGENTS.md +0 -0
  132. {arrayview-0.24.0 → arrayview-0.25.1}/CONTRIBUTING.md +0 -0
  133. {arrayview-0.24.0 → arrayview-0.25.1}/DESIGN.md +0 -0
  134. {arrayview-0.24.0 → arrayview-0.25.1}/LICENSE +0 -0
  135. {arrayview-0.24.0 → arrayview-0.25.1}/README.md +0 -0
  136. {arrayview-0.24.0 → arrayview-0.25.1}/docs/comparing.md +0 -0
  137. {arrayview-0.24.0 → arrayview-0.25.1}/docs/configuration.md +0 -0
  138. {arrayview-0.24.0 → arrayview-0.25.1}/docs/display.md +0 -0
  139. {arrayview-0.24.0 → arrayview-0.25.1}/docs/index.md +0 -0
  140. {arrayview-0.24.0 → arrayview-0.25.1}/docs/loading.md +0 -0
  141. {arrayview-0.24.0 → arrayview-0.25.1}/docs/logo.png +0 -0
  142. {arrayview-0.24.0 → arrayview-0.25.1}/docs/measurement.md +0 -0
  143. {arrayview-0.24.0 → arrayview-0.25.1}/docs/remote.md +0 -0
  144. {arrayview-0.24.0 → arrayview-0.25.1}/docs/stylesheets/extra.css +0 -0
  145. {arrayview-0.24.0 → arrayview-0.25.1}/docs/viewing.md +0 -0
  146. {arrayview-0.24.0 → arrayview-0.25.1}/matlab/arrayview.m +0 -0
  147. {arrayview-0.24.0 → arrayview-0.25.1}/mkdocs.yml +0 -0
  148. {arrayview-0.24.0 → arrayview-0.25.1}/plans/2026-04-14-immersive-animation.md +0 -0
  149. {arrayview-0.24.0 → arrayview-0.25.1}/plans/2026-05-07-unified-colormap-picker.md +0 -0
  150. {arrayview-0.24.0 → arrayview-0.25.1}/plans/arrayview_tool_menu_fix_prompt.md +0 -0
  151. {arrayview-0.24.0 → arrayview-0.25.1}/plans/arrayview_tool_menu_implementation_plan.md +0 -0
  152. {arrayview-0.24.0 → arrayview-0.25.1}/plans/egg-placement-mockup.html +0 -0
  153. {arrayview-0.24.0 → arrayview-0.25.1}/plans/refactoring_plan.md +0 -0
  154. {arrayview-0.24.0 → arrayview-0.25.1}/plans/webview/LOG.md +0 -0
  155. {arrayview-0.24.0 → arrayview-0.25.1}/scripts/demo.py +0 -0
  156. {arrayview-0.24.0 → arrayview-0.25.1}/scripts/release.sh +0 -0
  157. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/ARCHITECTURE.md +0 -0
  158. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/__main__.py +0 -0
  159. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_app.py +0 -0
  160. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_codex_open.py +0 -0
  161. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_config.py +0 -0
  162. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_diff.py +0 -0
  163. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_icon.png +0 -0
  164. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_imaging.py +0 -0
  165. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_overlays.py +0 -0
  166. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_platform.py +0 -0
  167. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_render.py +0 -0
  168. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_routes_analysis.py +0 -0
  169. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_routes_export.py +0 -0
  170. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_routes_persistence.py +0 -0
  171. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_routes_preload.py +0 -0
  172. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_routes_query.py +0 -0
  173. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_routes_rendering.py +0 -0
  174. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_routes_segmentation.py +0 -0
  175. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_routes_state.py +0 -0
  176. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_routes_vectorfield.py +0 -0
  177. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_segmentation.py +0 -0
  178. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_shell.html +0 -0
  179. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_stdio_server.py +0 -0
  180. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_synthetic_mri.py +0 -0
  181. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_torch.py +0 -0
  182. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_vectorfield.py +0 -0
  183. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_vscode.py +0 -0
  184. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_vscode_browser.py +0 -0
  185. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/_vscode_shm.py +0 -0
  186. {arrayview-0.24.0 → arrayview-0.25.1}/src/arrayview/gsap.min.js +0 -0
  187. {arrayview-0.24.0 → arrayview-0.25.1}/tests/capture_v_animation.py +0 -0
  188. {arrayview-0.24.0 → arrayview-0.25.1}/tests/conftest.py +0 -0
  189. {arrayview-0.24.0 → arrayview-0.25.1}/tests/make_vectorfield_test_arrays.py +0 -0
  190. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_backend_shared.py +0 -0
  191. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_colorbar_hover_highlight.py +0 -0
  192. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_command_reachability.py +0 -0
  193. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_config.py +0 -0
  194. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_cross_mode_parametrized.py +0 -0
  195. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_interactions.py +0 -0
  196. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_large_arrays.py +0 -0
  197. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_loading_server.py +0 -0
  198. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_mode_consistency.py +0 -0
  199. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_mode_entry_batching.py +0 -0
  200. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_mode_matrix.py +0 -0
  201. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_mode_roundtrip.py +0 -0
  202. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_nifti_meta.py +0 -0
  203. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_rgb_pixel_art.py +0 -0
  204. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_stdio_server.py +0 -0
  205. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_torch.py +0 -0
  206. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_view_component_integration.py +0 -0
  207. {arrayview-0.24.0 → arrayview-0.25.1}/tests/test_view_component_unit.py +0 -0
  208. {arrayview-0.24.0 → arrayview-0.25.1}/tests/ui_audit.py +0 -0
  209. {arrayview-0.24.0 → arrayview-0.25.1}/tests/v_anim_frames/.gitkeep +0 -0
  210. {arrayview-0.24.0 → arrayview-0.25.1}/tests/visual_smoke.py +0 -0
  211. {arrayview-0.24.0 → arrayview-0.25.1}/vscode-extension/AGENTS.md +0 -0
  212. {arrayview-0.24.0 → arrayview-0.25.1}/vscode-extension/LICENSE +0 -0
@@ -6,6 +6,8 @@ edges:
6
6
  condition: when the task depends on what is currently shipped, in progress, or recently changed
7
7
  - target: context/architecture.md
8
8
  condition: when working on system design, integrations, or understanding how components connect
9
+ - target: context/lifecycle.md
10
+ condition: when working on server startup, shutdown, display ownership, VS Code tabs, orphan processes, or session release
9
11
  - target: context/stack.md
10
12
  condition: when working with specific technologies, libraries, or making tech decisions
11
13
  - target: context/conventions.md
@@ -22,7 +24,7 @@ edges:
22
24
  condition: when starting a task — check the pattern index for a matching pattern file
23
25
  - target: ../DESIGN.md
24
26
  condition: when the task touches design philosophy — new features, UI changes, mode additions, or interaction model decisions
25
- last_updated: 2026-05-16
27
+ last_updated: 2026-06-05
26
28
  ---
27
29
 
28
30
  # arrayview — Router
@@ -81,6 +83,7 @@ Load `context/project-state.md` only when you need active-workstream or recent-s
81
83
  |-----------|------|
82
84
  | Checking current shipped / in-progress status | `context/project-state.md` |
83
85
  | Understanding system architecture | `context/architecture.md` |
86
+ | Startup/shutdown/display ownership lifecycle | `context/lifecycle.md` |
84
87
  | Working with a specific technology | `context/stack.md` |
85
88
  | Writing or reviewing code | `context/conventions.md` |
86
89
  | Making a design decision | `context/decisions.md` |
@@ -14,11 +14,13 @@ edges:
14
14
  condition: when specific technology details are needed
15
15
  - target: context/decisions.md
16
16
  condition: when understanding why the architecture is structured this way
17
+ - target: context/lifecycle.md
18
+ condition: when ownership, startup, teardown, or display routing lifecycle matters
17
19
  - target: context/frontend.md
18
20
  condition: when the task involves _viewer.html, modes, reconcilers, or the View Component System
19
21
  - target: context/render-pipeline.md
20
22
  condition: when the task involves slice extraction, colormaps, caching, or the render thread
21
- last_updated: 2026-05-26
23
+ last_updated: 2026-06-05
22
24
  ---
23
25
 
24
26
  # Architecture
@@ -0,0 +1,92 @@
1
+ ---
2
+ name: lifecycle
3
+ description: Ownership contract for ArrayView backends, viewer sessions, VS Code tabs, and shutdown/release behavior.
4
+ triggers:
5
+ - "lifecycle"
6
+ - "server ownership"
7
+ - "startup"
8
+ - "shutdown"
9
+ - "orphan process"
10
+ - "VS Code tab"
11
+ - "backend unavailable"
12
+ - "Jupyter iframe"
13
+ - "SSH"
14
+ edges:
15
+ - target: context/architecture.md
16
+ condition: when component boundaries or display routing need broader context
17
+ - target: context/stack.md
18
+ condition: when VS Code, FastAPI, WebSocket, or packaging details are needed
19
+ last_updated: 2026-06-05
20
+ ---
21
+
22
+ # Lifecycle
23
+
24
+ This contract describes who owns the backend, when it starts, and what closes it.
25
+
26
+ ## Ownership Matrix
27
+
28
+ | Invocation | Display owner | Backend model | Shutdown/release |
29
+ |---|---|---|---|
30
+ | Local VS Code CLI `arrayview file.npy` | VS Code URL webview panel | Shared transient daemon | Panel close releases URL sessions; last viewer WebSocket close stops daemon |
31
+ | VS Code file click/custom editor | VS Code extension | Extension-owned stdio subprocess | Panel close kills subprocess |
32
+ | Plain Python script `view(arr)` | Browser/native/VS Code display | Non-daemon background server thread | Survives caller until viewer connects then closes |
33
+ | Jupyter `view(arr)` | Notebook kernel inline iframe | Kernel-owned daemon server thread | Iframe disappearance must not hard-kill backend |
34
+ | Julia/PythonCall | Browser/VS Code route from subprocess | Detached subprocess | Never in-process; avoid GIL deadlock |
35
+ | Remote/tunnel | VS Code direct webview when possible | stdio direct webview or intentional persistent server | Persistence allowed only when transport requires it |
36
+ | Plain SSH | User-forwarded localhost URL | Transient server unless `--serve` requested | Viewer close ends transient session |
37
+
38
+ ## Local VS Code CLI
39
+
40
+ - `arrayview file.npy` from a local VS Code terminal should return to the prompt.
41
+ - Multiple local CLI launches may share one backend and open separate tabs.
42
+ - Closing one tab releases only that tab's arrays/sessions.
43
+ - Closing the last viewer tab should stop the transient daemon.
44
+ - The VS Code wrapper must not show "backend unavailable" based on a webview-side `fetch()`; backend health checks belong in the extension host.
45
+
46
+ ## VS Code File Click And Custom Editor
47
+
48
+ - Prefer direct extension-owned stdio subprocesses.
49
+ - Do not require localhost or a shared port when direct mode is available.
50
+ - Closing the tab should terminate the subprocess.
51
+ - This path is transient and owned by the extension session, not by a long-lived server.
52
+
53
+ ## Python Script
54
+
55
+ - `view(arr)` from a script should survive the script exiting.
56
+ - The backend must outlive the caller until viewer instances close.
57
+ - When the last viewer instance closes, free arrays and shut the backend down.
58
+ - Quick viewer connect/disconnect races must count as "a viewer connected" so transient waiters do not linger until connect timeout.
59
+
60
+ ## Jupyter
61
+
62
+ - Jupyter keeps the backend kernel-owned.
63
+ - An iframe disappearing should not hard-kill the backend.
64
+ - Explicit close or cleanup should free the session.
65
+ - Repeated `view()` calls should reuse the kernel-owned server when appropriate.
66
+
67
+ ## Remote, Tunnel, And SSH
68
+
69
+ - Remote or tunnel launches may persist when `--serve` or direct-server constraints require it.
70
+ - Direct VS Code tunnel display should prefer stdio direct webview to avoid forwarded-port auth and public-port setup.
71
+ - With multiple registered tunnel windows, a missing or stale `ARRAYVIEW_WINDOW_ID` must fail closed with a diagnostic rather than broadcasting to whichever window is focused.
72
+ - An exact registered `ARRAYVIEW_WINDOW_ID` wins; do not redirect it to a newer same-parent registration because live tunnel windows can share ancestry.
73
+ - Plain SSH should use `localhost` forwarding guidance and stay transient unless a shared server was explicitly requested.
74
+
75
+ ## Shared Rules
76
+
77
+ - Global lifecycle state lives in `_session.py`.
78
+ - `release_session()` is the session-release primitive.
79
+ - Viewer WebSocket connect/disconnect owns active viewer counts.
80
+ - URL panel disposal must release every SID encoded in the URL: `sid`, `compare_sid`, `compare_sids`, and `overlay_sid`.
81
+ - Tunnel registration cleanup must not remove live same-tunnel sibling windows.
82
+ - Explicit cleanup wins over implicit disappearance.
83
+ - Any VS Code extension source change must rebuild `src/arrayview/arrayview-opener.vsix` and keep the packaged version in sync.
84
+
85
+ ## Verification Anchors
86
+
87
+ - `tests/lifecycle_matrix.py` is the top-level lifecycle gate; it reports automated, real-process, local-state, and manual-only checks separately.
88
+ - `tests/test_lifecycle_contract.py` covers invocation ownership, release routes, transient daemon shutdown, and bundled VSIX lifecycle content.
89
+ - `tests/test_cli.py` covers CLI launch behavior.
90
+ - `tests/test_api.py` contains the affected WebSocket close and CLI helper coverage.
91
+ - `vscode-extension/test_lifecycle_helpers.js` covers URL SID collection and backend ping URL parsing.
92
+ - `vscode-extension/extension.js` must pass Node syntax checks after any extension change.
@@ -40,6 +40,7 @@ last_updated: 2026-05-13
40
40
 
41
41
  ## Recently Completed
42
42
 
43
+ - VS Code tab lifecycle hardening: local VS Code CLI launches now use transient daemon shutdown instead of `persist=True`, 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 via tested lifecycle helpers, quick viewer connect/disconnect races are detected by a monotonic connection counter, ambiguous multi-window tunnel routing now fails closed instead of opening in a guessed window, stale viewer SID retry state is cleared on WebSocket disconnect, and the bundled opener extension was rebuilt as v0.14.12.
43
44
  - Shift+C colormap picker redesign: the old centered shortlist is now a narrow translucent right-edge drawer with a close button, a yellow `Colormaps` title plus a `Favorites` subtitle, and a plain 12-swatch two-column quick set that stays visible above the search field. Search matches render in a separate results area below the input, Enter first exits the search field before a second Enter commits, arrow-key movement follows the visible two-column grid, and repeated `c` presses cycle through the currently visible swatches while the picker is open.
44
45
  - Detached compare-on-X: single-array non-spatial dimensions now support the same compare-center family as two-array compare. The frontend reuses compare mode with per-pane detached indices, the dimbar shows a purple `X`, the compare titles show index-over-total labels, `[` / `]` control pane A, `{` / `}` control pane B, and repeated `X` exits detached compare after cycling the center modes. Focused coverage now includes a browser regression for detached entry/scrubbing/exit plus API coverage for split `/diff` indices on the same session.
45
46
  - Normal-mode dimbar readability: inactive non-spatial dims no longer get a blanket reduced parent opacity, so the current index reads bright while `/total` stays subdued via the existing child dim-size styling.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arrayview
3
- Version: 0.24.0
3
+ Version: 0.25.1
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
@@ -0,0 +1,6 @@
1
+ # Lifecycle
2
+
3
+ The authoritative lifecycle contract lives in `.mex/context/lifecycle.md`.
4
+
5
+ Use that file before changing server startup, shutdown, display routing, VS Code
6
+ tab behavior, session release, or extension packaging.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "arrayview"
7
- version = "0.24.0"
7
+ version = "0.25.1"
8
8
  description = "Fast multi-dimensional array viewer"
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  requires-python = ">=3.12"
@@ -1,4 +1,4 @@
1
- __version__ = "0.20.0"
1
+ __version__ = "0.25.1"
2
2
 
3
3
  __all__ = [
4
4
  "TrainingMonitor",
@@ -43,8 +43,8 @@ def _build_metadata(session) -> dict:
43
43
  meta["ras_resample_active"] = bool(
44
44
  getattr(session, "ras_resample_active", False)
45
45
  )
46
- if getattr(session, "npz_keys", None):
47
- meta["npz_keys"] = session.npz_keys
46
+ if getattr(session, "array_keys", None):
47
+ meta["array_keys"] = session.array_keys
48
48
  return meta
49
49
 
50
50
 
@@ -268,11 +268,16 @@ def _pixel_value(
268
268
  """Return a finite pixel value or None."""
269
269
  if session.rgb_axis is not None:
270
270
  return None
271
- idx_tuple = (
272
- tuple(int(v) for v in indices.split(","))
273
- if isinstance(indices, str)
274
- else tuple(indices)
275
- )
271
+ if isinstance(indices, str):
272
+ parts = indices.split(",")
273
+ if not parts or any(v == "" for v in parts):
274
+ return None
275
+ try:
276
+ idx_tuple = tuple(int(v) for v in parts)
277
+ except ValueError:
278
+ return None
279
+ else:
280
+ idx_tuple = tuple(indices)
276
281
  raw = (
277
282
  qmri_display_slice(session, dim_x, dim_y, list(idx_tuple), qmri_role)
278
283
  if qmri_role
@@ -53,10 +53,52 @@ def list_npz_keys(filepath):
53
53
  return keys
54
54
 
55
55
 
56
+ def list_mat_keys(filepath):
57
+ """Return [{key, shape, dtype}] for each array in a .mat file.
58
+
59
+ Handles both scipy-loadable .mat files and v7.3 HDF5-based files.
60
+ Filters out metadata keys (starting with '_') and non-array entries.
61
+ """
62
+ try:
63
+ import scipy.io
64
+
65
+ mat = scipy.io.loadmat(filepath)
66
+ keys = []
67
+ for k, v in mat.items():
68
+ if k.startswith("_"):
69
+ continue
70
+ if isinstance(v, np.ndarray) and v.ndim >= 1 and v.dtype.kind in ("b", "i", "u", "f", "c"):
71
+ keys.append({"key": k, "shape": list(v.shape), "dtype": str(v.dtype)})
72
+ return keys
73
+ except NotImplementedError:
74
+ import h5py
75
+
76
+ f = h5py.File(filepath, "r")
77
+ keys = []
78
+ for k in f.keys():
79
+ ds = f[k]
80
+ if isinstance(ds, h5py.Dataset) and len(ds.shape) >= 1 and ds.dtype.kind in ("b", "i", "u", "f", "c"):
81
+ keys.append({"key": k, "shape": list(ds.shape), "dtype": str(ds.dtype)})
82
+ f.close()
83
+ return keys
84
+
85
+
86
+ def list_array_keys(filepath):
87
+ """Return [{key, shape, dtype}] for each array in a multi-array file.
88
+
89
+ Dispatches by extension: .npz or .mat.
90
+ """
91
+ if filepath.endswith(".npz"):
92
+ return list_npz_keys(filepath)
93
+ if filepath.endswith(".mat"):
94
+ return list_mat_keys(filepath)
95
+ return []
96
+
97
+
56
98
  def _select_npz_array(npz, filepath):
57
99
  """Load the first array from a multi-array .npz file.
58
100
 
59
- The in-viewer NPZ picker handles array selection — no terminal prompt.
101
+ The in-viewer array picker handles array selection — no terminal prompt.
60
102
  """
61
103
  keys = list(npz.keys())
62
104
  return npz[keys[0]]
@@ -193,11 +235,13 @@ def load_data(filepath, key=None):
193
235
  for k, v in mat.items()
194
236
  if not k.startswith("_") and isinstance(v, np.ndarray)
195
237
  }
238
+ if key is not None:
239
+ return _fix_mat_complex(arrays[key])
196
240
  if len(arrays) == 1:
197
241
  return _fix_mat_complex(next(iter(arrays.values())))
198
242
  raise ValueError(
199
243
  f".mat file contains multiple arrays: {list(arrays.keys())}. "
200
- "Load it manually and pass the array to view()."
244
+ "Select one in the viewer or pass a key."
201
245
  )
202
246
  except NotImplementedError:
203
247
  # MATLAB v7.3 files use HDF5 — scipy cannot load them; fall back to h5py.
@@ -205,11 +249,13 @@ def load_data(filepath, key=None):
205
249
 
206
250
  f = h5py.File(filepath, "r")
207
251
  arrays = {k: f[k] for k in f.keys() if isinstance(f[k], h5py.Dataset)}
252
+ if key is not None:
253
+ return np.array(arrays[key])
208
254
  if len(arrays) == 1:
209
255
  return np.array(next(iter(arrays.values())))
210
256
  raise ValueError(
211
257
  f".mat (v7.3) file contains multiple datasets: {list(arrays.keys())}. "
212
- "Load it manually with h5py and pass the array to view()."
258
+ "Select one in the viewer or pass a key."
213
259
  )
214
260
  else:
215
261
  raise ValueError(