No project description provided
Project description
Napari Plugin napari-npifile
Allows reading and writing of .npi files.
.npi files are essentially NumPy arrays packaged together with JSON metadata that
stores napari viewer and layer configuration, such as axis names or colormaps.
The goal is to keep the simplicity of .npy files while preserving useful visualization
settings when opening arrays in napari.
Quick Example
import napari_npifile
import numpy as np
data = np.random.random(size=(10, 20, 30, 40))
# save it without napari metadata
np.save("quick_example.npy", data)
# save it with napari metadata
napari_npifile.write_npi(
"quick_example.npi",
data=data,
layer_attributes={
"name": "foo",
"colormap": "magma",
"contrast_limits": (-0.25, 1.25),
},
viewer_settings={
"axis_labels": ["T", "Z", "Y", "X"],
"scale_bar_properties": {"visible": True, "unit": "px", "font_size": 40.0},
},
)
# and drag and drop it into napari
# |
# |
# v
Motivation
When working on image analysis tasks in Python it is common to save temporary NumPy arrays such as:
- image stacks
- neural network tensors
- intermediate processing results
- ...
to .npy files, which can easily be opened in napari via
drag-and-drop.
However, .npy files contain no visualization metadata. Each time a file is opened,
display settings (colormap, contrast limits, etc.) must be configured manually.
.npi files solve this by storing the arrays together with napari viewer metadata.
Installation
pip install --upgrade napari-npifile
Note: napari is not included as a dependency, to allow writing .npi files
even if napari is not installed (e.g., on headless servers).
To view .npi files in napari, you must install napari separately:
pip install napari
See the napari installation instructions for details.
Usage
Reading .npi files in napari
Once napari-npifile is installed, .npi files can be opened in napari like any other
supported format:
- via drag-and-drop,
- via the
File -> Openmenu, - via the napari console using
viewer.open("myfile.npi", plugin="napari-npifile"), or - programmatically using:
import napari viewer = napari.Viewer() viewer.open("myfile.npi", plugin="napari-npifile") napari.run()
When loaded, each layer in the .npi file becomes a separate napari layer. Layer
settings (colormap, contrast limits, gamma, name, etc.) and viewer settings (axis
labels, camera settings, scale bar settings, etc.) are applied automatically.
Writing .npi files from Python (no napari required)
napari-npifile provides a main writer class NpiWriter_v1 for full control, as well
as the convenience wrappers write_npi, write_multilayer_npi into a .npi file.
When to use what:
The convenience wrapper functions (write_npi, write_multilayer_npi) are useful for
cases where all the data to be stored is available upfront. Use write_npi for writing
a single layer and write_multilayer_npi for multiple layers.
The class NpiWriter_v1 allows to incrementally write layers into a single .npi
file over time, making it ideal for loops.
Convenience wrapper write_npi (single-layer):
import napari_npifile
import numpy as np
data = np.random.random((10, 20, 30))
napari_npifile.write_npi(
"single.npi",
data=data,
layer_attributes={"name": "layer0", "colormap": "magma"},
viewer_settings={"axis_labels": ["Z", "Y", "X"]},
)
Convenience wrapper write_multilayer_npi (multi-layer):
import napari_npifile
import numpy as np
data_seq = [
np.random.random((10, 20, 30)),
np.random.random((10, 20, 30)),
]
layer_attributes_seq = [
{"name": "first", "colormap": "gray"},
{"name": "second", "colormap": "green"},
]
napari_npifile.write_multilayer_npi(
"multi.npi",
data_seq=data_seq,
layer_attributes_seq=layer_attributes_seq,
viewer_settings={"axis_labels": ["Z", "Y", "X"]},
)
Full general example using NpiWriter_v1:
import napari_npifile
import numpy as np
# prepare writer
writer = napari_npifile.NpiWriter_v1(
out_path="out.npi",
exist_ok=True,
)
# viewer settings are saved once and are used for all layers
writer.write_viewer_settings(
{
"axis_labels": ["T", "K", "Z", "Y", "X"],
"grid_properties": {"enabled": True, "shape": (1, -1), "stride": 1, "spacing": 0.1},
"scale_bar_properties": {"visible": True, "unit": "px", "gridded": True},
}
)
# layers are written one at a time, each with individual attributes
data1 = np.random.random(size=(3, 10, 20, 30, 40))
writer.write_layer(data=data1, attributes={"colormap": "cyan", "name": "foo"})
data2 = np.random.random(size=(1, 10, 20, 30, 40))
writer.write_layer(data=data2, attributes={"colormap": "green", "name": "bar"})
File Format
Overview
.npi files are ZIP archives containing raw NumPy array data (stored
as .npy files) together with napari viewer and layer metadata stored as JSON files.
Versions
Every .npi file contains a root metadata.json with a mandatory "npi_format"
field. This format versioning ensures backward compatibility: the reader uses it to
select the appropriate parser for each format.
In addition, the class NpiWriter_v1 will remain indefinitely to ensure backward
compatibility. If a new .npi format version is introduced, a new writer class will be
added alongside it, leaving existing code using NpiWriter_v1 fully functional.
Version history:
| Format Version | napari-npifile version |
Comment |
|---|---|---|
v1 |
0.1.0+ |
Initial version, current format. Supports single- and multi-layer .npi files with full napari image layer metadata and a subset of viewer settings. |
Current Version Details (v1)
Archive Layout
example.npi # this is just a ZIP archive
├── metadata.json # contains {"npi_format": "v1"}
├── viewer_settings.json # dictionary with global viewer settings - see below
└── layers
├── 00000000 # each layer is stored under a sequential numeric key
│ ├── data.npy # NumPy array as saved via np.save
│ └── attributes.json # layer attributes (as in napari.layers.Image)
└── 00000001
├── data.npy
└── attributes.json
Metadata
All metadata files are JSON files which contain a dictionary.
File metadata.json
Only contains {"npi_format": "v1"}.
It is used by the reader to select the correct parser for the file.
File viewer_settings.json
Stores global napari viewer settings. All fields are optional; if missing, the reader does not change the current napari configuration.
| Field | Type | Notes |
|---|---|---|
clear_existing_layers |
bool |
If True, removes all existing layers before adding new ones |
hide_existing_layers |
bool |
If True, hides all existing layers before adding new ones |
title |
str |
Napari window title |
ndisplay |
int |
2 or 3 (for 2D or 3D mode) |
axis_labels |
list[str] |
One label per axis (e.g., ["T", "Z", "Y", "X"]) |
dims_set_point |
dict |
Optional subfields as in napari's set_point, i.e. axis: int or Sequence[int] and value: float or Sequence[float] |
camera_properties |
dict |
Optional subfields as in napari's Camera (e.g., {"center": (0.0, 10.0, 20.0)}) |
grid_properties |
dict |
Optional subfields as in napari's GridCanvas (enabled: bool, shape: tuple[int, int], stride: int, spacing: float) |
scale_bar_properties |
dict |
Optional subfields as in napari's ScaleBarOverlay (e.g., visible: bool, unit: str, gridded: bool) |
text_overlay_properties |
dict |
Optional subfields as in napari's TextOverlay (e.g., visible: bool, text: str, gridded: bool, font_size: float) |
File(s) layers/*/attributes.json
Layer-specific settings for each layer. All fields are optional; if missing, the reader uses napari defaults.
Any keyword argument accepted by napari’s Image layer
(except data), e.g.:
name: strcolormap: str(any napari colormap)contrast_limits: tuple[float, float]gamma: floatblending: str ("translucent", "additive", "opaque", ...)- ...
Design Principles and Limitations
Key principles for the .npi format and napari-npifile are:
- Simplicity and accessibility:
.npifiles are standard ZIP archives containing NumPy arrays and JSON metadata. Thus, the files can easily be inspected, read, and created even without this library. - Minimal dependencies: Only NumPy and napari (for viewing) are required.
- Tight napari integration:
.npistores viewer and layer settings exclusively for napari, and thus allows fine-grained control over how arrays are displayed. - Backward compatibility: Every
.npiincludes a format version, ensuring future readers can correctly handle older files. - Headless-friendly writing:
.npifiles can be created without napari installed, which is useful for server-side or automated workflows.
These design choices naturally impose some limitations:
- No access optimization:
.npiuses plainnp.save/np.loadfrom ZIP archives and thus can't compete with optimized formats for large arrays. - No compression:
.npistores raw arrays; large datasets may consume significant disk space. - Viewer-centric metadata: Metadata is tailored specifically to napari; other viewers or tools require extra work to interpret it.
In short, .npi prioritizes simplicity and tight napari integration over maximal
performance. Users needing advanced storage features or highly
efficient random access may prefer formats such as Zarr or
HDF5, while
OME-TIFF provides more generic
metadata handling.
Known Issues
- Setting the viewer slice position (
viewer.dims.set_point) and camera properties does not work when there are no pre-existing layers or whenclear_existing_layersisTrue.
Todo / Ideas
- Add support to write
.npifiles directly from napari. - Add CLI to convert existing
.npyfiles to.npifiles (and back).
Related Discussions / Projects
- napari GitHub issue: Changing viewer dimension when adding a new layer #6127
- image.sc forum: Saving volumetric data with voxel size, colormap, annotations
License
napari-npifile is released under the MIT License. See LICENSE.txt for full details.
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 napari_npifile-0.1.0.tar.gz.
File metadata
- Download URL: napari_npifile-0.1.0.tar.gz
- Upload date:
- Size: 17.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.11 {"installer":{"name":"uv","version":"0.9.11"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
379d5130239807151694fe72530025291a8eb35c34e3b83583c2e0a124d986b4
|
|
| MD5 |
1d9942824c9916075f11f9acd7104466
|
|
| BLAKE2b-256 |
24d1f03a4993891667f2002c625457d6652ad53736d618ef4338382c3055e1f8
|
File details
Details for the file napari_npifile-0.1.0-py3-none-any.whl.
File metadata
- Download URL: napari_npifile-0.1.0-py3-none-any.whl
- Upload date:
- Size: 12.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.11 {"installer":{"name":"uv","version":"0.9.11"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a9452229eef2b137faf94968983933879311c79b9e1a29c6eee0772ff7447aff
|
|
| MD5 |
fcf462d58979cc72edc381b74a0fcc5c
|
|
| BLAKE2b-256 |
2e8245924d1c625c24658a470bf11faec5144d0bdcf9b524f61c1b98ff8bf7d3
|