Minimal ndarray viewer for Jupyter notebooks, for interactive exploration of image data in notebooks.
Project description
notebook-nd-viewer
notebook-nd-viewer provides a small, copyable ndarray image viewer for
Jupyter notebooks. It is intended for quick interactive inspection of 2D images,
Z-stacks, and channel images without introducing a full image-viewer application
into an analysis notebook.
The public Python import package is nb_nd_viewer.
Features
- Display 2D image planes from NumPy-compatible arrays.
- Use axis labels to browse stack dimensions with notebook sliders.
- Mark one axis as channels with
Cand inspect channels individually, as RGB overlays, or side by side. - Configure channel names and Matplotlib-compatible channel colors.
- Adjust display contrast with absolute min/max or percentile thresholds.
- Overlay binary masks or integer labels with independent label display settings.
- Downsample large rendered planes by default to keep notebook interaction responsive.
Display controls only affect rendering. They do not modify, mask, or rescale the source array.
Installation
From another project, install the package into an environment that can run Jupyter widgets:
uv add notebook-nd-viewer
Or with pip:
pip install notebook-nd-viewer
Do not run either command from inside this repository: uv add records a
dependency in the current project, and a project should not install itself as a
dependency.
For local development inside this repository:
git clone https://github.com/Darlokt/notebook-nd-viewer.git
cd notebook-nd-viewer
uv sync --dev
If you use classic Notebook, JupyterLab, VS Code notebooks, or another frontend,
make sure that ipywidgets is enabled for that environment.
Usage
import numpy as np
from nb_nd_viewer import view_image_layers, view_labeled_image
image = np.random.default_rng(0).normal(size=(12, 256, 256))
view_image_layers(image, axis_order="ZYX")
axis_order must contain one label per array dimension. When both Y and X
are present, they are rendered as the image plane with Y as rows and X as
columns, no matter where they appear in axis_order. Other non-channel axes
become layer sliders.
If either Y or X is missing, the viewer falls back to positional behavior:
the last two non-channel axes are rendered in their listed order, and earlier
non-channel axes become layer sliders. This keeps arbitrary labels such as AB,
TZR, or labels with only one of Y/X working as before.
For channel data, mark the channel axis with C:
image = np.random.default_rng(0).normal(size=(8, 3, 256, 256))
view_image_layers(
image,
axis_order="ZCYX",
channel_names=("DAPI", "Actin", "Tubulin"),
channel_colors=("blue", "green", "magenta"),
)
axis_order="ZCXY" also renders rows as Y and columns as X; only the
underlying array-axis positions differ.
Large image planes are downsampled before rendering by default:
view_image_layers(
image,
axis_order="ZCYX",
max_render_pixels=1_000_000,
render_downsampling="stride",
)
Set max_render_pixels=None or render_downsampling="none" to render every
source pixel.
Use view_labeled_image to inspect images with label overlays:
image = np.random.default_rng(0).normal(size=(8, 3, 256, 256))
labels = np.zeros((256, 256), dtype=bool)
labels[80:180, 90:190] = True
view_labeled_image(
image,
axis_order="ZCYX",
labels=labels,
label_axis_order="YX",
channel_names=("DAPI", "Actin", "Tubulin"),
label_names=("Region",),
)
Label arrays may omit image stack axes. In the example above, the 2D YX mask
is overlaid on every Z slice. Multiple binary masks can be stored in one label
array by marking a label channel axis with C:
labels = np.zeros((2, 256, 256), dtype=bool)
labels[0, 80:180, 90:190] = True
labels[1, 100:140, 120:220] = True
view_labeled_image(
image,
axis_order="ZCYX",
labels=labels,
label_axis_order="CYX",
label_names=("Nuclei", "Cells"),
label_colors=("cyan", "magenta"),
label_opacities=(0.4, 0.6),
)
Integer labels are rendered with categorical colors from tab20 by default,
with label value 0 treated as transparent background:
instance_labels = np.zeros((256, 256), dtype=np.uint16)
instance_labels[40:100, 40:100] = 1
instance_labels[130:210, 150:230] = 2
view_labeled_image(
image,
axis_order="ZCYX",
labels=instance_labels,
label_axis_order="YX",
label_names=("Instances",),
integer_label_cmap="tab20",
)
Label overlays use the same render pixel budget as image planes, but labels are always downsampled with nearest-neighbor sampling so binary masks and integer IDs remain categorical.
API
view_image_layers(
image,
axis_order,
channel_names=None,
channel_colors=None,
figsize=(6, 6),
cmap="gray",
*,
continuous_update=False,
max_render_pixels=1_000_000,
render_downsampling="stride",
)
view_labeled_image(
image,
axis_order,
labels=None,
label_axis_order=None,
channel_names=None,
label_names=None,
label_colors=None,
label_opacities=0.5,
label_kinds="auto",
figsize=(6, 6),
cmap="gray",
integer_label_cmap="tab20",
*,
continuous_update=False,
max_render_pixels=1_000_000,
render_downsampling="stride",
)
Parameters:
image: NumPy-compatible image array.axis_order: axis labels matchingimage.ndim; useCfor the optional channel axis. When bothYandXare present, they define image rows and columns; otherwise the last two non-channel axes are rendered.channel_names: optional names for the channel axis.channel_colors: optional Matplotlib-compatible colors for channel rendering.figsize: Matplotlib figure size used before notebook scaling.cmap: colormap for non-channel images.continuous_update: redraw continuously while dragging sliders whenTrue.max_render_pixels: maximum rendered pixels per 2D plane; useNoneto disable pixel-count based downsampling.render_downsampling: one of"stride","nearest","bilinear","bicubic", or"none".
Additional view_labeled_image parameters:
labels: optional bool or integer label array.label_axis_order: axis labels matchinglabels.ndim; required when labels are provided. UseCfor a label channel axis.label_names: optional names for expanded label entries.label_colors: optional Matplotlib-compatible colors for binary label rendering.label_opacities: one opacity for all labels or one value per label.label_kinds:"auto","binary", or"integer"for all labels, or one value per label.integer_label_cmap: Matplotlib colormap used for integer label IDs.
Development
This project uses uv for dependency management:
uv sync
Run the main quality gates before submitting changes:
uv run ruff format src tests notebooks
uv run ruff check src tests notebooks
uv run ty check
uv run pytest
The default pytest configuration runs unit and integration tests while excluding
tests marked external. Tests under tests/unit/ and tests/integration/ are
marked automatically from their path, so focused runs can use:
uv run pytest -m unit
uv run pytest -m integration
Coverage is configured with a 90% minimum:
uv run pytest --cov
Install the repository's pre-commit hooks with:
uv run prek install
Project Layout
notebook-nd-viewer/
├── src/nb_nd_viewer/ # importable package and private viewer helpers
├── tests/unit/ # focused unit tests
├── tests/integration/ # public API and workflow tests
├── notebooks/ # Example notebooks
├── pyproject.toml # package metadata and tool configuration
└── uv.lock # locked development environment
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file notebook_nd_viewer-0.3.0.tar.gz.
File metadata
- Download URL: notebook_nd_viewer-0.3.0.tar.gz
- Upload date:
- Size: 21.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
706b06fce848e7187ffd9719ddbc88639b5d8069e9e56ae222d54748018c8d95
|
|
| MD5 |
20121773d35d12c632fa8c278147c623
|
|
| BLAKE2b-256 |
7e806de865f71ccf4ed2d82decbe12a9d8f17c452e674d397cd497c3d826ae55
|
Provenance
The following attestation bundles were made for notebook_nd_viewer-0.3.0.tar.gz:
Publisher:
publish.yml on Darlokt/notebook-nd-viewer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
notebook_nd_viewer-0.3.0.tar.gz -
Subject digest:
706b06fce848e7187ffd9719ddbc88639b5d8069e9e56ae222d54748018c8d95 - Sigstore transparency entry: 1649824374
- Sigstore integration time:
-
Permalink:
Darlokt/notebook-nd-viewer@475e806e68770c8fd1257049ed5fc54dd376df58 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/Darlokt
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@475e806e68770c8fd1257049ed5fc54dd376df58 -
Trigger Event:
push
-
Statement type:
File details
Details for the file notebook_nd_viewer-0.3.0-py3-none-any.whl.
File metadata
- Download URL: notebook_nd_viewer-0.3.0-py3-none-any.whl
- Upload date:
- Size: 28.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dfab5bce8d9384dc70184db5a767645458e13f35fd3ae139264a9bd1424dc270
|
|
| MD5 |
91f0b4e47f894e67d6462eab560e2319
|
|
| BLAKE2b-256 |
e73421b16026f0ddee79aba7ffe64309991918e24785a2fc9480f95db697f431
|
Provenance
The following attestation bundles were made for notebook_nd_viewer-0.3.0-py3-none-any.whl:
Publisher:
publish.yml on Darlokt/notebook-nd-viewer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
notebook_nd_viewer-0.3.0-py3-none-any.whl -
Subject digest:
dfab5bce8d9384dc70184db5a767645458e13f35fd3ae139264a9bd1424dc270 - Sigstore transparency entry: 1649824508
- Sigstore integration time:
-
Permalink:
Darlokt/notebook-nd-viewer@475e806e68770c8fd1257049ed5fc54dd376df58 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/Darlokt
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@475e806e68770c8fd1257049ed5fc54dd376df58 -
Trigger Event:
push
-
Statement type: