arrayview 0.12.0__tar.gz → 0.12.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.
Files changed (74) hide show
  1. {arrayview-0.12.0 → arrayview-0.12.2}/.claude/skills/viewer-ui-checklist/SKILL.md +10 -2
  2. {arrayview-0.12.0 → arrayview-0.12.2}/AGENTS.md +8 -1
  3. arrayview-0.12.2/CONTRIBUTING.md +93 -0
  4. {arrayview-0.12.0 → arrayview-0.12.2}/PKG-INFO +1 -1
  5. {arrayview-0.12.0 → arrayview-0.12.2}/pyproject.toml +1 -1
  6. arrayview-0.12.2/scripts/release.sh +138 -0
  7. {arrayview-0.12.0 → arrayview-0.12.2}/src/arrayview/_stdio_server.py +6 -1
  8. {arrayview-0.12.0 → arrayview-0.12.2}/src/arrayview/_viewer.html +279 -97
  9. {arrayview-0.12.0 → arrayview-0.12.2}/src/arrayview/_vscode.py +71 -1
  10. arrayview-0.12.2/src/arrayview/arrayview-opener.vsix +0 -0
  11. {arrayview-0.12.0 → arrayview-0.12.2}/uv.lock +1 -1
  12. {arrayview-0.12.0 → arrayview-0.12.2}/vscode-extension/extension.js +28 -0
  13. arrayview-0.12.0/.tmp-vsix/extension/extension.js +0 -343
  14. arrayview-0.12.0/.tmp-vsix/extension/package.json +0 -13
  15. arrayview-0.12.0/scripts/release.sh +0 -78
  16. arrayview-0.12.0/src/arrayview/arrayview-opener.vsix +0 -0
  17. {arrayview-0.12.0 → arrayview-0.12.2}/.claude/skills/invocation-consistency/SKILL.md +0 -0
  18. {arrayview-0.12.0 → arrayview-0.12.2}/.claude/skills/modes-consistency/SKILL.md +0 -0
  19. {arrayview-0.12.0 → arrayview-0.12.2}/.claude/skills/ui-consistency-audit/SKILL.md +0 -0
  20. {arrayview-0.12.0 → arrayview-0.12.2}/.claude/skills/visual-bug-fixing/SKILL.md +0 -0
  21. {arrayview-0.12.0 → arrayview-0.12.2}/.github/workflows/docs.yml +0 -0
  22. {arrayview-0.12.0 → arrayview-0.12.2}/.github/workflows/python-publish.yml +0 -0
  23. {arrayview-0.12.0 → arrayview-0.12.2}/.gitignore +0 -0
  24. {arrayview-0.12.0 → arrayview-0.12.2}/.python-version +0 -0
  25. {arrayview-0.12.0 → arrayview-0.12.2}/LICENSE +0 -0
  26. {arrayview-0.12.0 → arrayview-0.12.2}/README.md +0 -0
  27. {arrayview-0.12.0 → arrayview-0.12.2}/docs/comparing.md +0 -0
  28. {arrayview-0.12.0 → arrayview-0.12.2}/docs/configuration.md +0 -0
  29. {arrayview-0.12.0 → arrayview-0.12.2}/docs/display.md +0 -0
  30. {arrayview-0.12.0 → arrayview-0.12.2}/docs/index.md +0 -0
  31. {arrayview-0.12.0 → arrayview-0.12.2}/docs/loading.md +0 -0
  32. {arrayview-0.12.0 → arrayview-0.12.2}/docs/logo.png +0 -0
  33. {arrayview-0.12.0 → arrayview-0.12.2}/docs/measurement.md +0 -0
  34. {arrayview-0.12.0 → arrayview-0.12.2}/docs/remote.md +0 -0
  35. {arrayview-0.12.0 → arrayview-0.12.2}/docs/stylesheets/extra.css +0 -0
  36. {arrayview-0.12.0 → arrayview-0.12.2}/docs/viewing.md +0 -0
  37. {arrayview-0.12.0 → arrayview-0.12.2}/matlab/arrayview.m +0 -0
  38. {arrayview-0.12.0 → arrayview-0.12.2}/mkdocs.yml +0 -0
  39. {arrayview-0.12.0 → arrayview-0.12.2}/plans/webview/LOG.md +0 -0
  40. {arrayview-0.12.0 → arrayview-0.12.2}/scripts/demo.py +0 -0
  41. {arrayview-0.12.0 → arrayview-0.12.2}/src/arrayview/ARCHITECTURE.md +0 -0
  42. {arrayview-0.12.0 → arrayview-0.12.2}/src/arrayview/__init__.py +0 -0
  43. {arrayview-0.12.0 → arrayview-0.12.2}/src/arrayview/__main__.py +0 -0
  44. {arrayview-0.12.0 → arrayview-0.12.2}/src/arrayview/_app.py +0 -0
  45. {arrayview-0.12.0 → arrayview-0.12.2}/src/arrayview/_config.py +0 -0
  46. {arrayview-0.12.0 → arrayview-0.12.2}/src/arrayview/_icon.png +0 -0
  47. {arrayview-0.12.0 → arrayview-0.12.2}/src/arrayview/_io.py +0 -0
  48. {arrayview-0.12.0 → arrayview-0.12.2}/src/arrayview/_launcher.py +0 -0
  49. {arrayview-0.12.0 → arrayview-0.12.2}/src/arrayview/_platform.py +0 -0
  50. {arrayview-0.12.0 → arrayview-0.12.2}/src/arrayview/_render.py +0 -0
  51. {arrayview-0.12.0 → arrayview-0.12.2}/src/arrayview/_segmentation.py +0 -0
  52. {arrayview-0.12.0 → arrayview-0.12.2}/src/arrayview/_server.py +0 -0
  53. {arrayview-0.12.0 → arrayview-0.12.2}/src/arrayview/_session.py +0 -0
  54. {arrayview-0.12.0 → arrayview-0.12.2}/src/arrayview/_shell.html +0 -0
  55. {arrayview-0.12.0 → arrayview-0.12.2}/src/arrayview/_torch.py +0 -0
  56. {arrayview-0.12.0 → arrayview-0.12.2}/tests/conftest.py +0 -0
  57. {arrayview-0.12.0 → arrayview-0.12.2}/tests/make_vectorfield_test_arrays.py +0 -0
  58. {arrayview-0.12.0 → arrayview-0.12.2}/tests/test_api.py +0 -0
  59. {arrayview-0.12.0 → arrayview-0.12.2}/tests/test_browser.py +0 -0
  60. {arrayview-0.12.0 → arrayview-0.12.2}/tests/test_cli.py +0 -0
  61. {arrayview-0.12.0 → arrayview-0.12.2}/tests/test_command_reachability.py +0 -0
  62. {arrayview-0.12.0 → arrayview-0.12.2}/tests/test_config.py +0 -0
  63. {arrayview-0.12.0 → arrayview-0.12.2}/tests/test_interactions.py +0 -0
  64. {arrayview-0.12.0 → arrayview-0.12.2}/tests/test_large_arrays.py +0 -0
  65. {arrayview-0.12.0 → arrayview-0.12.2}/tests/test_mode_consistency.py +0 -0
  66. {arrayview-0.12.0 → arrayview-0.12.2}/tests/test_mode_matrix.py +0 -0
  67. {arrayview-0.12.0 → arrayview-0.12.2}/tests/test_mode_roundtrip.py +0 -0
  68. {arrayview-0.12.0 → arrayview-0.12.2}/tests/test_nifti_meta.py +0 -0
  69. {arrayview-0.12.0 → arrayview-0.12.2}/tests/test_rgb_pixel_art.py +0 -0
  70. {arrayview-0.12.0 → arrayview-0.12.2}/tests/test_torch.py +0 -0
  71. {arrayview-0.12.0 → arrayview-0.12.2}/tests/ui_audit.py +0 -0
  72. {arrayview-0.12.0 → arrayview-0.12.2}/tests/visual_smoke.py +0 -0
  73. {arrayview-0.12.0 → arrayview-0.12.2}/vscode-extension/LICENSE +0 -0
  74. {arrayview-0.12.0 → arrayview-0.12.2}/vscode-extension/package.json +0 -0
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  name: viewer-ui-checklist
3
- description: Use when adding keyboard shortcuts, changing layout, or making any UI change to arrayview. Ensures visual_smoke.py stays in sync.
3
+ description: Use when adding keyboard shortcuts, changing layout, or making any UI change to arrayview. Ensures visual_smoke.py, help overlay, and README stay in sync.
4
4
  ---
