arrayview 0.9.0__tar.gz → 0.10.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 (68) hide show
  1. {arrayview-0.9.0 → arrayview-0.10.1}/PKG-INFO +1 -1
  2. {arrayview-0.9.0 → arrayview-0.10.1}/pyproject.toml +1 -1
  3. {arrayview-0.9.0 → arrayview-0.10.1}/src/arrayview/_server.py +84 -0
  4. {arrayview-0.9.0 → arrayview-0.10.1}/src/arrayview/_viewer.html +562 -116
  5. {arrayview-0.9.0 → arrayview-0.10.1}/uv.lock +1 -1
  6. {arrayview-0.9.0 → arrayview-0.10.1}/.claude/skills/invocation-consistency/SKILL.md +0 -0
  7. {arrayview-0.9.0 → arrayview-0.10.1}/.claude/skills/modes-consistency/SKILL.md +0 -0
  8. {arrayview-0.9.0 → arrayview-0.10.1}/.claude/skills/ui-consistency-audit/SKILL.md +0 -0
  9. {arrayview-0.9.0 → arrayview-0.10.1}/.claude/skills/viewer-ui-checklist/SKILL.md +0 -0
  10. {arrayview-0.9.0 → arrayview-0.10.1}/.claude/skills/visual-bug-fixing/SKILL.md +0 -0
  11. {arrayview-0.9.0 → arrayview-0.10.1}/.github/workflows/docs.yml +0 -0
  12. {arrayview-0.9.0 → arrayview-0.10.1}/.github/workflows/python-publish.yml +0 -0
  13. {arrayview-0.9.0 → arrayview-0.10.1}/.gitignore +0 -0
  14. {arrayview-0.9.0 → arrayview-0.10.1}/.python-version +0 -0
  15. {arrayview-0.9.0 → arrayview-0.10.1}/.tmp-vsix/extension/extension.js +0 -0
  16. {arrayview-0.9.0 → arrayview-0.10.1}/.tmp-vsix/extension/package.json +0 -0
  17. {arrayview-0.9.0 → arrayview-0.10.1}/AGENTS.md +0 -0
  18. {arrayview-0.9.0 → arrayview-0.10.1}/LICENSE +0 -0
  19. {arrayview-0.9.0 → arrayview-0.10.1}/README.md +0 -0
  20. {arrayview-0.9.0 → arrayview-0.10.1}/docs/comparing.md +0 -0
  21. {arrayview-0.9.0 → arrayview-0.10.1}/docs/configuration.md +0 -0
  22. {arrayview-0.9.0 → arrayview-0.10.1}/docs/display.md +0 -0
  23. {arrayview-0.9.0 → arrayview-0.10.1}/docs/index.md +0 -0
  24. {arrayview-0.9.0 → arrayview-0.10.1}/docs/loading.md +0 -0
  25. {arrayview-0.9.0 → arrayview-0.10.1}/docs/logo.png +0 -0
  26. {arrayview-0.9.0 → arrayview-0.10.1}/docs/measurement.md +0 -0
  27. {arrayview-0.9.0 → arrayview-0.10.1}/docs/remote.md +0 -0
  28. {arrayview-0.9.0 → arrayview-0.10.1}/docs/stylesheets/extra.css +0 -0
  29. {arrayview-0.9.0 → arrayview-0.10.1}/docs/viewing.md +0 -0
  30. {arrayview-0.9.0 → arrayview-0.10.1}/matlab/arrayview.m +0 -0
  31. {arrayview-0.9.0 → arrayview-0.10.1}/mkdocs.yml +0 -0
  32. {arrayview-0.9.0 → arrayview-0.10.1}/plans/webview/LOG.md +0 -0
  33. {arrayview-0.9.0 → arrayview-0.10.1}/scripts/demo.py +0 -0
  34. {arrayview-0.9.0 → arrayview-0.10.1}/scripts/release.sh +0 -0
  35. {arrayview-0.9.0 → arrayview-0.10.1}/src/arrayview/ARCHITECTURE.md +0 -0
  36. {arrayview-0.9.0 → arrayview-0.10.1}/src/arrayview/__init__.py +0 -0
  37. {arrayview-0.9.0 → arrayview-0.10.1}/src/arrayview/__main__.py +0 -0
  38. {arrayview-0.9.0 → arrayview-0.10.1}/src/arrayview/_app.py +0 -0
  39. {arrayview-0.9.0 → arrayview-0.10.1}/src/arrayview/_config.py +0 -0
  40. {arrayview-0.9.0 → arrayview-0.10.1}/src/arrayview/_icon.png +0 -0
  41. {arrayview-0.9.0 → arrayview-0.10.1}/src/arrayview/_io.py +0 -0
  42. {arrayview-0.9.0 → arrayview-0.10.1}/src/arrayview/_launcher.py +0 -0
  43. {arrayview-0.9.0 → arrayview-0.10.1}/src/arrayview/_platform.py +0 -0
  44. {arrayview-0.9.0 → arrayview-0.10.1}/src/arrayview/_render.py +0 -0
  45. {arrayview-0.9.0 → arrayview-0.10.1}/src/arrayview/_segmentation.py +0 -0
  46. {arrayview-0.9.0 → arrayview-0.10.1}/src/arrayview/_session.py +0 -0
  47. {arrayview-0.9.0 → arrayview-0.10.1}/src/arrayview/_shell.html +0 -0
  48. {arrayview-0.9.0 → arrayview-0.10.1}/src/arrayview/_stdio_server.py +0 -0
  49. {arrayview-0.9.0 → arrayview-0.10.1}/src/arrayview/_torch.py +0 -0
  50. {arrayview-0.9.0 → arrayview-0.10.1}/src/arrayview/_vscode.py +0 -0
  51. {arrayview-0.9.0 → arrayview-0.10.1}/src/arrayview/arrayview-opener.vsix +0 -0
  52. {arrayview-0.9.0 → arrayview-0.10.1}/tests/conftest.py +0 -0
  53. {arrayview-0.9.0 → arrayview-0.10.1}/tests/make_vectorfield_test_arrays.py +0 -0
  54. {arrayview-0.9.0 → arrayview-0.10.1}/tests/test_api.py +0 -0
  55. {arrayview-0.9.0 → arrayview-0.10.1}/tests/test_browser.py +0 -0
  56. {arrayview-0.9.0 → arrayview-0.10.1}/tests/test_cli.py +0 -0
  57. {arrayview-0.9.0 → arrayview-0.10.1}/tests/test_config.py +0 -0
  58. {arrayview-0.9.0 → arrayview-0.10.1}/tests/test_interactions.py +0 -0
  59. {arrayview-0.9.0 → arrayview-0.10.1}/tests/test_large_arrays.py +0 -0
  60. {arrayview-0.9.0 → arrayview-0.10.1}/tests/test_mode_consistency.py +0 -0
  61. {arrayview-0.9.0 → arrayview-0.10.1}/tests/test_mode_matrix.py +0 -0
  62. {arrayview-0.9.0 → arrayview-0.10.1}/tests/test_rgb_pixel_art.py +0 -0
  63. {arrayview-0.9.0 → arrayview-0.10.1}/tests/test_torch.py +0 -0
  64. {arrayview-0.9.0 → arrayview-0.10.1}/tests/ui_audit.py +0 -0
  65. {arrayview-0.9.0 → arrayview-0.10.1}/tests/visual_smoke.py +0 -0
  66. {arrayview-0.9.0 → arrayview-0.10.1}/vscode-extension/LICENSE +0 -0
  67. {arrayview-0.9.0 → arrayview-0.10.1}/vscode-extension/extension.js +0 -0
  68. {arrayview-0.9.0 → arrayview-0.10.1}/vscode-extension/package.json +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arrayview
