def test_colormaps(): """Test setting test_colormaps.""" np.random.seed(0) data = np.random.random((10, 15)) layer = Image(data) assert layer.colormap[0] == 'gray' assert type(layer.colormap[1]) == Colormap layer.colormap = 'magma' assert layer.colormap[0] == 'magma' assert type(layer.colormap[1]) == Colormap cmap = Colormap([[0.0, 0.0, 0.0, 0.0], [0.3, 0.7, 0.2, 1.0]]) layer.colormap = 'custom', cmap assert layer.colormap[0] == 'custom' assert layer.colormap[1] == cmap cmap = Colormap([[0.0, 0.0, 0.0, 0.0], [0.7, 0.2, 0.6, 1.0]]) layer.colormap = {'new': cmap} assert layer.colormap[0] == 'new' assert layer.colormap[1] == cmap layer = Image(data, colormap='magma') assert layer.colormap[0] == 'magma' assert type(layer.colormap[1]) == Colormap cmap = Colormap([[0.0, 0.0, 0.0, 0.0], [0.3, 0.7, 0.2, 1.0]]) layer = Image(data, colormap=('custom', cmap)) assert layer.colormap[0] == 'custom' assert layer.colormap[1] == cmap cmap = Colormap([[0.0, 0.0, 0.0, 0.0], [0.7, 0.2, 0.6, 1.0]]) layer = Image(data, colormap={'new': cmap}) assert layer.colormap[0] == 'new' assert layer.colormap[1] == cmap
def test_colormap_discrete(): """Test discrete colormaps.""" cm = Colormap(['r', 'g'], interpolation='zero') assert_allclose(cm[-1].rgba, [[1, 0, 0, 1]]) assert_allclose(cm[0.].rgba, [[1, 0, 0, 1]]) assert_allclose(cm[0.49].rgba, [[1, 0, 0, 1]]) assert_allclose(cm[0.51].rgba, [[0, 1, 0, 1]]) assert_allclose(cm[1.].rgba, [[0, 1, 0, 1]]) cm = Colormap(['r', 'g', 'b'], interpolation='zero') assert_allclose(cm[-1].rgba, [[1, 0, 0, 1]]) assert_allclose(cm[0.].rgba, [[1, 0, 0, 1]]) assert_allclose(cm[.32].rgba, [[1, 0, 0, 1]]) assert_allclose(cm[.34].rgba, [[0, 1, 0, 1]]) assert_allclose(cm[.66].rgba, [[0, 1, 0, 1]]) assert_allclose(cm[.67].rgba, [[0, 0, 1, 1]]) assert_allclose(cm[.99].rgba, [[0, 0, 1, 1]]) assert_allclose(cm[1].rgba, [[0, 0, 1, 1]]) assert_allclose(cm[1.1].rgba, [[0, 0, 1, 1]]) cm = Colormap(['r', 'g', 'b'], [0., 0.1, 0.8, 1.0], interpolation='zero') assert_allclose(cm[-1].rgba, [[1, 0, 0, 1]]) assert_allclose(cm[0.].rgba, [[1, 0, 0, 1]]) assert_allclose(cm[.099].rgba, [[1, 0, 0, 1]]) assert_allclose(cm[.101].rgba, [[0, 1, 0, 1]]) assert_allclose(cm[.799].rgba, [[0, 1, 0, 1]]) assert_allclose(cm[.801].rgba, [[0, 0, 1, 1]]) assert_allclose(cm[1].rgba, [[0, 0, 1, 1]], 1e-6, 1e-6) assert_allclose(cm[2].rgba, [[0, 0, 1, 1]], 1e-6, 1e-6)
def _on_colormap_change(self): cmap = self.layer.colormap[1] if self.layer.gamma != 1: # when gamma!=1, we instantiate a new colormap with 256 control points from 0-1 cmap = Colormap(cmap[np.linspace(0, 1, 256)**self.layer.gamma]) if self.layer.dims.ndisplay == 3: self.node.view_program['texture2D_LUT'] = (cmap.texture_lut() if ( hasattr(cmap, 'texture_lut')) else None) self.node.cmap = cmap
def _on_colormap_change(self, event=None): if self.layer.gamma != 1: # when gamma!=1, we instantiate a new colormap with 256 control # points from 0-1 colors = self.layer.colormap.map( np.linspace(0, 1, 256)**self.layer.gamma) cmap = VispyColormap(colors) else: cmap = VispyColormap(*self.layer.colormap) if self.layer.dims.ndisplay == 3: self.node.view_program['texture2D_LUT'] = (cmap.texture_lut() if ( hasattr(cmap, 'texture_lut')) else None) self.node.cmap = cmap
def test_colormap(name): np.random.seed(0) cmap = AVAILABLE_COLORMAPS[name] # Test can map random 0-1 values values = np.random.rand(50) colors = cmap.map(values) assert colors.shape == (len(values), 4) # Create vispy colormap and check current colormaps match vispy # colormap vispy_cmap = VispyColormap(*cmap) vispy_colors = vispy_cmap.map(values) np.testing.assert_almost_equal(colors, vispy_colors, decimal=6)
def rgb_colormaps(bitspersample=8, samples=3): """Return RGB colormaps.""" n = 2**bitspersample ramp = numpy.linspace(0.0, 1.0, n).astype('float32') r = numpy.zeros((n, samples), dtype='float32') r[:, 0] = ramp g = numpy.zeros((n, samples), dtype='float32') g[:, 1] = ramp b = numpy.zeros((n, samples), dtype='float32') b[:, 2] = ramp if samples > 3: r[:, 3:] = 1.0 g[:, 3:] = 1.0 b[:, 3:] = 1.0 return [Colormap(r), Colormap(g), Colormap(b)]
def get_layer_list(channels, nd2_func, path, frame_shape, frame_dtype, n_timepoints): channel_dict = dict(zip(channels, [[] for _ in range(len(channels))])) for i, channel in enumerate(channels): arr = da.map_blocks(nd2_func(path, i), da.arange(n_timepoints, chunks=1), dtype=frame_dtype, chunks=da.core.normalize_chunks( (1, *frame_shape), (n_timepoints, *frame_shape)), new_axis=list(range(1, 1 + len(frame_shape)))) channel_dict[channel] = arr layer_list = [] for channel_name, channel in channel_dict.items(): visible = True blending = 'additive' if visible else 'translucent' meta = get_metadata(path) add_kwargs = { "name": channel_name, "visible": visible, "blending": blending, "scale": meta['scale'], "translate": meta['translate'], } try: channel_color = meta['channels'][channel_name] color = Colormap([[0, 0, 0], channel_color[:-1]]) # ignore alpha add_kwargs["colormap"] = color except KeyError: pass layer_type = "image" layer_list.append((channel, add_kwargs, layer_type)) return layer_list
def run(self): seg, seeds, mask = self.get_initial_viewer_data() self.print_help_impl() # add initial layers to the viewer with napari.gui_qt(): viewer = napari.Viewer() # add image layers and point layer for seeds viewer.add_image(self.raw, name='raw') viewer.add_image(self.imws.affinities, name='affinities', visible=False) if self.show_edges: edges = find_boundaries(seg) cmap = Colormap([ [0., 0., 0., 0.], # label 0 is transparent [1., 1., 1., 1.] # label 1 is white (better color?) ]) viewer.add_image(edges, name='edges', colormap=cmap, contrast_limits=[0, 1]) viewer.add_labels(mask, name='locked-segment-mask', visible=False) viewer.add_labels(seeds, name='seeds') viewer.add_labels(seg, name='segmentation') self.add_keybindings(viewer)
def label_colormap(num_colors=256, seed=0.5): """Produce a colormap suitable for use with a given label set. Parameters ---------- num_colors : int, optional Number of unique colors to use. Default used if not given. seed : float or array of float, length 3 The seed for the random color generator. Returns ------- cmap : vispy.color.Colormap A colormap for use with labels are remapped to [0, 1]. Notes ----- 0 always maps to fully transparent. """ # Starting the control points slightly above 0 and below 1 is necessary # to ensure that the background pixel 0 is transparent midpoints = np.linspace(0.00001, 1 - 0.00001, num_colors - 1) control_points = np.concatenate(([0], midpoints, [1.0])) # make sure to add an alpha channel to the colors colors = np.concatenate( (_color_random(num_colors, seed=seed), np.full((num_colors, 1), 1)), axis=1, ) colors[0, :] = 0 # ensure alpha is 0 for label 0 cmap = Colormap(colors=colors, controls=control_points, interpolation='zero') return cmap
def color_dict_to_colormap(colors): """ Generate a color map based on the given color dictionary Parameters ---------- colors : dict of int to array of float, shape (4) Mapping between labels and color Returns ------- colormap : Colormap Colormap constructed with provided control colors label_color_index : dict of int Mapping of Label to color control point within colormap """ control_colors = np.unique(list(colors.values()), axis=0) colormap = Colormap(control_colors) control2index = { tuple(ctrl): i / (len(control_colors) - 1) for i, ctrl in enumerate(control_colors) } label_color_index = { label: control2index[tuple(color)] for label, color in colors.items() } return colormap, label_color_index
def cbcolor(self, data=None, length=10): """Set the color of the colorbar. Kargs: data: ndarray, optional, (def: None) Array of data. This array is used to automatically set the minimum and maximum of the colorbar. length: int, optional, (def: 10) Length of the colorbar lines. Return: cmap: vispy colormap The vispy colormap to use to create the colorbar. """ # Define a vector of linearly spaced values : if data is None: colval = np.linspace(self['clim'][0], self['clim'][1], num=length) else: colval = np.linspace(np.min(data), np.max(data)) # Turn the colval vector into a RGB array of colors. The clim parameter # is not usefull here : colorbar = array2colormap(colval, vmin=self['vmin'], vmax=self['vmax'], under=self['under'], over=self['over'], cmap=self['cmap'], clim=None) # Use the Colormap function of vispy to create a colormap : cmap = Colormap(np.flipud(colorbar)) return cmap
def load_omero_metadata(zarr_path): """Load OMERO metadata as json and convert for napari""" omero_path = zarr_path + "omero.json" metadata = {} try: image_data = requests.get(omero_path).json() print(image_data) colormaps = [] for ch in image_data['channels']: # 'FF0000' -> [1, 0, 0] rgb = [(int(ch['color'][i:i + 2], 16) / 255) for i in range(0, 6, 2)] if image_data['rdefs']['model'] == 'greyscale': rgb = [1, 1, 1] colormaps.append(Colormap([[0, 0, 0], rgb])) metadata['colormap'] = colormaps metadata['contrast_limits'] = [[ ch['window']['start'], ch['window']['end'] ] for ch in image_data['channels']] metadata['name'] = [ch['label'] for ch in image_data['channels']] metadata['visible'] = [ch['active'] for ch in image_data['channels']] except Exception: pass return metadata
def mask_color(self) -> Colormap: """Get mask marking color""" color = Color( np.divide( self.settings.get_from_profile("mask_presentation_color", [255, 255, 255]), 255)) return Colormap(ColorArray(["black", color.rgba]))
def get_omero_metadata(image: ImageWrapper) -> Dict: """Get metadata from OMERO as a Dict to pass to napari.""" channels = image.getChannels() colors = [] for ch in channels: # use current rendering settings from OMERO color = ch.getColor().getRGB() color = [r / 256 for r in color] colors.append(Colormap([[0, 0, 0], color])) contrast_limits = [[ch.getWindowStart(), ch.getWindowEnd()] for ch in channels] visibles = [ch.isActive() for ch in channels] names = [ch.getLabel() for ch in channels] scale = None # Setting z-scale causes issues with Z-slider. # See https://github.com/tlambert03/napari-omero/pull/15 # if image.getSizeZ() > 1: # size_x = image.getPixelSizeX() # size_z = image.getPixelSizeZ() # if size_x is not None and size_z is not None: # scale = [1, size_z / size_x, 1, 1] return { 'channel_axis': 1, 'colormap': colors, 'contrast_limits': contrast_limits, 'name': names, 'visible': visibles, 'scale': scale, }
def get_layer_list(channels, nd2_func, path, frame_shape, frame_dtype, n_timepoints): channel_dict = dict(zip(channels, [[] for _ in range(len(channels))])) for i, channel in enumerate(channels): arr = da.stack([ da.from_delayed(delayed(nd2_func(path, i))(j), shape=frame_shape, dtype=frame_dtype) for j in range(n_timepoints) ]) channel_dict[channel] = dask.optimize(arr)[0] layer_list = [] for channel_name, channel in channel_dict.items(): visible = channel_name in VISIBLE blending = 'additive' if visible else 'translucent' channel_color = list(CHANNEL_COLORS[channel_name]) color = Colormap([[0, 0, 0], channel_color]) meta = get_metadata(path) add_kwargs = { "name": channel_name, "visible": visible, "colormap": color, "blending": blending, **meta } layer_type = "image" layer_list.append((channel, add_kwargs, layer_type)) return layer_list
def num_color_colormap(cmap_name: str, num: int, bg_color=None): """ Generate num-color colormap from available matplotlib cmap :param cmap_name: str, matplotlib cmap name :param num: int, positive, number of colors used for colormap generation :param bg_color: background color rgba value, default = transparent black :return: cmap_napari: generated num-color colormap for napari display cmap_plt: generated num-color colormap for matplotlib display rgba: colormap array, note that rgba[0] = bg_color """ if bg_color is None: bg_color = [0.0, 0.0, 0.0, 0.0] cmap = cm.get_cmap(cmap_name) if num <= 0: raise ValueError( "0 or negative values cannot be used to generate n-color colormap." ) else: rgba = cmap(np.arange(0, 1, 1 / num)) rgba = np.insert(rgba, 0, bg_color, axis=0) cmap_napari = Colormap(rgba) cmap_plt = ListedColormap(rgba) return cmap_napari, cmap_plt, rgba
def load_omero_channel(image: ImageWrapper, channel: ChannelWrapper, c_index: int) -> LayerData: data = get_data_lazy(image, c_index=c_index) color = channel.getColor().getRGB() color = [r / 256 for r in color] cmap = Colormap([[0, 0, 0], color]) scale = None # FIXME: still getting size mismatch sometimes is there a getNDim()? if image.getSizeZ() > 1: size_x = image.getPixelSizeX() size_z = image.getPixelSizeZ() if size_x is not None and size_z is not None: if image.getSizeC() > 1: scale = [1, size_z / size_x, 1, 1] else: scale = [size_z / size_x, 1, 1] meta = { "blending": "additive", "colormap": ("from_omero", cmap), "scale": scale, "name": channel.getLabel(), "visible": channel.isActive(), "contrast_limits": [channel.getWindowStart(), channel.getWindowEnd()], } # contrast limits range ... not accessible from plugin interface # win_min = channel.getWindowMin() # win_max = channel.getWindowMax() return (data, meta)
def load_omero_channel(image, channel, c_index): data = get_data_lazy(image, c=c_index) color = channel.getColor().getRGB() color = [r / 256 for r in color] cmap = Colormap([[0, 0, 0], color]) scale = None if image.getSizeZ() > 1: size_x = image.getPixelSizeX() size_z = image.getPixelSizeZ() if size_x is not None and size_z is not None: if image.getSizeC() > 1: scale = [1, size_z / size_x, 1, 1] else: scale = [size_z / size_x, 1, 1] meta = { "blending": "additive", "colormap": ("from_omero", cmap), "scale": scale, "name": channel.getLabel(), "visible": channel.isActive(), "contrast_limits": [channel.getWindowStart(), channel.getWindowEnd()], } return (data, meta)
def get_roi_view_parameters(self, image_info: ImageInfo) -> Colormap: colors = self.settings.label_colors / 255 if self.image_state.show_label == LabelEnum.Not_show or image_info.roi_count == 0 or colors.size == 0: colors = np.array([[0, 0, 0, 0], [0, 0, 0, 0]]) else: repeat = int(np.ceil(image_info.roi_count / colors.shape[0])) colors = np.concatenate([colors] * repeat) colors = np.concatenate( [colors, np.ones(colors.shape[0]).reshape(colors.shape[0], 1)], axis=1) colors = np.concatenate([[[0, 0, 0, 0]], colors[:image_info.roi_count]]) if self.image_state.show_label == LabelEnum.Show_selected: try: colors *= self.settings.components_mask().reshape( (colors.shape[0], 1)) except ValueError: pass control_points = [0] + list( np.linspace(1 / (2 * colors.shape[0]), 1, endpoint=True, num=colors.shape[0])) return Colormap(colors, controls=control_points, interpolation="zero")
def map_property( prop: np.ndarray, colormap: Colormap, contrast_limits: Union[None, Tuple[float, float]] = None, ) -> Tuple[np.ndarray, Tuple[float, float]]: """Apply a colormap to a property Parameters ---------- prop : np.ndarray The property to be colormapped colormap : vispy.color.Colormap The vispy colormap object to apply to the property contrast_limits: Union[None, Tuple[float, float]] The contrast limits for applying the colormap to the property. If a 2-tuple is provided, it should be provided as (lower_bound, upper_bound). If None is provided, the contrast limits will be set to (property.min(), property.max()). Default value is None. """ if contrast_limits is None: contrast_limits = (prop.min(), prop.max()) normalized_properties = np.interp(prop, contrast_limits, (0, 1)) mapped_properties = colormap.map(normalized_properties) return mapped_properties, contrast_limits
def alpha_colormap(bitspersample=8, samples=4): """Return Alpha colormap.""" n = 2**bitspersample ramp = numpy.linspace(0.0, 1.0, n).astype('float32') a = numpy.zeros((n, samples), dtype='float32') a[:, 3] = ramp[::-1] return Colormap(a)
def vispy_or_mpl_colormap(name): """Try to get a colormap from vispy, or convert an mpl one to vispy format. Parameters ---------- name : str The name of the colormap. Returns ------- cmap : vispy.color.Colormap The found colormap. Raises ------ KeyError If no colormap with that name is found within vispy or matplotlib. """ vispy_cmaps = get_colormaps() if name in vispy_cmaps: cmap = get_colormap(name) else: try: mpl_cmap = getattr(cm, name) except AttributeError: raise KeyError(f'Colormap "{name}" not found in either vispy ' 'or matplotlib.') mpl_colors = mpl_cmap(np.linspace(0, 1, 256)) cmap = Colormap(mpl_colors) return cmap
def __init__(self): app.Canvas.__init__(self, keys='interactive') self.program = gloo.Program(VERT_SHADER, FRAG_SHADER) self.program['index'] = [(x,) for x in range(num_bins)] * num_lines self.program['line'] = [(x,) * num_bins for x in range(num_lines)] self.program['map_offset'] = 0 self.program['num_bins'] = num_bins self.program['num_lines'] = num_lines heightmap = np.random.random(size=(num_lines, num_bins)).astype('float32') self.program['heightmap'] = gloo.Texture2D(data=heightmap, internalformat='r32f') #print (dir(self.program['heightmap'])) self.program['colormap'] = Colormap(['r', 'g', 'b']).map(np.linspace(0, 1, 64)).astype('float32') gloo.set_viewport(0, 0, *self.physical_size) gloo.set_state(clear_color='black', blend=True, blend_func=('src_alpha', 'one_minus_src_alpha')) self.show()
def get_layer_list(channels, nd2_func, path, frame_shape, frame_dtype, n_timepoints): channel_dict = dict(zip(channels, [[] for _ in range(len(channels))])) for i, channel in enumerate(channels): arr = da.stack([ da.from_delayed(delayed(nd2_func(path, i))(j), shape=frame_shape, dtype=frame_dtype) for j in range(n_timepoints) ]) channel_dict[channel] = dask.optimize(arr)[0] layer_list = [] for channel_name, channel in channel_dict.items(): visible = True blending = 'additive' if visible else 'translucent' meta = get_metadata(path) channel_color = meta['channels'][channel_name] color = Colormap([[0, 0, 0], channel_color[:-1]]) # ignore alpha add_kwargs = { "name": channel_name, "visible": visible, "colormap": color, "blending": blending, "scale": meta['scale'], "translate": meta['translate'], } layer_type = "image" layer_list.append((channel, add_kwargs, layer_type)) return layer_list
def ScatterPlot3D(data, labels=None, x_feat=0, y_feat=1, z_feat=2, label_feat=-1, title="Scatterplot"): """" Creates a 3D scatterplot of data with unique colors for each label :param @data: matrix of row vectors containing data feature and optionally labels @labels: optional vector of labels for the samples in @data @x_feat: which feature in @data to use for the x-axis @y_feat: which feature in @data to use for the y-axis @z_feat: which feature in @data to use for the z-axis @label_feat: which column in @data to use as labels (ignored if @labels is provided) @title: plot window title :returns None """ # Extract data and labels if no label vector is supplied if labels is None: labels = data[:, label_feat] data = np.delete(data, label_feat, axis=1) # Create a canvas and add view canvas = vispy.scene.SceneCanvas(title=title, keys='interactive', show=True) view = canvas.central_widget.add_view() # Separate data into point clouds based on label unique_labels = np.unique(labels) cm = Colormap(['r', 'g', 'b']) for y in unique_labels: cloud = data[np.where(labels.ravel() == y), :] cloud = np.squeeze(cloud, axis=0) # Define Colors y = y / len(unique_labels) color = cm[y] # Create scatter object and fill in the data scatter = visuals.Markers() scatter.set_data(cloud[:, [x_feat, y_feat, z_feat]], edge_color=None, face_color=color, size=5) view.add(scatter) # Define camara rotation view.camera = 'turntable' # or try 'arcball' # Add a colored 3D axis for orientation axis = visuals.XYZAxis(parent=view.scene)
def test_colormap_discrete(): """Test discrete RGB colormap""" with TestingCanvas(size=size, bgcolor='w') as c: idata = np.linspace(255, 0, size[0] * size[1]).astype(np.ubyte) data = idata.reshape((size[0], size[1])) image = Image(cmap=Colormap(colors=['r', 'g', 'b'], interpolation='zero'), clim='auto', parent=c.scene) image.set_data(data) assert_image_approved(c.render(), "visuals/colormap_rgb.png")
def test_colormap(): """Test colormap support for non-uniformly distributed control-points""" with TestingCanvas(size=size, bgcolor='w') as c: idata = np.linspace(255, 0, size[0] * size[1]).astype(np.ubyte) data = idata.reshape((size[0], size[1])) image = Image(cmap=Colormap(colors=['k', 'w', 'r'], controls=[0.0, 0.1, 1.0]), clim='auto', parent=c.scene) image.set_data(data) assert_image_approved(c.render(), "visuals/colormap_kwr.png")
def __init__(self, img=None): super(Viewer, self).__init__() # use empty image if none provided if img is None: self.img = np.zeros((256, 256)) else: self.img = img # class variables self.min_object_size = 25 self.background_label = 1 self.labels = np.zeros(self.img.shape, dtype=int) self.add_image(self.img, name='input') self.selem = morphology.selem.square(3) self.prob = None self.segmentation = None if len(img.shape) > 2: self.selem = np.array([self.selem]) # create empty heatmap label self.probability_heatmap = self.add_image(self.labels.astype(float), \ name="prediction probability") self.probability_heatmap.opacity = 0.0 self.colormap = Colormap([[0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 1.0], [0.0, 0.0, 0.0, 0.0]]) # add label layers self.add_labels(self.labels, name='output') self.add_labels(self.labels, name='train') self.layers['train'].opacity = 0.9 # define featurizers featurizer_dir = os.path.join( os.path.abspath(os.path.dirname(__file__)), "model", "saved_model") featurizer_paths = os.listdir(featurizer_dir) featurizer_paths = sorted( [os.path.join(featurizer_dir, path) for path in featurizer_paths]) featurizer_paths.append("filter") self.featurizers = cycle(featurizer_paths) self.cur_featurizer = next(self.featurizers) self.status = self.cur_featurizer.split("/")[-1] # key-bindings self.bind_key('Shift-S', self.segment) self.bind_key('Shift-H', self.show_heatmap) self.bind_key('Shift-N', self.next_featurizer) self.bind_key('Shift-D', self.dilation) self.bind_key('Shift-E', self.erosion) self.bind_key('Shift-C', self.closing) self.bind_key('Shift-O', self.opening) self.bind_key('Shift-F', self.fill_holes)
def setLookupTable(self, lut=None, update=True): try: table = self.HistogramLUTWidget.item.gradient.colorMap().color/256. pos = self.HistogramLUTWidget.item.gradient.colorMap().pos #table=np.clip(table*(self.levels[1]-self.levels[0])+self.levels[0],0.,1.) table[:, 3] = pos table = np.vstack([np.array([[0,0,0,0]]),table,np.array([[1,1,1,1]])]) pos = np.hstack([[0], pos*(self.levels[1] - self.levels[0]) + self.levels[0], [1]]) self.volumeRenderWidget.volume.cmap = Colormap(table, controls=pos) except AttributeError as ex: print ex
def test_colormap_discrete_nu(): """Test discrete colormap with non-uniformly distributed control-points""" with TestingCanvas(size=size, bgcolor='w') as c: idata = np.linspace(255, 0, size[0] * size[1]).astype(np.ubyte) data = idata.reshape((size[0], size[1])) image = Image(cmap=Colormap(np.array([[0, .75, 0], [.75, .25, .5]]), [0., .25, 1.], interpolation='zero'), clim='auto', parent=c.scene) image.set_data(data) assert_image_approved(c.render(), "visuals/colormap_nu.png")