5
5
 
6
6
  # ArrayView UI Checklist
7
7
 
8
8
  ## Rule
9
9
 
10
- Every UI change to arrayview MUST be reflected in `tests/visual_smoke.py` before the task is complete.
10
+ Every UI change to arrayview MUST be reflected in `tests/visual_smoke.py`, the help overlay, and (when user-facing) `README.md` before the task is complete.
11
11
 
12
12
  ## What counts as a UI change
13
13
 
@@ -35,6 +35,14 @@ Every UI change to arrayview MUST be reflected in `tests/visual_smoke.py` before
35
35
 
36
36
  4. **Open and review** the new screenshots in `tests/smoke_output/`
37
37
 
38
+ 5. **Update `GUIDE_TABS`** in `_viewer.html` if you added, removed, or changed a keybinding
39
+ - Add/update the entry in the appropriate tab and section
40
+ - Include a `hint` for non-obvious shortcuts
41
+ - Use the `docs-style` skill for formatting rules
42
+
43
+ 6. **Update `README.md`** if the change is user-facing (new CLI flag, new API, new mode)
44
+ - Use the `docs-style` skill for formatting rules
45
+
38
46
  ## Red flags — STOP
39
47
 
40
48
  - "The shortcut is too simple to need a smoke test" → ALL shortcuts need entries
