Plugin contributions#
This page provides guides on many of the plugin contribution patterns. Each provides a general overview of the purpose of the contribution and an example implementation. For details on the type and meaning of each field in a specific contribution, See the contributions reference
This is a stub. The real file is autogenerated in a full build.
This is a stub. The real file is autogenerated in a full build.
This is a stub. The real file is autogenerated in a full build.
This is a stub. The real file is autogenerated in a full build.
The LayerData tuple#
When transferring data to and from plugins, napari does not pass Layer
objects
directly. Instead, it passes (mostly) pure-python and array-like types,
deconstructed into a tuple
that we refer to as a LayerData
tuple. This type shows
up often in plugins and is explained here.
Note that when writing your own plugin, type annotations are optional,
except in the case of magicgui
function widgets.
For several types related to LayerData
tuples, napari defines a type alias
which better indicates a value’s functional role in a plugin.
We describe these below.
Informal description#
(data, [attributes, [layer_type]])
A LayerData
tuple is a tuple of length 1, 2, or 3 whose items, in order, are:
The
data
object that would be used forlayer.data
(such as a numpy array for theImage
layer)(Optional). A
dict
of layer attributes, suitable for passing as keyword arguments to the corresponding layer constructor (e.g.{'opacity': 0.7}
)(Optional). A lower case
str
indicating the layer type (e.g.'image'
,'labels'
, etc…). If not provided (i.e. if the tuple is only of length 2), the layer type is assumed to be'image
’.
Formal type definition#
Formally, the typing for LayerData
looks like this:
LayerData = Union[Tuple[DataType], Tuple[DataType, LayerProps], FullLayerData]
where …
from typing import Literal, Protocol, Sequence
LayerTypeName = Literal[
"image", "labels", "points", "shapes", "surface", "tracks", "vectors"
]
LayerProps = Dict
DataType = Union[ArrayLike, Sequence[ArrayLike]]
FullLayerData = Tuple[DataType, LayerProps, LayerTypeName]
LayerData = Union[Tuple[DataType], Tuple[DataType, LayerProps], FullLayerData]
# where "ArrayLike" is very roughly ...
class ArrayLike(Protocol):
shape: Tuple[int, ...]
ndim: int
dtype: np.dtype
def __array__(self) -> np.ndarray: ...
def __getitem__(self, key) -> ArrayLike: ...
# the main point is that we're more concerned with structural
# typing than literal array types (e.g. numpy, dask, xarray, etc...)
Examples#
Assume that data
is a numpy array:
import numpy as np
data = np.random.rand(64, 64)
All of the following are valid LayerData
tuples:
# the first three are equivalent, just an image array with default settings
(data,)
(data, {})
(data, {}, 'image')
# provide kwargs for image constructor
(data, {'name': 'My Image', 'colormap': 'red'})
# labels layer instead of image:
(data.astype(int), {'name': 'My Labels', 'blending': 'additive'}, 'labels')
Creation from a Layer
instance.#
Note, the as_layer_data_tuple()
method will create a layer data
tuple from a given layer
>>> img = Image(np.random.rand(2, 2), colormap='green', scale=(4, 4))
>>> img.as_layer_data_tuple()
Out[7]:
(
array([[0.94414642, 0.89192899],
[0.21258344, 0.85242735]]),
{
'name': 'Image',
'metadata': {},
'scale': [4.0, 4.0],
'translate': [0.0, 0.0],
'rotate': [[1.0, 0.0], [0.0, 1.0]],
'shear': [0.0],
'opacity': 1,
'blending': 'translucent',
'visible': True,
'experimental_clipping_planes': [],
'rgb': False,
'multiscale': False,
'colormap': 'green',
'contrast_limits': [0.2125834437981784, 0.9441464162780605],
'interpolation': 'nearest',
'rendering': 'mip',
'experimental_slicing_plane': {'normal': (1.0, 0.0, 0.0), 'position': (0.0, 0.0, 0.0), 'enabled': False, 'thickness': 1.0},
'iso_threshold': 0.5,
'attenuation': 0.05,
'gamma': 1
},
'image'
)
Adding to the viewer#
To add a LayerData
tuple to the napari viewer, use :meth:Layer.create
:
>>> image_layer_data = (data, {'name': 'My Image', 'colormap': 'red'}, 'image')
>>> viewer = napari.current_viewer()
>>> viewer.add_layer(napari.layers.Layer.create(*image_layer_data))
The only attribute that can’t be passed to napari.layers.Layer.create
that is otherwise valid for a LayerData
tuple is ‘channel_axis’.