From cb25850ae6927e9426063e74599afdd2abb8e4c0 Mon Sep 17 00:00:00 2001 From: Genevieve Buckley <30920819+GenevieveBuckley@users.noreply.github.com> Date: Fri, 14 Jun 2024 16:18:22 +1000 Subject: [PATCH 1/7] Replace colormap code with inbuilt napari colormap functions --- napari_tiff/napari_tiff_colormaps.py | 44 +--------------------------- napari_tiff/napari_tiff_metadata.py | 12 +++----- 2 files changed, 5 insertions(+), 51 deletions(-) diff --git a/napari_tiff/napari_tiff_colormaps.py b/napari_tiff/napari_tiff_colormaps.py index 524d54a..ef89e6e 100644 --- a/napari_tiff/napari_tiff_colormaps.py +++ b/napari_tiff/napari_tiff_colormaps.py @@ -1,5 +1,5 @@ import numpy -from vispy.color import Colormap +from napari.utils import Colormap def alpha_colormap(bitspersample=8, samples=4): @@ -11,48 +11,6 @@ def alpha_colormap(bitspersample=8, samples=4): return Colormap(a) -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 cmyk_colormaps(bitspersample=8, samples=3): - """Return CMYK colormaps.""" - n = 2**bitspersample - ramp = numpy.linspace(1.0, 0.0, n).astype("float32") - c = numpy.zeros((n, samples), dtype="float32") - c[:, 1] = ramp - c[:, 2] = ramp - m = numpy.zeros((n, samples), dtype="float32") - m[:, 0] = ramp - m[:, 2] = ramp - y = numpy.zeros((n, samples), dtype="float32") - y[:, 0] = ramp - y[:, 1] = ramp - k = numpy.zeros((n, samples), dtype="float32") - k[:, 0] = ramp - k[:, 1] = ramp - k[:, 2] = ramp - if samples > 3: - c[:, 3:] = 1.0 - m[:, 3:] = 1.0 - y[:, 3:] = 1.0 - k[:, 3:] = 1.0 - return [Colormap(c), Colormap(m), Colormap(y), Colormap(k)] - - def int_to_rgba(intrgba: int) -> tuple: signed = intrgba < 0 rgba = [x / 255 for x in intrgba.to_bytes(4, signed=signed, byteorder="big")] diff --git a/napari_tiff/napari_tiff_metadata.py b/napari_tiff/napari_tiff_metadata.py index 2ddd2c0..51e349a 100644 --- a/napari_tiff/napari_tiff_metadata.py +++ b/napari_tiff/napari_tiff_metadata.py @@ -3,13 +3,9 @@ import numpy from tifffile import PHOTOMETRIC, TiffFile, xml2dict from vispy.color import Colormap +from napari.utils.colormaps import ALL_COLORMAPS -from napari_tiff.napari_tiff_colormaps import ( - alpha_colormap, - cmyk_colormaps, - int_to_rgba, - rgb_colormaps, -) +from napari_tiff.napari_tiff_colormaps import alpha_colormap, int_to_rgba def get_metadata(tif: TiffFile) -> dict[str, Any]: @@ -75,7 +71,7 @@ def get_tiff_metadata(tif: TiffFile) -> dict[str, Any]: # CMYK channel_axis = axes.find("S") if channel_axis >= 0 and shape[channel_axis] >= 4: - colormap = cmyk_colormaps() + colormap = [ALL_COLORMAPS["cyan"], ALL_COLORMAPS["magenta"], ALL_COLORMAPS["yellow"], ALL_COLORMAPS["gray"]] name = ["Cyan", "Magenta", "Yellow", "Black"] visible = [False, False, False, True] blending = ["additive", "additive", "additive", "additive"] @@ -243,7 +239,7 @@ def get_imagej_metadata(tif: TiffFile) -> dict[str, Any]: rgb = False n = shape[channel_axis] visible = [True, True, True] - colormap = rgb_colormaps(samples=4)[:n] + colormap = [ALL_COLORMAPS["red"], ALL_COLORMAPS["green"], ALL_COLORMAPS["blue"]] name = ["Red", "Green", "Blue", "Alpha"][:n] blending = ["additive", "additive", "additive", "translucent"][:n] else: From 39db19071c342c73b69350bc17cd90c6b93b2a36 Mon Sep 17 00:00:00 2001 From: Genevieve Buckley <30920819+GenevieveBuckley@users.noreply.github.com> Date: Fri, 14 Jun 2024 16:32:31 +1000 Subject: [PATCH 2/7] Add napari dependency, remove vispy dependency --- napari_tiff/napari_tiff_metadata.py | 3 +-- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/napari_tiff/napari_tiff_metadata.py b/napari_tiff/napari_tiff_metadata.py index 51e349a..394e40e 100644 --- a/napari_tiff/napari_tiff_metadata.py +++ b/napari_tiff/napari_tiff_metadata.py @@ -2,8 +2,7 @@ import numpy from tifffile import PHOTOMETRIC, TiffFile, xml2dict -from vispy.color import Colormap -from napari.utils.colormaps import ALL_COLORMAPS +from napari.utils.colormaps import ALL_COLORMAPS, Colormap from napari_tiff.napari_tiff_colormaps import alpha_colormap, int_to_rgba diff --git a/pyproject.toml b/pyproject.toml index 294bccc..c049f80 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,9 +28,9 @@ classifiers = [ requires-python = '>=3.10' dependencies = [ 'imagecodecs', + 'napari', 'numpy', 'tifffile>=2023.9.26', - 'vispy', 'zarr', ] From c14c9539b4c6976dec30b8908727987beb89c1b4 Mon Sep 17 00:00:00 2001 From: Genevieve Buckley <30920819+GenevieveBuckley@users.noreply.github.com> Date: Mon, 17 Jun 2024 16:55:46 +1000 Subject: [PATCH 3/7] Simplify napari colormap input further --- napari_tiff/napari_tiff_metadata.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/napari_tiff/napari_tiff_metadata.py b/napari_tiff/napari_tiff_metadata.py index 394e40e..d2c2f2a 100644 --- a/napari_tiff/napari_tiff_metadata.py +++ b/napari_tiff/napari_tiff_metadata.py @@ -2,7 +2,7 @@ import numpy from tifffile import PHOTOMETRIC, TiffFile, xml2dict -from napari.utils.colormaps import ALL_COLORMAPS, Colormap +from napari.utils.colormaps import Colormap from napari_tiff.napari_tiff_colormaps import alpha_colormap, int_to_rgba @@ -70,7 +70,7 @@ def get_tiff_metadata(tif: TiffFile) -> dict[str, Any]: # CMYK channel_axis = axes.find("S") if channel_axis >= 0 and shape[channel_axis] >= 4: - colormap = [ALL_COLORMAPS["cyan"], ALL_COLORMAPS["magenta"], ALL_COLORMAPS["yellow"], ALL_COLORMAPS["gray"]] + colormap = ["cyan", "magenta", "yellow", "gray"] name = ["Cyan", "Magenta", "Yellow", "Black"] visible = [False, False, False, True] blending = ["additive", "additive", "additive", "additive"] @@ -238,7 +238,7 @@ def get_imagej_metadata(tif: TiffFile) -> dict[str, Any]: rgb = False n = shape[channel_axis] visible = [True, True, True] - colormap = [ALL_COLORMAPS["red"], ALL_COLORMAPS["green"], ALL_COLORMAPS["blue"]] + colormap = ["red", "green", "blue", alpha_colormap()] name = ["Red", "Green", "Blue", "Alpha"][:n] blending = ["additive", "additive", "additive", "translucent"][:n] else: From c6a4b34f15745e36aa5d456100197c89a4ffbd22 Mon Sep 17 00:00:00 2001 From: Genevieve Buckley <30920819+GenevieveBuckley@users.noreply.github.com> Date: Tue, 18 Jun 2024 13:28:32 +1000 Subject: [PATCH 4/7] Remove napari dependency --- napari_tiff/napari_tiff_colormaps.py | 7 +++---- napari_tiff/napari_tiff_metadata.py | 3 +-- napari_tiff/napari_tiff_reader.py | 2 +- pyproject.toml | 1 - 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/napari_tiff/napari_tiff_colormaps.py b/napari_tiff/napari_tiff_colormaps.py index ef89e6e..fc35cac 100644 --- a/napari_tiff/napari_tiff_colormaps.py +++ b/napari_tiff/napari_tiff_colormaps.py @@ -1,14 +1,13 @@ import numpy -from napari.utils import Colormap 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) + alpha_cmap = numpy.zeros((n, samples), dtype="float32") + alpha_cmap[:, 3] = ramp[::-1] + return alpha_cmap def int_to_rgba(intrgba: int) -> tuple: diff --git a/napari_tiff/napari_tiff_metadata.py b/napari_tiff/napari_tiff_metadata.py index d2c2f2a..c4a25dc 100644 --- a/napari_tiff/napari_tiff_metadata.py +++ b/napari_tiff/napari_tiff_metadata.py @@ -2,7 +2,6 @@ import numpy from tifffile import PHOTOMETRIC, TiffFile, xml2dict -from napari.utils.colormaps import Colormap from napari_tiff.napari_tiff_colormaps import alpha_colormap, int_to_rgba @@ -151,7 +150,7 @@ def get_tiff_metadata(tif: TiffFile) -> dict[str, Any]: colormap = colormap / 65535.0 else: colormap = colormap / 255.0 - colormap = Colormap(colormap.astype("float32").T) + colormap = colormap.astype("float32").T if colormap is None and page.photometric == 0: # MINISBLACK diff --git a/napari_tiff/napari_tiff_reader.py b/napari_tiff/napari_tiff_reader.py index dcffb76..2e70a5b 100644 --- a/napari_tiff/napari_tiff_reader.py +++ b/napari_tiff/napari_tiff_reader.py @@ -12,7 +12,7 @@ from typing import Any, Callable, Dict, List, Optional, Tuple, Union -from tifffile import TIFF, TiffFile, TiffSequence, xml2dict +from tifffile import TIFF, TiffFile, TiffSequence from napari_tiff.napari_tiff_metadata import get_metadata diff --git a/pyproject.toml b/pyproject.toml index c049f80..c783e37 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,6 @@ classifiers = [ requires-python = '>=3.10' dependencies = [ 'imagecodecs', - 'napari', 'numpy', 'tifffile>=2023.9.26', 'zarr', From 5b57ce970d21b6896246ab99f102ed89809e0f85 Mon Sep 17 00:00:00 2001 From: Genevieve Buckley <30920819+GenevieveBuckley@users.noreply.github.com> Date: Wed, 26 Jun 2024 17:28:20 +1000 Subject: [PATCH 5/7] Update napari_tiff/napari_tiff_colormaps.py Co-authored-by: Grzegorz Bokota --- napari_tiff/napari_tiff_colormaps.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/napari_tiff/napari_tiff_colormaps.py b/napari_tiff/napari_tiff_colormaps.py index fc35cac..f289b89 100644 --- a/napari_tiff/napari_tiff_colormaps.py +++ b/napari_tiff/napari_tiff_colormaps.py @@ -7,7 +7,7 @@ def alpha_colormap(bitspersample=8, samples=4): ramp = numpy.linspace(0.0, 1.0, n).astype("float32") alpha_cmap = numpy.zeros((n, samples), dtype="float32") alpha_cmap[:, 3] = ramp[::-1] - return alpha_cmap + return {"name": "alpha", "colors": alpha_cmap} def int_to_rgba(intrgba: int) -> tuple: From bf90b95106fec0f9583a75e19c60418252c5d910 Mon Sep 17 00:00:00 2001 From: Genevieve Buckley <30920819+GenevieveBuckley@users.noreply.github.com> Date: Thu, 27 Jun 2024 14:34:49 +1000 Subject: [PATCH 6/7] Use PHOTOMETRIC Enum for easier readability --- napari_tiff/napari_tiff_metadata.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/napari_tiff/napari_tiff_metadata.py b/napari_tiff/napari_tiff_metadata.py index c4a25dc..866dd80 100644 --- a/napari_tiff/napari_tiff_metadata.py +++ b/napari_tiff/napari_tiff_metadata.py @@ -56,7 +56,7 @@ def get_tiff_metadata(tif: TiffFile) -> dict[str, Any]: page = next(p for p in series.pages if p is not None) extrasamples = page.extrasamples - rgb = page.photometric in (2, 6) and shape[-1] in (3, 4) + rgb = page.photometric in (PHOTOMETRIC.RGB, PHOTOMETRIC.YCBCR) and shape[-1] in (3, 4) name = None scale = None colormap = None @@ -65,7 +65,7 @@ def get_tiff_metadata(tif: TiffFile) -> dict[str, Any]: channel_axis = None visible = True - if page.photometric == 5: + if page.photometric == PHOTOMETRIC.SEPARATED: # CMYK channel_axis = axes.find("S") if channel_axis >= 0 and shape[channel_axis] >= 4: @@ -76,7 +76,7 @@ def get_tiff_metadata(tif: TiffFile) -> dict[str, Any]: # TODO: use subtractive blending else: channel_axis = None - elif page.photometric in (2, 6) and ( + elif page.photometric in (PHOTOMETRIC.RGB, PHOTOMETRIC.YCBCR) and ( page.planarconfig == 2 or (page.bitspersample > 8 and dtype.kind in "iu") or (extrasamples and len(extrasamples) > 1) @@ -92,7 +92,7 @@ def get_tiff_metadata(tif: TiffFile) -> dict[str, Any]: else: channel_axis = None elif ( - page.photometric in (0, 1) + page.photometric in (PHOTOMETRIC.MINISWHITE, PHOTOMETRIC.MINISBLACK) and extrasamples and any(sample > 0 for sample in extrasamples) ): @@ -101,7 +101,7 @@ def get_tiff_metadata(tif: TiffFile) -> dict[str, Any]: if channel_axis >= 0: visible = [True] colormap = ["gray"] - name = ["Minisblack" if page.photometric == 1 else "Miniswhite"] + name = ["Minisblack" if page.photometric == PHOTOMETRIC.MINISBLACK else "Miniswhite"] blending = ["additive"] else: channel_axis = None @@ -123,7 +123,7 @@ def get_tiff_metadata(tif: TiffFile) -> dict[str, Any]: name.append("Alpha") blending.append("translucent") - if channel_axis is None and page.photometric in (0, 1): + if channel_axis is None and page.photometric in (PHOTOMETRIC.MINISWHITE, PHOTOMETRIC.MINISBLACK): # separate up to 3 samples in grayscale images channel_axis = axes.find("S") if channel_axis >= 0 and 1 < shape[channel_axis] < 4: @@ -143,7 +143,7 @@ def get_tiff_metadata(tif: TiffFile) -> dict[str, Any]: else: channel_axis = None - if page.photometric == 3 and page.colormap is not None: + if page.photometric == PHOTOMETRIC.PALETTE and page.colormap is not None: # PALETTE colormap = page.colormap if numpy.max(colormap) > 255: @@ -152,14 +152,14 @@ def get_tiff_metadata(tif: TiffFile) -> dict[str, Any]: colormap = colormap / 255.0 colormap = colormap.astype("float32").T - if colormap is None and page.photometric == 0: - # MINISBLACK + if colormap is None and page.photometric == PHOTOMETRIC.MINISWHITE: + # MINISWHITE colormap = "gray_r" if ( contrast_limits is None and dtype.kind == "u" - and page.photometric != 3 + and page.photometric != PHOTOMETRIC.PALETTE and page.bitspersample not in (8, 16, 32, 64) ): contrast_limits = (0, 2**page.bitspersample) @@ -189,7 +189,7 @@ def get_imagej_metadata(tif: TiffFile) -> dict[str, Any]: axes = series.axes shape = series.shape page = series.pages[0] - rgb = page.photometric == 2 and shape[-1] in (3, 4) + rgb = page.photometric == PHOTOMETRIC.RGB and shape[-1] in (3, 4) mode = ijmeta.get("mode", None) channels = ijmeta.get("channels", 1) channel_axis = None From 8102c811519879add83baf2c630c89d4d5862b1c Mon Sep 17 00:00:00 2001 From: Genevieve Buckley <30920819+GenevieveBuckley@users.noreply.github.com> Date: Thu, 27 Jun 2024 14:44:20 +1000 Subject: [PATCH 7/7] Use new alpha colormap --- napari_tiff/napari_tiff_metadata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/napari_tiff/napari_tiff_metadata.py b/napari_tiff/napari_tiff_metadata.py index 866dd80..5e3bd0b 100644 --- a/napari_tiff/napari_tiff_metadata.py +++ b/napari_tiff/napari_tiff_metadata.py @@ -325,7 +325,7 @@ def get_ome_tiff_metadata(tif: TiffFile) -> dict[str, Any]: colormap = int_to_rgba(int(color)) elif is_rgb and len(channels) > 1: # separate channels provided for RGB (with missing color) - colormap = ["red", "green", "blue", "alpha"][channeli] + colormap = ["red", "green", "blue", alpha_colormap()][channeli] if not name: name = colormap