@@ -15,7 +15,8 @@ Load the relevant skill before touching the corresponding area.
15
15
  | `frontend-designer` | Styling/layout changes to `_viewer.html` |
16
16
  | `vscode-simplebrowser` | Extension, signal-file IPC, `_VSCODE_EXT_VERSION` |
17
17
  | `invocation-consistency` | Server startup, display-opening, env detection |
18
- | `docs-style` | README, help overlay, docstrings |
18
+ | `viewer-ui-checklist` | Any UI change (smoke tests, help overlay, README sync) |
19
+ | `docs-style` | README, help overlay, docstrings (formatting rules) |
19
20
 
20
21
  ## Non-Negotiables
21
22
 
@@ -29,6 +30,12 @@ Load the relevant skill before touching the corresponding area.
29
30
  - All colorbar state (animation, window/level, hover, drag) flows through `primaryCb` ColorBar instance — never read/write legacy globals. Multiview colorbars sync via `primaryCb`.
30
31
  - Keybinds flow through the command registry (`commands` / `keybinds` in `_viewer.html`), not inline keydown branches. The help overlay auto-generates from command `title` fields — do not hand-edit it.
31
32
 
33
+ ## Contributing
34
+
35
+ Before creating a PR or making user-facing changes, read `CONTRIBUTING.md`. It defines the design
36
+ language, keybinding conventions, overlay/popup patterns, and testing requirements. All PRs that
37
+ touch the viewer must follow it.
38
+
32
39
  ## Execution
33
40
 
34
41
  Always use **subagent-driven development** for implementation. Commit completed work automatically.
