From 3fd53599c9c1302495c138d0a574baa60edffd6c Mon Sep 17 00:00:00 2001 From: David Stansby Date: Mon, 2 May 2022 10:50:13 +0100 Subject: [PATCH 1/2] Support 2D and RGB images for histograms --- CHANGELOG.rst | 12 ++++++++ src/napari_matplotlib/histogram.py | 29 ++++++++++++++++--- src/napari_matplotlib/tests/test_histogram.py | 9 ++++-- 3 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 CHANGELOG.rst diff --git a/CHANGELOG.rst b/CHANGELOG.rst new file mode 100644 index 00000000..fafd2e0b --- /dev/null +++ b/CHANGELOG.rst @@ -0,0 +1,12 @@ +0.0.2 +===== + +New features +------------ +- `HistogramWidget` now shows individual histograms for RGB channels when + present. + + +Bug fixes +--------- +- `HistogramWidget` now works properly with 2D images. diff --git a/src/napari_matplotlib/histogram.py b/src/napari_matplotlib/histogram.py index 066683bd..1cee9695 100644 --- a/src/napari_matplotlib/histogram.py +++ b/src/napari_matplotlib/histogram.py @@ -6,6 +6,9 @@ __all__ = ["HistogramWidget"] +_COLORS = {"r": "tab:red", "g": "tab:green", "b": "tab:blue"} + + class HistogramWidget(NapariMPLWidget): """ Widget to display a histogram of the currently selected layer. @@ -40,9 +43,27 @@ def hist_current_layer(self) -> None: """ self.axes.clear() layer = self.layer - z = self.viewer.dims.current_step[0] bins = np.linspace(np.min(layer.data), np.max(layer.data), 100) - data = layer.data[z] - self.axes.hist(data.ravel(), bins=bins) - self.axes.set_title(f"{layer.name}, z={z}") + + if layer.data.ndim - layer.rgb == 3: + # 3D data, can be single channel or RGB + data = layer.data[self.current_z] + self.axes.set_title(f"z={self.current_z}") + else: + data = layer.data + + if layer.rgb: + # Histogram RGB channels independently + for i, c in enumerate("rgb"): + self.axes.hist( + data[..., i].ravel(), + bins=bins, + label=c, + histtype="step", + color=_COLORS[c], + ) + else: + self.axes.hist(data.ravel(), bins=bins, label=layer.name) + + self.axes.legend() self.canvas.draw() diff --git a/src/napari_matplotlib/tests/test_histogram.py b/src/napari_matplotlib/tests/test_histogram.py index b3a4953e..6af8c4c7 100644 --- a/src/napari_matplotlib/tests/test_histogram.py +++ b/src/napari_matplotlib/tests/test_histogram.py @@ -1,10 +1,15 @@ import numpy as np +import pytest from napari_matplotlib import HistogramWidget -def test_example_q_widget(make_napari_viewer): +# Test with 2D and 3D data +@pytest.mark.parametrize( + "data", [np.random.random((100, 100)), np.random.random((100, 100, 100))] +) +def test_example_q_widget(make_napari_viewer, data): # Smoke test adding a histogram widget viewer = make_napari_viewer() - viewer.add_image(np.random.random((100, 100))) + viewer.add_image(data) HistogramWidget(viewer) From b67be6c5875414550448631b95b5774f6b9754b0 Mon Sep 17 00:00:00 2001 From: David Stansby Date: Mon, 2 May 2022 18:13:14 +0100 Subject: [PATCH 2/2] Test multiple data shapes --- src/napari_matplotlib/tests/conftest.py | 13 +++++++++++++ src/napari_matplotlib/tests/test_histogram.py | 11 ++--------- 2 files changed, 15 insertions(+), 9 deletions(-) create mode 100644 src/napari_matplotlib/tests/conftest.py diff --git a/src/napari_matplotlib/tests/conftest.py b/src/napari_matplotlib/tests/conftest.py new file mode 100644 index 00000000..274f1226 --- /dev/null +++ b/src/napari_matplotlib/tests/conftest.py @@ -0,0 +1,13 @@ +import numpy as np +import pytest + + +@pytest.fixture( + params=[ + ((100, 100), {"rgb": False}), + ((100, 100, 100), {"rgb": False}), + ((100, 100, 3), {"rgb": True}), + ] +) +def image_data(request): + return np.ones(request.param[0]), request.param[1] diff --git a/src/napari_matplotlib/tests/test_histogram.py b/src/napari_matplotlib/tests/test_histogram.py index 6af8c4c7..f497a1a9 100644 --- a/src/napari_matplotlib/tests/test_histogram.py +++ b/src/napari_matplotlib/tests/test_histogram.py @@ -1,15 +1,8 @@ -import numpy as np -import pytest - from napari_matplotlib import HistogramWidget -# Test with 2D and 3D data -@pytest.mark.parametrize( - "data", [np.random.random((100, 100)), np.random.random((100, 100, 100))] -) -def test_example_q_widget(make_napari_viewer, data): +def test_example_q_widget(make_napari_viewer, image_data): # Smoke test adding a histogram widget viewer = make_napari_viewer() - viewer.add_image(data) + viewer.add_image(image_data[0], **image_data[1]) HistogramWidget(viewer)