arrayview 0.51.0__tar.gz → 0.51.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.
- {arrayview-0.51.0 → arrayview-0.51.1}/PKG-INFO +3 -1
- {arrayview-0.51.0 → arrayview-0.51.1}/README.md +2 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/pyproject.toml +1 -1
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_launcher.py +14 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_routes_loading.py +2 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_routes_query.py +15 -1
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_viewer.html +2795 -814
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_api.py +46 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_browser.py +521 -29
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_cli.py +29 -0
- arrayview-0.51.1/tests/test_glides.py +166 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_mode_roundtrip.py +5 -1
- arrayview-0.51.1/tests/test_pane_names.py +512 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/.gitignore +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/LICENSE +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/ARCHITECTURE.md +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/__init__.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/__main__.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_analysis.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_app.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_bootstrap_app.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_config.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_diagnostics.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_dicom.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_diff.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_extra_ports.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_icon.png +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_imaging.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_instance_registry.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_io.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_launch_plan.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_launch_trace.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_lifecycle.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_overlays.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_platform.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_render.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_routes_analysis.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_routes_drop.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_routes_export.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_routes_persistence.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_routes_preferences.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_routes_preload.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_routes_rendering.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_routes_segmentation.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_routes_state.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_routes_vectorfield.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_routes_websocket.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_segmentation.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_server.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_session.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_session_spec.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_shell.html +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_source_safety.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_synthetic_mri.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_torch.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_tutorial.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_vectorfield.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_view_memory.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_vscode.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_vscode_browser.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_vscode_extension.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_vscode_signal.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/_watch.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/arrayview-opener.vsix +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/gsap.min.js +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/src/arrayview/todo.md +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/capture_patient_loading.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/capture_v_animation.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/conftest.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/make_vectorfield_test_arrays.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_1d_arrays.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_backend_shared.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_config.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_dicom.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_drop_import.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_instance_registry.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_io.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_large_arrays.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_launch_blackbox.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_nifti_meta.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_nifti_series.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_rgb_pixel_art.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_safe_server_stop.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_source_safety.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_torch.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_tutorial.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_view_memory.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/test_vsix_bundle.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/ui_audit.py +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/v_anim_frames/.gitkeep +0 -0
- {arrayview-0.51.0 → arrayview-0.51.1}/tests/visual_smoke.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: arrayview
|
|
3
|
-
Version: 0.51.
|
|
3
|
+
Version: 0.51.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
|
|
@@ -39,6 +39,8 @@ Description-Content-Type: text/markdown
|
|
|
39
39
|
|
|
40
40
|
_This is my array viewer. There are many like it, but this one is mine._
|
|
41
41
|
|
|
42
|
+
<img src="docs/teaser.gif" alt="ArrayView: scrolling a volume, switching colormaps, three planes, and a difference view" width="800">
|
|
43
|
+
|
|
42
44
|
Arrayview lets you scroll through multi-dimensional arrays.
|
|
43
45
|
|
|
44
46
|
Open it from the shell, from Python, Julia, or Matlab, or inside a Jupyter notebook. Use it locally or over SSH.
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
_This is my array viewer. There are many like it, but this one is mine._
|
|
4
4
|
|
|
5
|
+
<img src="docs/teaser.gif" alt="ArrayView: scrolling a volume, switching colormaps, three planes, and a difference view" width="800">
|
|
6
|
+
|
|
5
7
|
Arrayview lets you scroll through multi-dimensional arrays.
|
|
6
8
|
|
|
7
9
|
Open it from the shell, from Python, Julia, or Matlab, or inside a Jupyter notebook. Use it locally or over SSH.
|
|
@@ -1323,6 +1323,7 @@ def _load_session_from_filepath(
|
|
|
1323
1323
|
dir_exclude_cases: list[str] | None = None,
|
|
1324
1324
|
collection_load: str = "lazy",
|
|
1325
1325
|
collection_stack: str = "auto",
|
|
1326
|
+
collection_keep_order: bool = False,
|
|
1326
1327
|
background: bool = False,
|
|
1327
1328
|
expected_server_id: str | None = None,
|
|
1328
1329
|
native_request_id: str | None = None,
|
|
@@ -1365,6 +1366,7 @@ def _load_session_from_filepath(
|
|
|
1365
1366
|
payload["dir_exclude_cases"] = dir_exclude_cases or []
|
|
1366
1367
|
payload["load"] = collection_load
|
|
1367
1368
|
payload["stack"] = collection_stack
|
|
1369
|
+
payload["keep_order"] = collection_keep_order
|
|
1368
1370
|
if notify and compare_sids:
|
|
1369
1371
|
payload["compare_sid"] = compare_sids[0]
|
|
1370
1372
|
payload["compare_sids"] = _join_query_values(compare_sids)
|
|
@@ -1686,6 +1688,7 @@ def _register_cli_session_with_existing_server_impl(
|
|
|
1686
1688
|
dir_exclude_cases: list[str] | None = None,
|
|
1687
1689
|
collection_load: str = "lazy",
|
|
1688
1690
|
collection_stack: str = "auto",
|
|
1691
|
+
collection_keep_order: bool = False,
|
|
1689
1692
|
overlay_names: list[str] | None = None,
|
|
1690
1693
|
background_base: bool = False,
|
|
1691
1694
|
expected_server_id: str | None = None,
|
|
@@ -1741,6 +1744,7 @@ def _register_cli_session_with_existing_server_impl(
|
|
|
1741
1744
|
dir_exclude_cases=dir_exclude_cases,
|
|
1742
1745
|
collection_load=collection_load,
|
|
1743
1746
|
collection_stack=collection_stack,
|
|
1747
|
+
collection_keep_order=collection_keep_order,
|
|
1744
1748
|
background=background_base,
|
|
1745
1749
|
expected_server_id=expected_server_id,
|
|
1746
1750
|
native_request_id=native_request_id,
|
|
@@ -1838,6 +1842,7 @@ def _handle_cli_existing_server(
|
|
|
1838
1842
|
dir_exclude_cases: list[str] | None = None,
|
|
1839
1843
|
collection_load: str = "lazy",
|
|
1840
1844
|
collection_stack: str = "auto",
|
|
1845
|
+
collection_keep_order: bool = False,
|
|
1841
1846
|
overlay_names: list[str] | None = None,
|
|
1842
1847
|
cleanup_dir: str | None = None,
|
|
1843
1848
|
source_staging_dirs: dict[str, str] | None = None,
|
|
@@ -1866,6 +1871,7 @@ def _handle_cli_existing_server(
|
|
|
1866
1871
|
dir_exclude_cases=dir_exclude_cases,
|
|
1867
1872
|
collection_load=collection_load,
|
|
1868
1873
|
collection_stack=collection_stack,
|
|
1874
|
+
collection_keep_order=collection_keep_order,
|
|
1869
1875
|
overlay_names=overlay_names,
|
|
1870
1876
|
background_base=(
|
|
1871
1877
|
is_remote
|
|
@@ -1954,6 +1960,7 @@ def _handle_cli_existing_server(
|
|
|
1954
1960
|
dir_exclude_cases=dir_exclude_cases,
|
|
1955
1961
|
collection_load=collection_load,
|
|
1956
1962
|
collection_stack=collection_stack,
|
|
1963
|
+
collection_keep_order=collection_keep_order,
|
|
1957
1964
|
overlay_names=overlay_names,
|
|
1958
1965
|
source_staging_dirs=source_staging_dirs,
|
|
1959
1966
|
)
|
|
@@ -2084,6 +2091,7 @@ def _handle_cli_spawned_daemon(
|
|
|
2084
2091
|
dir_exclude_cases: list[str] | None = None,
|
|
2085
2092
|
collection_load: str = "lazy",
|
|
2086
2093
|
collection_stack: str = "auto",
|
|
2094
|
+
collection_keep_order: bool = False,
|
|
2087
2095
|
overlay_names: list[str] | None = None,
|
|
2088
2096
|
cleanup_dir: str | None = None,
|
|
2089
2097
|
source_staging_dirs: dict[str, str] | None = None,
|
|
@@ -2147,6 +2155,7 @@ def _handle_cli_spawned_daemon(
|
|
|
2147
2155
|
dir_exclude_cases=dir_exclude_cases,
|
|
2148
2156
|
collection_load=collection_load,
|
|
2149
2157
|
collection_stack=collection_stack,
|
|
2158
|
+
collection_keep_order=collection_keep_order,
|
|
2150
2159
|
overlay_names=resolved_overlay_names,
|
|
2151
2160
|
cleanup_dir=cleanup_dir,
|
|
2152
2161
|
source_staging_dirs=source_staging_dirs,
|
|
@@ -2202,6 +2211,7 @@ def _handle_cli_spawned_daemon(
|
|
|
2202
2211
|
f" dir_exclude_cases={repr(dir_exclude_cases)},"
|
|
2203
2212
|
f" collection_load={repr(collection_load)},"
|
|
2204
2213
|
f" collection_stack={repr(collection_stack)},"
|
|
2214
|
+
f" collection_keep_order={repr(collection_keep_order)},"
|
|
2205
2215
|
f" cleanup_dir={repr(cleanup_dir)},"
|
|
2206
2216
|
f" source_staging_dirs={repr(source_staging_dirs or {})},"
|
|
2207
2217
|
f" watch={watch},"
|
|
@@ -4729,6 +4739,7 @@ def _serve_daemon(
|
|
|
4729
4739
|
dir_exclude_cases: list[str] | None = None,
|
|
4730
4740
|
collection_load: str = "lazy",
|
|
4731
4741
|
collection_stack: str = "auto",
|
|
4742
|
+
collection_keep_order: bool = False,
|
|
4732
4743
|
cleanup_dir: str | None = None,
|
|
4733
4744
|
source_staging_dirs: dict[str, str] | None = None,
|
|
4734
4745
|
watch: bool = False,
|
|
@@ -4868,6 +4879,7 @@ def _serve_daemon(
|
|
|
4868
4879
|
exclude_cases=dir_exclude_cases,
|
|
4869
4880
|
load=collection_load,
|
|
4870
4881
|
stack=collection_stack,
|
|
4882
|
+
keep_order=collection_keep_order,
|
|
4871
4883
|
)
|
|
4872
4884
|
collection_spatial_ndim = len(_summary["spatial_shape"])
|
|
4873
4885
|
elif (filepath.endswith(".npz") or filepath.endswith(".mat")) and not cleanup:
|
|
@@ -6706,6 +6718,7 @@ def arrayview():
|
|
|
6706
6718
|
dir_exclude_cases=sorted(excluded_cases),
|
|
6707
6719
|
collection_load=args.load,
|
|
6708
6720
|
collection_stack=args.stack_policy or "auto",
|
|
6721
|
+
collection_keep_order=getattr(args, "keep_file_order", False),
|
|
6709
6722
|
cleanup_dir=getattr(args, "_tutorial_cleanup_dir", None),
|
|
6710
6723
|
source_staging_dirs=(
|
|
6711
6724
|
source_staging_dirs if not args.stack_mode else None
|
|
@@ -6746,6 +6759,7 @@ def arrayview():
|
|
|
6746
6759
|
dir_exclude_cases=sorted(excluded_cases),
|
|
6747
6760
|
collection_load=args.load,
|
|
6748
6761
|
collection_stack=args.stack_policy or "auto",
|
|
6762
|
+
collection_keep_order=getattr(args, "keep_file_order", False),
|
|
6749
6763
|
source_staging_dirs=(
|
|
6750
6764
|
source_staging_dirs if not args.stack_mode else None
|
|
6751
6765
|
),
|
|
@@ -227,6 +227,7 @@ def register_loading_routes(app, *, notify_shells, setup_rgb) -> None:
|
|
|
227
227
|
tuple(str(case) for case in body.get("dir_exclude_cases", [])),
|
|
228
228
|
body.get("load", "lazy"),
|
|
229
229
|
body.get("stack", "auto"),
|
|
230
|
+
bool(body.get("keep_order", False)),
|
|
230
231
|
)
|
|
231
232
|
for existing in [] if requested_sid else SESSIONS.values():
|
|
232
233
|
if getattr(existing, "collection_identity", None) == collection_identity:
|
|
@@ -440,6 +441,7 @@ def register_loading_routes(app, *, notify_shells, setup_rgb) -> None:
|
|
|
440
441
|
exclude_cases=body.get("dir_exclude_cases", []),
|
|
441
442
|
load=body.get("load", "lazy"),
|
|
442
443
|
stack=body.get("stack", "auto"),
|
|
444
|
+
keep_order=bool(body.get("keep_order", False)),
|
|
443
445
|
)
|
|
444
446
|
elif filepath.endswith(".npz") or filepath.endswith(".mat"):
|
|
445
447
|
_array_keys = await asyncio.to_thread(list_array_keys, filepath)
|
|
@@ -429,7 +429,7 @@ def register_query_routes(app, *, get_session_or_404, pil_image, pil_imageops) -
|
|
|
429
429
|
info["overlay_labels"] = []
|
|
430
430
|
try:
|
|
431
431
|
if np.issubdtype(session.data.dtype, np.integer):
|
|
432
|
-
labels = np.unique(session
|
|
432
|
+
labels = np.unique(_overlay_label_sample(session))
|
|
433
433
|
labels = labels[labels > 0]
|
|
434
434
|
if labels.size <= 16:
|
|
435
435
|
info["overlay_labels"] = [int(value) for value in labels]
|
|
@@ -531,6 +531,18 @@ def register_query_routes(app, *, get_session_or_404, pil_image, pil_imageops) -
|
|
|
531
531
|
)
|
|
532
532
|
|
|
533
533
|
|
|
534
|
+
def _overlay_label_sample(session):
|
|
535
|
+
"""Overlay values to read label ids from: the whole array, or only the
|
|
536
|
+
first case of a collection (reading every case would stall opening; the
|
|
537
|
+
viewer adds labels found in other cases as they are visited)."""
|
|
538
|
+
spatial = getattr(session, "collection_spatial_ndim", None)
|
|
539
|
+
shape = tuple(session.shape)
|
|
540
|
+
if spatial is None or not (0 < spatial < len(shape)):
|
|
541
|
+
return np.asarray(session.data)
|
|
542
|
+
index = (slice(None),) * spatial + (0,) * (len(shape) - spatial)
|
|
543
|
+
return np.asarray(session.data[index])
|
|
544
|
+
|
|
545
|
+
|
|
534
546
|
def _overlay_slice_counts(ov_session, base_shape, dim_x, dim_y, axis, idx_list):
|
|
535
547
|
"""Count overlay pixels per label on every slice along ``axis``."""
|
|
536
548
|
n = int(base_shape[axis])
|
|
@@ -555,6 +567,8 @@ def _overlay_slice_counts(ov_session, base_shape, dim_x, dim_y, axis, idx_list):
|
|
|
555
567
|
return empty
|
|
556
568
|
kept = [a for a in base_axes if a in (dim_x, dim_y, axis)]
|
|
557
569
|
if axis in kept:
|
|
570
|
+
# Ragged collections return this case's own size, not the max-shape facade.
|
|
571
|
+
n = int(vol.shape[kept.index(axis)])
|
|
558
572
|
vol = np.moveaxis(vol, kept.index(axis), 0).reshape(n, -1)
|
|
559
573
|
else:
|
|
560
574
|
# The overlay has no such axis: it looks the same on every slice.
|