Contribution Guides
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
The LayerData tuple¶
When transfering 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.
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 contructor
(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'
)