From 5e3fc4f270d852643390f828c3acfd37c08292b8 Mon Sep 17 00:00:00 2001 From: Nicholas Sofroniew Date: Sun, 26 Jan 2020 21:59:20 -0800 Subject: [PATCH] refactor add_* methods (#897) --- napari/components/add_layers_mixin.py | 631 ++++++++++++++++++++++++++ napari/components/viewer_model.py | 617 +------------------------ 2 files changed, 633 insertions(+), 615 deletions(-) create mode 100644 napari/components/add_layers_mixin.py diff --git a/napari/components/add_layers_mixin.py b/napari/components/add_layers_mixin.py new file mode 100644 index 00000000000..5bd89af6f51 --- /dev/null +++ b/napari/components/add_layers_mixin.py @@ -0,0 +1,631 @@ +import itertools +import numpy as np + +from .. import layers +from ..utils import colormaps +from ..utils.misc import ensure_iterable, is_iterable +from ..utils import io + + +class AddLayersMixin: + """A mixin that adds add_* methods for adding layers to the ViewerModel. + + Each method corresponds to adding one or more layers to the viewer. + Methods that just add a single layer contain the keyword arguments and + copies of the documentation from that the layer. These are copied and + pasted instead of being autogenerated because IDEs like PyCharm parse the + source code for docs instead of pulling it up dynamically. + + These methods are separated into a mixin to keep the ViewerModel class + easier to read and make these methods easier to maintain. + """ + + def add_image( + self, + data=None, + *, + channel_axis=None, + rgb=None, + is_pyramid=None, + colormap=None, + contrast_limits=None, + gamma=1, + interpolation='nearest', + rendering='mip', + iso_threshold=0.5, + attenuation=0.5, + name=None, + metadata=None, + scale=None, + translate=None, + opacity=1, + blending=None, + visible=True, + path=None, + ): + """Add an image layer to the layers list. + + Parameters + ---------- + data : array or list of array + Image data. Can be N dimensional. If the last dimension has length + 3 or 4 can be interpreted as RGB or RGBA if rgb is `True`. If a + list and arrays are decreasing in shape then the data is treated as + an image pyramid. + channel_axis : int, optional + Axis to expand image along. + rgb : bool + Whether the image is rgb RGB or RGBA. If not specified by user and + the last dimension of the data has length 3 or 4 it will be set as + `True`. If `False` the image is interpreted as a luminance image. + is_pyramid : bool + Whether the data is an image pyramid or not. Pyramid data is + represented by a list of array like image data. If not specified by + the user and if the data is a list of arrays that decrease in shape + then it will be taken to be a pyramid. The first image in the list + should be the largest. + colormap : str, vispy.Color.Colormap, tuple, dict, list + Colormaps to use for luminance images. If a string must be the name + of a supported colormap from vispy or matplotlib. If a tuple the + first value must be a string to assign as a name to a colormap and + the second item must be a Colormap. If a dict the key must be a + string to assign as a name to a colormap and the value must be a + Colormap. If a list then must be same length as the axis that is + being expanded as channels, and each colormap is applied to each + new image layer. + contrast_limits : list (2,) + Color limits to be used for determining the colormap bounds for + luminance images. If not passed is calculated as the min and max of + the image. If list of lists then must be same length as the axis + that is being expanded and then each colormap is applied to each + image. + gamma : list, float + Gamma correction for determining colormap linearity. Defaults to 1. + If a list then must be same length as the axis that is being + expanded and then each entry in the list is applied to each image. + interpolation : str + Interpolation mode used by vispy. Must be one of our supported + modes. + rendering : str + Rendering mode used by vispy. Must be one of our supported + modes. + iso_threshold : float + Threshold for isosurface. + attenuation : float + Attenuation rate for attenuated maximum intensity projection. + name : str + Name of the layer. + metadata : dict + Layer metadata. + scale : tuple of float + Scale factors for the layer. + translate : tuple of float + Translation values for the layer. + opacity : float + Opacity of the layer visual, between 0.0 and 1.0. + blending : str + One of a list of preset blending modes that determines how RGB and + alpha values of the layer visual get mixed. Allowed values are + {'opaque', 'translucent', and 'additive'}. + visible : bool + Whether the layer visual is currently being displayed. + path : str or list of str + Path or list of paths to image data. Paths can be passed as strings + or `pathlib.Path` instances. + + Returns + ------- + layer : :class:`napari.layers.Image` or list + The newly-created image layer or list of image layers. + """ + if data is None and path is None: + raise ValueError("One of either data or path must be provided") + elif data is not None and path is not None: + raise ValueError("Only one of data or path can be provided") + elif data is None: + data = io.magic_imread(path) + + if channel_axis is None: + if colormap is None: + colormap = 'gray' + if blending is None: + blending = 'translucent' + layer = layers.Image( + data, + rgb=rgb, + is_pyramid=is_pyramid, + colormap=colormap, + contrast_limits=contrast_limits, + gamma=gamma, + interpolation=interpolation, + rendering=rendering, + iso_threshold=iso_threshold, + attenuation=attenuation, + name=name, + metadata=metadata, + scale=scale, + translate=translate, + opacity=opacity, + blending=blending, + visible=visible, + ) + self.add_layer(layer) + return layer + else: + if is_pyramid: + n_channels = data[0].shape[channel_axis] + else: + n_channels = data.shape[channel_axis] + + name = ensure_iterable(name) + + if blending is None: + blending = 'additive' + + if colormap is None: + if n_channels < 3: + colormap = colormaps.MAGENTA_GREEN + else: + colormap = itertools.cycle(colormaps.CYMRGB) + else: + colormap = ensure_iterable(colormap) + + # If one pair of clim values is passed then need to iterate them to + # all layers. + if contrast_limits is not None and not is_iterable( + contrast_limits[0] + ): + contrast_limits = itertools.repeat(contrast_limits) + else: + contrast_limits = ensure_iterable(contrast_limits) + + gamma = ensure_iterable(gamma) + + layer_list = [] + zipped_args = zip( + range(n_channels), colormap, contrast_limits, gamma, name + ) + for i, cmap, clims, _gamma, name in zipped_args: + if is_pyramid: + image = [ + np.take(data[j], i, axis=channel_axis) + for j in range(len(data)) + ] + else: + image = np.take(data, i, axis=channel_axis) + layer = layers.Image( + image, + rgb=rgb, + colormap=cmap, + contrast_limits=clims, + gamma=_gamma, + interpolation=interpolation, + rendering=rendering, + name=name, + metadata=metadata, + scale=scale, + translate=translate, + opacity=opacity, + blending=blending, + visible=visible, + ) + self.add_layer(layer) + layer_list.append(layer) + return layer_list + + def add_points( + self, + data=None, + *, + symbol='o', + size=10, + edge_width=1, + edge_color='black', + face_color='white', + n_dimensional=False, + name=None, + metadata=None, + scale=None, + translate=None, + opacity=1, + blending='translucent', + visible=True, + ): + """Add a points layer to the layers list. + + Parameters + ---------- + data : array (N, D) + Coordinates for N points in D dimensions. + symbol : str + Symbol to be used for the point markers. Must be one of the + following: arrow, clobber, cross, diamond, disc, hbar, ring, + square, star, tailed_arrow, triangle_down, triangle_up, vbar, x. + size : float, array + Size of the point marker. If given as a scalar, all points are made + the same size. If given as an array, size must be the same + broadcastable to the same shape as the data. + edge_width : float + Width of the symbol edge in pixels. + edge_color : str, array-like + Color of the point marker border. Numeric color values should be RGB(A). + face_color : str, array-like + Color of the point marker body. Numeric color values should be RGB(A). + n_dimensional : bool + If True, renders points not just in central plane but also in all + n-dimensions according to specified point marker size. + name : str + Name of the layer. + metadata : dict + Layer metadata. + scale : tuple of float + Scale factors for the layer. + translate : tuple of float + Translation values for the layer. + opacity : float + Opacity of the layer visual, between 0.0 and 1.0. + blending : str + One of a list of preset blending modes that determines how RGB and + alpha values of the layer visual get mixed. Allowed values are + {'opaque', 'translucent', and 'additive'}. + visible : bool + Whether the layer visual is currently being displayed. + + Returns + ------- + layer : :class:`napari.layers.Points` + The newly-created points layer. + + Notes + ----- + See vispy's marker visual docs for more details: + http://api.vispy.org/en/latest/visuals.html#vispy.visuals.MarkersVisual + """ + if data is None: + ndim = max(self.dims.ndim, 2) + data = np.empty([0, ndim]) + + layer = layers.Points( + data=data, + symbol=symbol, + size=size, + edge_width=edge_width, + edge_color=edge_color, + face_color=face_color, + n_dimensional=n_dimensional, + name=name, + metadata=metadata, + scale=scale, + translate=translate, + opacity=opacity, + blending=blending, + visible=visible, + ) + self.add_layer(layer) + return layer + + def add_labels( + self, + data=None, + *, + is_pyramid=None, + num_colors=50, + seed=0.5, + name=None, + metadata=None, + scale=None, + translate=None, + opacity=0.7, + blending='translucent', + visible=True, + path=None, + ): + """Add a labels (or segmentation) layer to the layers list. + + An image-like layer where every pixel contains an integer ID + corresponding to the region it belongs to. + + Parameters + ---------- + data : array or list of array + Labels data as an array or pyramid. + is_pyramid : bool + Whether the data is an image pyramid or not. Pyramid data is + represented by a list of array like image data. If not specified by + the user and if the data is a list of arrays that decrease in shape + then it will be taken to be a pyramid. The first image in the list + should be the largest. + num_colors : int + Number of unique colors to use in colormap. + seed : float + Seed for colormap random generator. + name : str + Name of the layer. + metadata : dict + Layer metadata. + scale : tuple of float + Scale factors for the layer. + translate : tuple of float + Translation values for the layer. + opacity : float + Opacity of the layer visual, between 0.0 and 1.0. + blending : str + One of a list of preset blending modes that determines how RGB and + alpha values of the layer visual get mixed. Allowed values are + {'opaque', 'translucent', and 'additive'}. + visible : bool + Whether the layer visual is currently being displayed. + path : str or list of str + Path or list of paths to image data. Paths can be passed as strings + or `pathlib.Path` instances. + + Returns + ------- + layer : :class:`napari.layers.Labels` + The newly-created labels layer. + """ + if data is None and path is None: + raise ValueError("One of either data or path must be provided") + elif data is not None and path is not None: + raise ValueError("Only one of data or path can be provided") + elif data is None: + data = io.magic_imread(path) + + layer = layers.Labels( + data, + is_pyramid=is_pyramid, + num_colors=num_colors, + seed=seed, + name=name, + metadata=metadata, + scale=scale, + translate=translate, + opacity=opacity, + blending=blending, + visible=visible, + ) + self.add_layer(layer) + return layer + + def add_shapes( + self, + data=None, + *, + shape_type='rectangle', + edge_width=1, + edge_color='black', + face_color='white', + z_index=0, + name=None, + metadata=None, + scale=None, + translate=None, + opacity=0.7, + blending='translucent', + visible=True, + ): + """Add a shapes layer to the layers list. + + Parameters + ---------- + data : list or array + List of shape data, where each element is an (N, D) array of the + N vertices of a shape in D dimensions. Can be an 3-dimensional + array if each shape has the same number of vertices. + shape_type : string or list + String of shape shape_type, must be one of "{'line', 'rectangle', + 'ellipse', 'path', 'polygon'}". If a list is supplied it must be + the same length as the length of `data` and each element will be + applied to each shape otherwise the same value will be used for all + shapes. + edge_width : float or list + Thickness of lines and edges. If a list is supplied it must be the + same length as the length of `data` and each element will be + applied to each shape otherwise the same value will be used for all + shapes. + edge_color : str or list + If string can be any color name recognized by vispy or hex value if + starting with `#`. If array-like must be 1-dimensional array with 3 + or 4 elements. If a list is supplied it must be the same length as + the length of `data` and each element will be applied to each shape + otherwise the same value will be used for all shapes. + face_color : str or list + If string can be any color name recognized by vispy or hex value if + starting with `#`. If array-like must be 1-dimensional array with 3 + or 4 elements. If a list is supplied it must be the same length as + the length of `data` and each element will be applied to each shape + otherwise the same value will be used for all shapes. + z_index : int or list + Specifier of z order priority. Shapes with higher z order are + displayed ontop of others. If a list is supplied it must be the + same length as the length of `data` and each element will be + applied to each shape otherwise the same value will be used for all + shapes. + name : str + Name of the layer. + metadata : dict + Layer metadata. + scale : tuple of float + Scale factors for the layer. + translate : tuple of float + Translation values for the layer. + opacity : float or list + Opacity of the layer visual, between 0.0 and 1.0. + blending : str + One of a list of preset blending modes that determines how RGB and + alpha values of the layer visual get mixed. Allowed values are + {'opaque', 'translucent', and 'additive'}. + visible : bool + Whether the layer visual is currently being displayed. + + Returns + ------- + layer : :class:`napari.layers.Shapes` + The newly-created shapes layer. + """ + if data is None: + ndim = max(self.dims.ndim, 2) + data = np.empty((0, 0, ndim)) + + layer = layers.Shapes( + data=data, + shape_type=shape_type, + edge_width=edge_width, + edge_color=edge_color, + face_color=face_color, + z_index=z_index, + name=name, + metadata=metadata, + scale=scale, + translate=translate, + opacity=opacity, + blending=blending, + visible=visible, + ) + self.add_layer(layer) + return layer + + def add_surface( + self, + data, + *, + colormap='gray', + contrast_limits=None, + gamma=1, + name=None, + metadata=None, + scale=None, + translate=None, + opacity=1, + blending='translucent', + visible=True, + ): + """Add a surface layer to the layers list. + + Parameters + ---------- + data : 3-tuple of array + The first element of the tuple is an (N, D) array of vertices of + mesh triangles. The second is an (M, 3) array of int of indices + of the mesh triangles. The third element is the (K0, ..., KL, N) + array of values used to color vertices where the additional L + dimensions are used to color the same mesh with different values. + colormap : str, vispy.Color.Colormap, tuple, dict + Colormap to use for luminance images. If a string must be the name + of a supported colormap from vispy or matplotlib. If a tuple the + first value must be a string to assign as a name to a colormap and + the second item must be a Colormap. If a dict the key must be a + string to assign as a name to a colormap and the value must be a + Colormap. + contrast_limits : list (2,) + Color limits to be used for determining the colormap bounds for + luminance images. If not passed is calculated as the min and max of + the image. + gamma : float + Gamma correction for determining colormap linearity. Defaults to 1. + name : str + Name of the layer. + metadata : dict + Layer metadata. + scale : tuple of float + Scale factors for the layer. + translate : tuple of float + Translation values for the layer. + opacity : float + Opacity of the layer visual, between 0.0 and 1.0. + blending : str + One of a list of preset blending modes that determines how RGB and + alpha values of the layer visual get mixed. Allowed values are + {'opaque', 'translucent', and 'additive'}. + visible : bool + Whether the layer visual is currently being displayed. + + Returns + ------- + layer : :class:`napari.layers.Surface` + The newly-created surface layer. + """ + layer = layers.Surface( + data, + colormap=colormap, + contrast_limits=contrast_limits, + gamma=gamma, + name=name, + metadata=metadata, + scale=scale, + translate=translate, + opacity=opacity, + blending=blending, + visible=visible, + ) + self.add_layer(layer) + return layer + + def add_vectors( + self, + data, + *, + edge_width=1, + edge_color='red', + length=1, + name=None, + metadata=None, + scale=None, + translate=None, + opacity=0.7, + blending='translucent', + visible=True, + ): + """Add a vectors layer to the layers list. + + Parameters + ---------- + data : (N, 2, D) or (N1, N2, ..., ND, D) array + An (N, 2, D) array is interpreted as "coordinate-like" data and a + list of N vectors with start point and projections of the vector in + D dimensions. An (N1, N2, ..., ND, D) array is interpreted as + "image-like" data where there is a length D vector of the + projections at each pixel. + edge_width : float + Width for all vectors in pixels. + length : float + Multiplicative factor on projections for length of all vectors. + edge_color : str + Edge color of all the vectors. + name : str + Name of the layer. + metadata : dict + Layer metadata. + scale : tuple of float + Scale factors for the layer. + translate : tuple of float + Translation values for the layer. + opacity : float + Opacity of the layer visual, between 0.0 and 1.0. + blending : str + One of a list of preset blending modes that determines how RGB and + alpha values of the layer visual get mixed. Allowed values are + {'opaque', 'translucent', and 'additive'}. + visible : bool + Whether the layer visual is currently being displayed. + + Returns + ------- + layer : :class:`napari.layers.Vectors` + The newly-created vectors layer. + """ + layer = layers.Vectors( + data, + edge_width=edge_width, + edge_color=edge_color, + length=length, + name=name, + metadata=metadata, + scale=scale, + translate=translate, + opacity=opacity, + blending=blending, + visible=visible, + ) + self.add_layer(layer) + return layer diff --git a/napari/components/viewer_model.py b/napari/components/viewer_model.py index d7c1fd02a94..2d45564e474 100644 --- a/napari/components/viewer_model.py +++ b/napari/components/viewer_model.py @@ -4,18 +4,15 @@ import numpy as np +from .add_layers_mixin import AddLayersMixin from .dims import Dims from .layerlist import LayerList -from .. import layers -from ..utils import colormaps from ..utils.event import EmitterGroup, Event from ..utils.keybindings import KeymapMixin from ..utils.theme import palettes -from ..utils.misc import ensure_iterable, is_iterable -from ..utils import io -class ViewerModel(KeymapMixin): +class ViewerModel(AddLayersMixin, KeymapMixin): """Viewer containing the rendered scene, layers, and controlling elements including dimension sliders, and control bars for color limits. @@ -390,616 +387,6 @@ def add_layer(self, layer): if len(self.layers) == 1: self.reset_view() - def add_image( - self, - data=None, - *, - channel_axis=None, - rgb=None, - is_pyramid=None, - colormap=None, - contrast_limits=None, - gamma=1, - interpolation='nearest', - rendering='mip', - iso_threshold=0.5, - attenuation=0.5, - name=None, - metadata=None, - scale=None, - translate=None, - opacity=1, - blending=None, - visible=True, - path=None, - ): - """Add an image layer to the layers list. - - Parameters - ---------- - data : array or list of array - Image data. Can be N dimensional. If the last dimension has length - 3 or 4 can be interpreted as RGB or RGBA if rgb is `True`. If a - list and arrays are decreasing in shape then the data is treated as - an image pyramid. - channel_axis : int, optional - Axis to expand image along. - rgb : bool - Whether the image is rgb RGB or RGBA. If not specified by user and - the last dimension of the data has length 3 or 4 it will be set as - `True`. If `False` the image is interpreted as a luminance image. - is_pyramid : bool - Whether the data is an image pyramid or not. Pyramid data is - represented by a list of array like image data. If not specified by - the user and if the data is a list of arrays that decrease in shape - then it will be taken to be a pyramid. The first image in the list - should be the largest. - colormap : str, vispy.Color.Colormap, tuple, dict, list - Colormaps to use for luminance images. If a string must be the name - of a supported colormap from vispy or matplotlib. If a tuple the - first value must be a string to assign as a name to a colormap and - the second item must be a Colormap. If a dict the key must be a - string to assign as a name to a colormap and the value must be a - Colormap. If a list then must be same length as the axis that is - being expanded as channels, and each colormap is applied to each - new image layer. - contrast_limits : list (2,) - Color limits to be used for determining the colormap bounds for - luminance images. If not passed is calculated as the min and max of - the image. If list of lists then must be same length as the axis - that is being expanded and then each colormap is applied to each - image. - gamma : list, float - Gamma correction for determining colormap linearity. Defaults to 1. - If a list then must be same length as the axis that is being - expanded and then each entry in the list is applied to each image. - interpolation : str - Interpolation mode used by vispy. Must be one of our supported - modes. - rendering : str - Rendering mode used by vispy. Must be one of our supported - modes. - iso_threshold : float - Threshold for isosurface. - attenuation : float - Attenuation rate for attenuated maximum intensity projection. - name : str - Name of the layer. - metadata : dict - Layer metadata. - scale : tuple of float - Scale factors for the layer. - translate : tuple of float - Translation values for the layer. - opacity : float - Opacity of the layer visual, between 0.0 and 1.0. - blending : str - One of a list of preset blending modes that determines how RGB and - alpha values of the layer visual get mixed. Allowed values are - {'opaque', 'translucent', and 'additive'}. - visible : bool - Whether the layer visual is currently being displayed. - path : str or list of str - Path or list of paths to image data. Paths can be passed as strings - or `pathlib.Path` instances. - - Returns - ------- - layer : :class:`napari.layers.Image` or list - The newly-created image layer or list of image layers. - """ - if data is None and path is None: - raise ValueError("One of either data or path must be provided") - elif data is not None and path is not None: - raise ValueError("Only one of data or path can be provided") - elif data is None: - data = io.magic_imread(path) - - if channel_axis is None: - if colormap is None: - colormap = 'gray' - if blending is None: - blending = 'translucent' - layer = layers.Image( - data, - rgb=rgb, - is_pyramid=is_pyramid, - colormap=colormap, - contrast_limits=contrast_limits, - gamma=gamma, - interpolation=interpolation, - rendering=rendering, - iso_threshold=iso_threshold, - attenuation=attenuation, - name=name, - metadata=metadata, - scale=scale, - translate=translate, - opacity=opacity, - blending=blending, - visible=visible, - ) - self.add_layer(layer) - return layer - else: - if is_pyramid: - n_channels = data[0].shape[channel_axis] - else: - n_channels = data.shape[channel_axis] - - name = ensure_iterable(name) - - if blending is None: - blending = 'additive' - - if colormap is None: - if n_channels < 3: - colormap = colormaps.MAGENTA_GREEN - else: - colormap = itertools.cycle(colormaps.CYMRGB) - else: - colormap = ensure_iterable(colormap) - - # If one pair of clim values is passed then need to iterate them to - # all layers. - if contrast_limits is not None and not is_iterable( - contrast_limits[0] - ): - contrast_limits = itertools.repeat(contrast_limits) - else: - contrast_limits = ensure_iterable(contrast_limits) - - gamma = ensure_iterable(gamma) - - layer_list = [] - zipped_args = zip( - range(n_channels), colormap, contrast_limits, gamma, name - ) - for i, cmap, clims, _gamma, name in zipped_args: - if is_pyramid: - image = [ - np.take(data[j], i, axis=channel_axis) - for j in range(len(data)) - ] - else: - image = np.take(data, i, axis=channel_axis) - layer = layers.Image( - image, - rgb=rgb, - colormap=cmap, - contrast_limits=clims, - gamma=_gamma, - interpolation=interpolation, - rendering=rendering, - name=name, - metadata=metadata, - scale=scale, - translate=translate, - opacity=opacity, - blending=blending, - visible=visible, - ) - self.add_layer(layer) - layer_list.append(layer) - return layer_list - - def add_points( - self, - data=None, - *, - symbol='o', - size=10, - edge_width=1, - edge_color='black', - face_color='white', - n_dimensional=False, - name=None, - metadata=None, - scale=None, - translate=None, - opacity=1, - blending='translucent', - visible=True, - ): - """Add a points layer to the layers list. - - Parameters - ---------- - data : array (N, D) - Coordinates for N points in D dimensions. - symbol : str - Symbol to be used for the point markers. Must be one of the - following: arrow, clobber, cross, diamond, disc, hbar, ring, - square, star, tailed_arrow, triangle_down, triangle_up, vbar, x. - size : float, array - Size of the point marker. If given as a scalar, all points are made - the same size. If given as an array, size must be the same - broadcastable to the same shape as the data. - edge_width : float - Width of the symbol edge in pixels. - edge_color : str, array-like - Color of the point marker border. Numeric color values should be RGB(A). - face_color : str, array-like - Color of the point marker body. Numeric color values should be RGB(A). - n_dimensional : bool - If True, renders points not just in central plane but also in all - n-dimensions according to specified point marker size. - name : str - Name of the layer. - metadata : dict - Layer metadata. - scale : tuple of float - Scale factors for the layer. - translate : tuple of float - Translation values for the layer. - opacity : float - Opacity of the layer visual, between 0.0 and 1.0. - blending : str - One of a list of preset blending modes that determines how RGB and - alpha values of the layer visual get mixed. Allowed values are - {'opaque', 'translucent', and 'additive'}. - visible : bool - Whether the layer visual is currently being displayed. - - Returns - ------- - layer : :class:`napari.layers.Points` - The newly-created points layer. - - Notes - ----- - See vispy's marker visual docs for more details: - http://api.vispy.org/en/latest/visuals.html#vispy.visuals.MarkersVisual - """ - if data is None: - ndim = max(self.dims.ndim, 2) - data = np.empty([0, ndim]) - - layer = layers.Points( - data=data, - symbol=symbol, - size=size, - edge_width=edge_width, - edge_color=edge_color, - face_color=face_color, - n_dimensional=n_dimensional, - name=name, - metadata=metadata, - scale=scale, - translate=translate, - opacity=opacity, - blending=blending, - visible=visible, - ) - self.add_layer(layer) - return layer - - def add_labels( - self, - data=None, - *, - is_pyramid=None, - num_colors=50, - seed=0.5, - name=None, - metadata=None, - scale=None, - translate=None, - opacity=0.7, - blending='translucent', - visible=True, - path=None, - ): - """Add a labels (or segmentation) layer to the layers list. - - An image-like layer where every pixel contains an integer ID - corresponding to the region it belongs to. - - Parameters - ---------- - data : array or list of array - Labels data as an array or pyramid. - is_pyramid : bool - Whether the data is an image pyramid or not. Pyramid data is - represented by a list of array like image data. If not specified by - the user and if the data is a list of arrays that decrease in shape - then it will be taken to be a pyramid. The first image in the list - should be the largest. - num_colors : int - Number of unique colors to use in colormap. - seed : float - Seed for colormap random generator. - name : str - Name of the layer. - metadata : dict - Layer metadata. - scale : tuple of float - Scale factors for the layer. - translate : tuple of float - Translation values for the layer. - opacity : float - Opacity of the layer visual, between 0.0 and 1.0. - blending : str - One of a list of preset blending modes that determines how RGB and - alpha values of the layer visual get mixed. Allowed values are - {'opaque', 'translucent', and 'additive'}. - visible : bool - Whether the layer visual is currently being displayed. - path : str or list of str - Path or list of paths to image data. Paths can be passed as strings - or `pathlib.Path` instances. - - Returns - ------- - layer : :class:`napari.layers.Labels` - The newly-created labels layer. - """ - if data is None and path is None: - raise ValueError("One of either data or path must be provided") - elif data is not None and path is not None: - raise ValueError("Only one of data or path can be provided") - elif data is None: - data = io.magic_imread(path) - - layer = layers.Labels( - data, - is_pyramid=is_pyramid, - num_colors=num_colors, - seed=seed, - name=name, - metadata=metadata, - scale=scale, - translate=translate, - opacity=opacity, - blending=blending, - visible=visible, - ) - self.add_layer(layer) - return layer - - def add_shapes( - self, - data=None, - *, - shape_type='rectangle', - edge_width=1, - edge_color='black', - face_color='white', - z_index=0, - name=None, - metadata=None, - scale=None, - translate=None, - opacity=0.7, - blending='translucent', - visible=True, - ): - """Add a shapes layer to the layers list. - - Parameters - ---------- - data : list or array - List of shape data, where each element is an (N, D) array of the - N vertices of a shape in D dimensions. Can be an 3-dimensional - array if each shape has the same number of vertices. - shape_type : string or list - String of shape shape_type, must be one of "{'line', 'rectangle', - 'ellipse', 'path', 'polygon'}". If a list is supplied it must be - the same length as the length of `data` and each element will be - applied to each shape otherwise the same value will be used for all - shapes. - edge_width : float or list - Thickness of lines and edges. If a list is supplied it must be the - same length as the length of `data` and each element will be - applied to each shape otherwise the same value will be used for all - shapes. - edge_color : str or list - If string can be any color name recognized by vispy or hex value if - starting with `#`. If array-like must be 1-dimensional array with 3 - or 4 elements. If a list is supplied it must be the same length as - the length of `data` and each element will be applied to each shape - otherwise the same value will be used for all shapes. - face_color : str or list - If string can be any color name recognized by vispy or hex value if - starting with `#`. If array-like must be 1-dimensional array with 3 - or 4 elements. If a list is supplied it must be the same length as - the length of `data` and each element will be applied to each shape - otherwise the same value will be used for all shapes. - z_index : int or list - Specifier of z order priority. Shapes with higher z order are - displayed ontop of others. If a list is supplied it must be the - same length as the length of `data` and each element will be - applied to each shape otherwise the same value will be used for all - shapes. - name : str - Name of the layer. - metadata : dict - Layer metadata. - scale : tuple of float - Scale factors for the layer. - translate : tuple of float - Translation values for the layer. - opacity : float or list - Opacity of the layer visual, between 0.0 and 1.0. - blending : str - One of a list of preset blending modes that determines how RGB and - alpha values of the layer visual get mixed. Allowed values are - {'opaque', 'translucent', and 'additive'}. - visible : bool - Whether the layer visual is currently being displayed. - - Returns - ------- - layer : :class:`napari.layers.Shapes` - The newly-created shapes layer. - """ - if data is None: - ndim = max(self.dims.ndim, 2) - data = np.empty((0, 0, ndim)) - - layer = layers.Shapes( - data=data, - shape_type=shape_type, - edge_width=edge_width, - edge_color=edge_color, - face_color=face_color, - z_index=z_index, - name=name, - metadata=metadata, - scale=scale, - translate=translate, - opacity=opacity, - blending=blending, - visible=visible, - ) - self.add_layer(layer) - return layer - - def add_surface( - self, - data, - *, - colormap='gray', - contrast_limits=None, - gamma=1, - name=None, - metadata=None, - scale=None, - translate=None, - opacity=1, - blending='translucent', - visible=True, - ): - """Add a surface layer to the layers list. - - Parameters - ---------- - data : 3-tuple of array - The first element of the tuple is an (N, D) array of vertices of - mesh triangles. The second is an (M, 3) array of int of indices - of the mesh triangles. The third element is the (K0, ..., KL, N) - array of values used to color vertices where the additional L - dimensions are used to color the same mesh with different values. - colormap : str, vispy.Color.Colormap, tuple, dict - Colormap to use for luminance images. If a string must be the name - of a supported colormap from vispy or matplotlib. If a tuple the - first value must be a string to assign as a name to a colormap and - the second item must be a Colormap. If a dict the key must be a - string to assign as a name to a colormap and the value must be a - Colormap. - contrast_limits : list (2,) - Color limits to be used for determining the colormap bounds for - luminance images. If not passed is calculated as the min and max of - the image. - gamma : float - Gamma correction for determining colormap linearity. Defaults to 1. - name : str - Name of the layer. - metadata : dict - Layer metadata. - scale : tuple of float - Scale factors for the layer. - translate : tuple of float - Translation values for the layer. - opacity : float - Opacity of the layer visual, between 0.0 and 1.0. - blending : str - One of a list of preset blending modes that determines how RGB and - alpha values of the layer visual get mixed. Allowed values are - {'opaque', 'translucent', and 'additive'}. - visible : bool - Whether the layer visual is currently being displayed. - - Returns - ------- - layer : :class:`napari.layers.Surface` - The newly-created surface layer. - """ - layer = layers.Surface( - data, - colormap=colormap, - contrast_limits=contrast_limits, - gamma=gamma, - name=name, - metadata=metadata, - scale=scale, - translate=translate, - opacity=opacity, - blending=blending, - visible=visible, - ) - self.add_layer(layer) - return layer - - def add_vectors( - self, - data, - *, - edge_width=1, - edge_color='red', - length=1, - name=None, - metadata=None, - scale=None, - translate=None, - opacity=0.7, - blending='translucent', - visible=True, - ): - """Add a vectors layer to the layers list. - - Parameters - ---------- - data : (N, 2, D) or (N1, N2, ..., ND, D) array - An (N, 2, D) array is interpreted as "coordinate-like" data and a - list of N vectors with start point and projections of the vector in - D dimensions. An (N1, N2, ..., ND, D) array is interpreted as - "image-like" data where there is a length D vector of the - projections at each pixel. - edge_width : float - Width for all vectors in pixels. - length : float - Multiplicative factor on projections for length of all vectors. - edge_color : str - Edge color of all the vectors. - name : str - Name of the layer. - metadata : dict - Layer metadata. - scale : tuple of float - Scale factors for the layer. - translate : tuple of float - Translation values for the layer. - opacity : float - Opacity of the layer visual, between 0.0 and 1.0. - blending : str - One of a list of preset blending modes that determines how RGB and - alpha values of the layer visual get mixed. Allowed values are - {'opaque', 'translucent', and 'additive'}. - visible : bool - Whether the layer visual is currently being displayed. - - Returns - ------- - layer : :class:`napari.layers.Vectors` - The newly-created vectors layer. - """ - layer = layers.Vectors( - data, - edge_width=edge_width, - edge_color=edge_color, - length=length, - name=name, - metadata=metadata, - scale=scale, - translate=translate, - opacity=opacity, - blending=blending, - visible=visible, - ) - self.add_layer(layer) - return layer - def _new_labels(self): if self.dims.ndim == 0: dims = (512, 512)