@@ -0,0 +1,93 @@
1
+ # Contributing to arrayview
2
+
3
+ Thanks for your interest. This guide keeps things consistent as more people
4
+ contribute.
5
+
6
+ ## Proposing changes
7
+
8
+ For anything user-facing (new shortcut, overlay, layout change), **open an
9
+ issue first**. Include:
10
+
11
+ - What it does, in one sentence
12
+ - Which key triggers it (if any)
13
+ - Which modes it affects (Normal, Multi-view, Compare, Diff, Registration, qMRI)
14
+ - A rough sketch or description of how it looks
15
+
16
+ Bug fixes and internal refactors can go straight to a PR.
17
+
18
+ ## Design principles
19
+
20
+ 1. **Array fills the screen.** Minimize chrome. UI elements stay hidden or
21
+ dimmed until the user hovers or presses a key, then fade back out.
22
+
23
+ 2. **Monospace only.** All text uses the system monospace stack
24
+ (`'SF Mono', ui-monospace, 'Cascadia Code', 'JetBrains Mono', monospace`).
25
+ Never use sans-serif.
26
+
27
+ 3. **Colors via CSS custom properties.** Use `var(--surface)`, `var(--text)`,
28
+ `var(--active-dim)`, etc. Never hardcode hex values. The viewer ships four
29
+ themes (dark, light, solarized, nord) and all must work.
30
+
31
+ 4. **Yellow for active state.** `--active-dim` (#f5c842 in dark theme) marks
32
+ the currently active element. Don't introduce new accent colors.
33
+
34
+ 5. **All six modes.** Every visual feature must be tested across Normal,
35
+ Multi-view (V/v), Compare (B/P), Diff (X), Registration (R), and qMRI (q).
36
+ If your feature only applies to some modes, add explicit mode guards.
37
+
38
+ ## Keyboard shortcuts
39
+
40
+ - Check the existing shortcut table (press `?` in the viewer) before picking a
41
+ key. Conflicts will be caught in review but save yourself the round-trip.
42
+ - Single lowercase letters are scarce. Prefer Shift+key or a modifier for new
43
+ features.
44
+ - If a shortcut only makes sense in certain modes, guard it:
45
+ ```js
46
+ if (currentMode !== 'compare') return;
47
+ ```
48
+ - Document the new shortcut in the help overlay (`#help-overlay` in
49
+ `_viewer.html`).
50
+
51
+ ## Popup menus and overlays
52
+
53
+ Several proposals involve popup/context menus. To keep them visually
54
+ consistent:
55
+
56
+ - Background: `var(--surface)`, border: `1px solid var(--border)`,
57
+ border-radius: `var(--radius-lg)`.
58
+ - Dismiss on **Escape** and on clicking outside the popup.
59
+ - No permanent visibility -- show on trigger, hide when done.
60
+ - Keep text small (12-13px) and monospace.
61
+ - Use `var(--active-dim)` for the selected/hovered item, `var(--text)` for
62
+ normal items, `var(--muted)` for secondary info.
63
+ - Animate in with a short opacity+scale transition, not an instant pop.
64
+
65
+ Look at `#uni-picker-box` in `_viewer.html` for a reference implementation.
66
+
67
+ ## Testing checklist
68
+
69
+ Before submitting a PR:
70
+
71
+ - [ ] `uv run pytest tests/test_api.py -x` passes
72
+ - [ ] `uv run python tests/visual_smoke.py` passes
73
+ - [ ] If you added UI, update `tests/visual_smoke.py` to cover it
74
+ - [ ] Manually verify in all affected modes (at minimum: Normal + one
75
+ multi-pane mode)
76
+ - [ ] New shortcuts are documented in the help overlay
77
+
78
+ ## Dev setup
79
+
80
+ ```bash
81
+ git clone <repo-url>
82
+ cd arrayview
83
+ uv sync
84
+ uv run arrayview tests/ # launch with test data
85
+ ```
86
+
87
+ ## Style notes
88
+
89
+ - The frontend lives in a single file: `src/arrayview/_viewer.html`.
90
+ HTML, CSS, and JS are all in there. Keep it that way.
91
+ - Python backend uses `uv` for package management.
92
+ - Commit messages follow conventional commits (`feat:`, `fix:`, `refactor:`,
93
+ etc.).
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arrayview
3
- Version: 0.12.0
3
+ Version: 0.12.2
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
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "arrayview"
7
- version = "0.12.0"
7
+ version = "0.12.2"
8
8
  description = "Fast multi-dimensional array viewer"
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  requires-python = ">=3.12"
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # ---------------------------------------------------------------------------
5
+ # release.sh — bump version, commit, tag, push, create GitHub release
6
+ # ---------------------------------------------------------------------------
7
+
8
+ BUMP="minor"
9
+ DRY_RUN=true
10
+ NO_AI=false
11
+
12
+ usage() {
13
+ cat <<EOF
14
+ Usage: $(basename "$0") [OPTIONS]
15
+
16
+ Options:
17
+ --bump {major,minor,patch} Version bump type (default: minor)
18
+ --execute Actually run (default is dry-run)
19
+ --no-ai Skip AI release notes, use GitHub's --generate-notes
20
+ -h, --help Show this help
21
+ EOF
22
+ }
23
+
24
+ while [[ $# -gt 0 ]]; do
25
+ case "$1" in
26
+ --bump) BUMP="$2"; shift 2 ;;
27
+ --execute) DRY_RUN=false; shift ;;
28
+ --no-ai) NO_AI=true; shift ;;
29
+ -h|--help) usage; exit 0 ;;
30
+ *) echo "Unknown option: $1"; usage; exit 1 ;;
31
+ esac
32
+ done
33
+
34
+ if [[ ! "$BUMP" =~ ^(major|minor|patch)$ ]]; then
35
+ echo "Error: --bump must be major, minor, or patch (got '$BUMP')"
36
+ exit 1
37
+ fi
38
+
39
+ # --- Guard: clean working tree on main ---
40
+ branch=$(git rev-parse --abbrev-ref HEAD)
41
+ if [[ "$branch" != "main" ]]; then
42
+ echo "Error: must be on main (currently on '$branch')"
43
+ exit 1
44
+ fi
45
+
46
+ if ! git diff --quiet || ! git diff --cached --quiet; then
47
+ echo "Error: working tree is dirty — commit or stash first"
48
+ exit 1
49
+ fi
50
+
51
+ # --- Bump version ---
52
+ uv version --bump "$BUMP"
53
+ VERSION=$(uv version --short)
54
+ TAG="v${VERSION}"
55
+
56
+ echo "Version bumped to $VERSION (tag: $TAG)"
57
+
58
+ uv lock --quiet
59
+
60
+ run() {
61
+ echo "+ $*"
62
+ if [[ "$DRY_RUN" == true ]]; then
63
+ return
64
+ fi
65
+ "$@"
66
+ }
67
+
68
+ # --- Generate release notes ---
69
+ CLAUDE_BIN="${CLAUDE_BIN:-/Users/oscar/.local/bin/claude}"
70
+ PREV_TAG=$(git describe --tags --abbrev=0 HEAD 2>/dev/null || echo "")
71
+ NOTES=""
72
+
73
+ if [[ -n "$PREV_TAG" ]]; then
74
+ COMMITS=$(git log "${PREV_TAG}..HEAD" --oneline)
75
+ else
76
+ COMMITS=$(git log --oneline -20)
77
+ fi
78
+
79
+ if [[ "$NO_AI" == false ]] && command -v "$CLAUDE_BIN" &>/dev/null; then
80
+ echo "Generating release notes with Claude..."
81
+ NOTES=$("$CLAUDE_BIN" -p "You are writing release notes for arrayview $TAG (a Python array/image viewer).
82
+
83
+ Here are the commits since the last release ($PREV_TAG):
84
+
85
+ $COMMITS
86
+
87
+ Write concise, user-friendly release notes in this exact format:
88
+
89
+ ## What's new in $TAG
90
+
91
+ - **Feature name**: one-sentence description
92
+
93
+ Rules:
94
+ - 5-10 bullet points max — group related commits into one bullet
95
+ - Write for end-users, not developers (no commit hashes, no file names)
96
+ - Use past tense (\"added\", \"fixed\", \"improved\")
97
+ - Skip pure refactors/docs unless they affect user experience
98
+ - Bold the feature name, keep the description to one sentence" 2>/dev/null) || true
99
+ fi
100
+
101
+ if [[ -z "$NOTES" ]]; then
102
+ if [[ "$NO_AI" == false ]]; then
103
+ echo "AI notes unavailable, falling back to --generate-notes"
104
+ fi
105
+ fi
106
+
107
+ if [[ "$DRY_RUN" == true && -n "$NOTES" ]]; then
108
+ echo ""
109
+ echo "--- Release notes preview ---"
110
+ echo "$NOTES"
111
+ echo "-----------------------------"
112
+ echo ""
113
+ fi
114
+
115
+ # --- Commit, tag, push, release ---
116
+ run git add pyproject.toml uv.lock
117
+ run git commit -m "release: $TAG"
118
+ run git push origin main
119
+ run git tag "$TAG"
120
+ run git push origin "$TAG"
121
+
122
+ if [[ -n "$NOTES" ]]; then
123
+ run gh release create "$TAG" \
124
+ --title "$TAG" \
125
+ --notes "$NOTES" \
126
+ --prerelease
127
+ else
128
+ run gh release create "$TAG" \
129
+ --title "$TAG" \
130
+ --generate-notes \
131
+ --prerelease
132
+ fi
133
+
134
+ if [[ "$DRY_RUN" == true ]]; then
135
+ echo ""
136
+ echo "(dry-run — re-run with --execute to apply)"
137
+ git checkout pyproject.toml uv.lock
138
+ fi
@@ -637,7 +637,7 @@ def _handle_get_viewer_html(msg: dict) -> None:
637
637
  """Return the rendered viewer HTML with template substitutions."""
638
638
  from importlib.resources import files as _pkg_files
639
639
 
640
- from arrayview._config import get_viewer_colormaps
640
+ from arrayview._config import get_viewer_colormaps, get_viewer_theme
641
641
  from arrayview._render import COLORMAP_GRADIENT_STOPS, COMPLEX_MODES, REAL_MODES
642
642
  from arrayview._session import COLORMAPS
643
643
 
@@ -650,12 +650,17 @@ def _handle_get_viewer_html(msg: dict) -> None:
650
650
 
651
651
  query_val = json.dumps(f"?sid={sid}&transport=postMessage") if sid else "null"
652
652
 
653
+ _theme_names = ["dark", "light", "solarized", "nord"]
654
+ _cfg_theme = get_viewer_theme()
655
+ _default_theme_idx = _theme_names.index(_cfg_theme) if _cfg_theme in _theme_names else 0
656
+
653
657
  html = (
654
658
  template.replace("__COLORMAPS__", str(_active_colormaps))
655
659
  .replace("__COLORMAP_GRADIENT_STOPS__", json.dumps(COLORMAP_GRADIENT_STOPS))
656
660
  .replace("__COMPLEX_MODES__", str(COMPLEX_MODES))
657
661
  .replace("__REAL_MODES__", str(REAL_MODES))
658
662
  .replace("__ARRAYVIEW_QUERY__", query_val)
663
+ .replace("__DEFAULT_THEME_IDX__", str(_default_theme_idx))
659
664
  )
660
665
 
661
666
  _write_json({"html": html})