3
- Version: 0.9.0
3
+ Version: 0.10.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
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "arrayview"
7
- version = "0.9.0"
7
+ version = "0.10.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"
@@ -1913,6 +1913,90 @@ def get_volume_histogram(
1913
1913
  return result
1914
1914
 
1915
1915
 
1916
+ # ── Volume Data (3-D MIP) ────────────────────────────────────────
1917
+
1918
+
1919
+ @app.get("/volume_data/{sid}")
1920
+ def get_volume_data(
1921
+ sid: str,
1922
+ dims: str = "",
1923
+ indices: str = "",
1924
+ complex_mode: int = 0,
1925
+ ):
1926
+ """Return the full 3-D sub-volume as raw float32 bytes for the WebGL MIP renderer.
1927
+
1928
+ *dims* is a comma-separated triple of the three spatial dimensions (e.g. ``"0,1,2"``).
1929
+ *indices* gives the current index for every dimension (comma-separated).
1930
+ Dimensions not in *dims* are sliced at the value given in *indices*.
1931
+
1932
+ If any axis exceeds 256, stride-based down-sampling is applied so that
1933
+ the returned volume fits within 256^3.
1934
+
1935
+ Response headers carry ``X-Shape`` (comma-separated), ``X-Vmin``, ``X-Vmax``.
1936
+ """
1937
+ session = SESSIONS.get(sid)
1938
+ if not session:
1939
+ return Response(status_code=404)
1940
+
1941
+ # Parse dims and indices
1942
+ if not dims:
1943
+ return Response(status_code=400, content="dims required")
1944
+ dim_list = [int(d) for d in dims.split(",")]
1945
+ if len(dim_list) != 3:
1946
+ return Response(status_code=400, content="dims must be exactly 3 integers")
1947
+
1948
+ idx_list = [int(x) for x in indices.split(",")] if indices else [s // 2 for s in session.shape]
1949
+
1950
+ # Build slicer: keep the 3 spatial dims free, fix everything else
1951
+ slicer = []
1952
+ for i in range(len(session.shape)):
1953
+ if i in dim_list:
1954
+ slicer.append(slice(None))
1955
+ else:
1956
+ idx = idx_list[i] if i < len(idx_list) else session.shape[i] // 2
1957
+ slicer.append(min(max(idx, 0), session.shape[i] - 1))
1958
+ vol = np.array(session.data[tuple(slicer)])
1959
+
1960
+ # Reorder axes so dim_list order maps to (0, 1, 2) of the output
1961
+ # vol currently has axes at the positions corresponding to dim_list within
1962
+ # the free-axis subset. We need to figure out which axes of `vol` correspond
1963
+ # to which dim in dim_list.
1964
+ free_axes_sorted = sorted(dim_list)
1965
+ # vol axes are in the order of free_axes_sorted (numpy preserves order)
1966
+ perm = [free_axes_sorted.index(d) for d in dim_list]
1967
+ vol = np.transpose(vol, perm)
1968
+
1969
+ # Apply complex mode
1970
+ vol = apply_complex_mode(vol, complex_mode)
1971
+
1972
+ # Downsample any axis > 256
1973
+ max_dim = 256
1974
+ strides = []
1975
+ for s in vol.shape:
1976
+ strides.append(max(1, (s + max_dim - 1) // max_dim))
1977
+ if any(st > 1 for st in strides):
1978
+ vol = vol[::strides[0], ::strides[1], ::strides[2]]
1979
+
1980
+ vol = np.ascontiguousarray(vol, dtype=np.float32)
1981
+
1982
+ finite = vol[np.isfinite(vol)]
1983
+ if finite.size > 0:
1984
+ vmin = float(np.percentile(finite, 1))
1985
+ vmax = float(np.percentile(finite, 99))
1986
+ else:
1987
+ vmin, vmax = 0.0, 1.0
1988
+
1989
+ return Response(
1990
+ content=vol.tobytes(),
1991
+ media_type="application/octet-stream",
1992
+ headers={
1993
+ "X-Shape": ",".join(str(s) for s in vol.shape),
1994
+ "X-Vmin": str(vmin),
1995
+ "X-Vmax": str(vmax),
1996
+ },
1997
+ )
1998
+
1999
+
1916
2000
  @app.get("/lebesgue/{sid}")
1917
2001
  def get_lebesgue_slice(
1918
2002
  sid: str,