def test_image_clims_and_gamma(input_dtype, texture_format, num_channels, clim_on_init, data_on_init): """Test image visual with clims and gamma on shader.""" size = (40, 40) if texture_format == '__dtype__': texture_format = input_dtype shape = size + (num_channels, ) if num_channels > 0 else size np.random.seed(0) data = _make_test_data(shape, input_dtype) orig_clim, new_clim = _get_orig_and_new_clims(input_dtype) # 16-bit integers and above seem to have precision loss when scaled on the CPU is_16int_cpu_scaled = (np.dtype(input_dtype).itemsize >= 2 and np.issubdtype(input_dtype, np.integer) and texture_format is None) clim_atol = 2 if is_16int_cpu_scaled else 1 gamma_atol = 3 if is_16int_cpu_scaled else 2 kwargs = {} if clim_on_init: kwargs['clim'] = orig_clim if data_on_init: kwargs['data'] = data # default is RGBA, anything except auto requires reformat set_data_fails = (num_channels != 4 and texture_format is not None and texture_format != 'auto') with TestingCanvas(size=size[::-1], bgcolor="w") as c: image = Image(cmap='grays', texture_format=texture_format, parent=c.scene, **kwargs) if not data_on_init: _set_image_data(image, data, set_data_fails) if set_data_fails: return rendered = c.render() _dtype = rendered.dtype shape_ratio = rendered.shape[0] // data.shape[0] rendered1 = downsample(rendered, shape_ratio, axis=(0, 1)).astype(_dtype) _compare_render(data, rendered1) # adjust color limits image.clim = new_clim rendered2 = downsample(c.render(), shape_ratio, axis=(0, 1)).astype(_dtype) scaled_data = (np.clip(data, new_clim[0], new_clim[1]) - new_clim[0]) / (new_clim[1] - new_clim[0]) _compare_render(scaled_data, rendered2, rendered1, atol=clim_atol) # adjust gamma image.gamma = 2 rendered3 = downsample(c.render(), shape_ratio, axis=(0, 1)).astype(_dtype) _compare_render(scaled_data**2, rendered3, rendered2, atol=gamma_atol)
def test_volume_clims_and_gamma(): """Test volume visual with clims and gamma on shader. currently just using np.ones since the angle of view made more complicated samples challenging, but this confirms gamma and clims works in the shader. """ with TestingCanvas(size=(40, 40), bgcolor="k") as c: v = c.central_widget.add_view(border_width=0, size=(40, 40)) data = np.ones((40, 40, 40)) / 2.5 volume = scene.visuals.Volume( data, clim=(0, 1), interpolation='nearest', parent=v.scene, method='mip', ) v.camera = 'arcball' v.camera.fov = 0 v.camera.scale_factor = 40 v.camera.center = (19.5, 19.5, 19.5) rendered = c.render()[..., 0] _dtype = rendered.dtype shape_ratio = rendered.shape[0] // data.shape[0] rendered1 = downsample(rendered, shape_ratio, axis=(0, 1)).astype(_dtype) predicted = np.round(data.max(0) * 255).astype(np.uint8) assert np.allclose(predicted, rendered1, atol=1) # adjust contrast limits new_clim = (0.3, 0.8) volume.clim = new_clim rendered2 = downsample(c.render()[..., 0], shape_ratio, axis=(0, 1)).astype(_dtype) scaled_data = np.clip((data - new_clim[0]) / np.diff(new_clim)[0], 0, 1) predicted = np.round(scaled_data.max(0) * 255).astype(np.uint8) assert np.allclose(predicted, rendered2) assert not np.allclose(rendered1, rendered2, atol=10) # adjust gamma volume.gamma = 1.5 rendered3 = downsample(c.render()[..., 0], shape_ratio, axis=(0, 1)).astype(_dtype) predicted = np.round( (scaled_data**volume.gamma).max(0) * 255).astype(np.uint8) assert np.allclose(predicted, rendered3) assert not np.allclose(rendered2, rendered3, atol=10)
def test_image_clims_and_gamma(): """Test image visual with clims and gamma on shader.""" size = (40, 40) with TestingCanvas(size=size, bgcolor="w") as c: for three_d in (True,): shape = size + ((3,) if three_d else ()) np.random.seed(0) image = Image(cmap='grays', clim=[0, 1], parent=c.scene) data = np.random.rand(*shape) image.set_data(data) rendered = c.render() _dtype = rendered.dtype shape_ratio = rendered.shape[0] // data.shape[0] rendered1 = downsample(rendered, shape_ratio, axis=(0, 1)).astype(_dtype) predicted = _make_rgba(data) assert np.allclose(predicted, rendered1, atol=1) # adjust contrast limits new_clim = (0.3, 0.8) image.clim = new_clim rendered2 = downsample(c.render(), shape_ratio, axis=(0, 1)).astype(_dtype) scaled_data = np.clip((data - new_clim[0]) / np.diff(new_clim)[0], 0, 1) predicted = _make_rgba(scaled_data) assert np.allclose(predicted, rendered2, atol=1) assert not np.allclose(rendered1, rendered2, atol=10) # adjust gamma image.gamma = 2 rendered3 = downsample(c.render(), shape_ratio, axis=(0, 1)).astype(_dtype) predicted = _make_rgba(scaled_data ** 2) assert np.allclose( predicted.astype(np.float), rendered3.astype(np.float), atol=2 ) assert not np.allclose( rendered2.astype(np.float), rendered3.astype(np.float), atol=10 )
def test_volume_clims_and_gamma(texture_format, input_dtype, clim_on_init): """Test volume visual with clims and gamma on shader. Test is parameterized based on ``texture_format`` and should produce relatively the same results for each format. Currently just using np.ones since the angle of view made more complicated samples challenging, but this confirms gamma and clims works in the shader. The VolumeVisual defaults to the "grays" colormap so although we compare data using RGBA arrays, each R/G/B channel should be the same. """ size = (40, 40) if texture_format == '__dtype__': texture_format = input_dtype np.random.seed(0) # make tests the same every time data = _make_test_data(size[:1] * 3, input_dtype) clim = (0, 1) new_clim = (0.3, 0.8) max = max_for_dtype(input_dtype) if max != 1: clim = (clim[0] * max, clim[1] * max) new_clim = (new_clim[0] * max, new_clim[1] * max) kwargs = {} if clim_on_init: kwargs['clim'] = clim with TestingCanvas(size=size, bgcolor="k") as c: v = c.central_widget.add_view(border_width=0) volume = scene.visuals.Volume(data, interpolation='nearest', parent=v.scene, method='mip', texture_format=texture_format, **kwargs) v.camera = 'arcball' v.camera.fov = 0 v.camera.scale_factor = 40.0 v.camera.center = (19.5, 19.5, 19.5) rendered = c.render() _dtype = rendered.dtype shape_ratio = rendered.shape[0] // data.shape[0] rendered1 = downsample(rendered, shape_ratio, axis=(0, 1)).astype(_dtype) predicted = data.max(axis=1) compare_render(predicted, rendered1) # adjust contrast limits volume.clim = new_clim rendered2 = downsample(c.render(), shape_ratio, axis=(0, 1)).astype(_dtype) scaled_data = (np.clip(data, new_clim[0], new_clim[1]) - new_clim[0]) / (new_clim[1] - new_clim[0]) predicted = scaled_data.max(axis=1) compare_render(predicted, rendered2, previous_render=rendered) # adjust gamma volume.gamma = 2 rendered3 = downsample(c.render(), shape_ratio, axis=(0, 1)).astype(_dtype) predicted = (scaled_data**2).max(axis=1) compare_render(predicted, rendered3, previous_render=rendered2)