Skip to content

Commit

Permalink
Merge branch 'main' into fix-dt64-conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
sfinkens committed Jul 17, 2024
2 parents 964890c + 3a742c2 commit 4011541
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 34 deletions.
2 changes: 1 addition & 1 deletion continuous_integration/environment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,6 @@ dependencies:
- pip:
- pytest-lazy-fixtures
- trollsift
- trollimage>=1.23
- trollimage>=1.24
- pyspectral
- pyorbital
9 changes: 9 additions & 0 deletions doc/source/enhancements.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,15 @@ the example here::
- {colors: spectral, min_value: 193.15, max_value: 253.149999}
- {colors: greys, min_value: 253.15, max_value: 303.15}

In addition, it is also possible to add a linear alpha channel to the colormap, as in the
following example::

- name: colorize
method: !!python/name:satpy.enhancements.colorize
kwargs:
palettes:
- {colors: ylorrd, min_alpha: 100, max_alpha: 255}

It is also possible to provide your own custom defined color mapping by
specifying a list of RGB values and the corresponding min and max values
between which to apply the colors. This is for instance a common use case for
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ dependencies = [
"pyproj>=2.2",
"pyresample>=1.24.0",
"pyyaml>=5.1",
"trollimage>=1.23",
"trollimage>=1.24",
"trollsift",
"xarray>=0.14.1",
"zarr",
Expand Down
8 changes: 4 additions & 4 deletions satpy/composites/glm.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,19 @@ def __init__(self, name, min_highlight=0.0, max_highlight=10.0, # noqa: D417
Args:
min_highlight (float): Minimum raw value of the "highlight" data
that will be used for linearly scaling the data along with
``max_hightlight``.
``max_highlight``.
max_highlight (float): Maximum raw value of the "highlight" data
that will be used for linearly scaling the data along with
``min_hightlight``.
``min_highlight``.
max_factor (tuple): Maximum effect that the highlight data can
have on each channel of the primary image data. This will be
multiplied by the linearly scaled highlight data and then
added or subtracted from the highlight channels. See class
docstring for more information. By default this is set to
``(0.8, 0.8, -0.8, 0)`` meaning the Red and Green channel
will be added to by at most 0.8, the Blue channel will be
subtracted from by at most 0.8, and the Alpha channel will
not be effected.
subtracted from by at most 0.8 (resulting in yellow highlights),
and the Alpha channel will not be affected.
"""
self.min_highlight = min_highlight
Expand Down
40 changes: 29 additions & 11 deletions satpy/enhancements/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ def create_colormap(palette, img=None): # noqa: D417
Colormaps can be loaded from lists of colors provided by the ``colors``
key in the provided dictionary. Each element in the list represents a
single color to be mapped to and can be 3 (RGB) or 4 (RGBA) elements long.
By default the value or control point for a color is determined by the
By default, the value or control point for a color is determined by the
index in the list (0, 1, 2, ...) divided by the total number of colors
to produce a number between 0 and 1. This can be overridden by providing a
``values`` key in the provided dictionary. See the "Set Range" section
Expand Down Expand Up @@ -455,12 +455,37 @@ def create_colormap(palette, img=None): # noqa: D417
``max_value``. See :meth:`trollimage.colormap.Colormap.set_range` for more
information.
**Set Alpha Range**
The alpha channel of a created colormap can be added and/or modified by
specifying ``min_alpha`` and ``max_alpha``.
See :meth:`trollimage.colormap.Colormap.set_alpha_range` for more info.
"""
# are colors between 0-255 or 0-1
color_scale = palette.get("color_scale", 255)
cmap = _get_cmap_from_palette_info(palette, img, color_scale)

if palette.get("reverse", False):
cmap.reverse()
if "min_value" in palette and "max_value" in palette:
cmap.set_range(palette["min_value"], palette["max_value"])
elif "min_value" in palette or "max_value" in palette:
raise ValueError("Both 'min_value' and 'max_value' must be specified (or neither).")

if "min_alpha" in palette and "max_alpha" in palette:
cmap.set_alpha_range(palette["min_alpha"] / color_scale,
palette["max_alpha"] / color_scale)
elif "min_alpha" in palette or "max_alpha" in palette:
raise ValueError("Both 'min_alpha' and 'max_alpha' must be specified (or neither).")

return cmap


def _get_cmap_from_palette_info(palette, img, color_scale):
fname = palette.get("filename", None)
colors = palette.get("colors", None)
dataset = palette.get("dataset", None)
# are colors between 0-255 or 0-1
color_scale = palette.get("color_scale", 255)
if fname:
if not os.path.exists(fname):
fname = get_config_path(fname)
Expand All @@ -473,17 +498,10 @@ def create_colormap(palette, img=None): # noqa: D417
cmap = _create_colormap_from_dataset(img, dataset, color_scale)
else:
raise ValueError("Unknown colormap format: {}".format(palette))

if palette.get("reverse", False):
cmap.reverse()
if "min_value" in palette and "max_value" in palette:
cmap.set_range(palette["min_value"], palette["max_value"])
elif "min_value" in palette or "max_value" in palette:
raise ValueError("Both 'min_value' and 'max_value' must be specified (or neither)")

return cmap



def _create_colormap_from_dataset(img, dataset, color_scale):
"""Create a colormap from an auxiliary variable in a source file."""
match = find_in_ancillary(img.data, dataset)
Expand Down
68 changes: 51 additions & 17 deletions satpy/tests/enhancement_tests/test_enhancements.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,24 +331,57 @@ def test_cmap_from_file(self, color_scale, colormap_mode, extra_kwargs, filename
kwargs1["color_scale"] = color_scale

cmap = create_colormap(kwargs1)
assert cmap.colors.shape[0] == 4
np.testing.assert_equal(cmap.colors[0], first_color)
assert cmap.values.shape[0] == 4
assert cmap.values[0] == unset_first_value
assert cmap.values[-1] == unset_last_value

assert cmap.colors.shape[0] == 4
np.testing.assert_equal(cmap.colors[0], first_color)
assert cmap.values.shape[0] == 4
assert cmap.values[0] == unset_first_value
assert cmap.values[-1] == unset_last_value

def test_cmap_vrgb_as_rgba(self):
"""Test that data created as VRGB still reads as RGBA."""
with closed_named_temp_file(suffix=".npy") as cmap_filename:
cmap_data = _generate_cmap_test_data(None, "VRGB")
np.save(cmap_filename, cmap_data)
cmap = create_colormap({"filename": cmap_filename, "colormap_mode": "RGBA"})
assert cmap.colors.shape[0] == 4
assert cmap.colors.shape[1] == 4 # RGBA
np.testing.assert_equal(cmap.colors[0], [128 / 255., 1.0, 0, 0])
assert cmap.values.shape[0] == 4
assert cmap.values[0] == 0
assert cmap.values[-1] == 1.0

assert cmap.colors.shape[0] == 4
assert cmap.colors.shape[1] == 4 # RGBA
np.testing.assert_equal(cmap.colors[0], [128 / 255., 1.0, 0, 0])
assert cmap.values.shape[0] == 4
assert cmap.values[0] == 0
assert cmap.values[-1] == 1.0

def test_cmap_with_alpha_set(self):
"""Test that the min_alpha and max_alpha arguments set the alpha channel correctly."""
with closed_named_temp_file(suffix=".npy") as cmap_filename:
cmap_data = _generate_cmap_test_data(None, "RGB")
np.save(cmap_filename, cmap_data)
cmap = create_colormap({"filename": cmap_filename, "min_alpha": 100, "max_alpha": 255})

assert cmap.colors.shape[0] == 4
assert cmap.colors.shape[1] == 4 # RGBA
# check that we start from min_alpha
np.testing.assert_equal(cmap.colors[0], [1.0, 0, 0, 100/255.])
# two thirds of the linear scale
np.testing.assert_almost_equal(cmap.colors[2], [1., 1., 1., (100+(2/3)*(255-100))/255])
# check that we end at max_alpha
np.testing.assert_equal(cmap.colors[3], [0, 0, 1., 1.0])
# check that values have not been changed
assert cmap.values.shape[0] == 4
assert cmap.values[0] == 0
assert cmap.values[-1] == 1.0

@pytest.mark.parametrize("alpha_arg", ["max_alpha", "min_alpha"])
def test_cmap_error_with_only_one_alpha_set(self, alpha_arg):
"""Test that when only min_alpha or max_alpha arguments are set an error is raised."""
with closed_named_temp_file(suffix=".npy") as cmap_filename:
cmap_data = _generate_cmap_test_data(None, "RGB")
np.save(cmap_filename, cmap_data)

# check that if a value is missing we raise a ValueError
with pytest.raises(ValueError, match="Both 'min_alpha' and 'max_alpha' must be specified*."):
create_colormap({"filename": cmap_filename, alpha_arg: 255})

@pytest.mark.parametrize(
("real_mode", "forced_mode"),
Expand Down Expand Up @@ -397,12 +430,13 @@ def test_cmap_from_config_path(self, tmp_path):
with satpy.config.set(config_path=[tmp_path]):
rel_cmap_filename = os.path.join("colormaps", "my_colormap.npy")
cmap = create_colormap({"filename": rel_cmap_filename, "colormap_mode": "RGBA"})
assert cmap.colors.shape[0] == 4
assert cmap.colors.shape[1] == 4 # RGBA
np.testing.assert_equal(cmap.colors[0], [128 / 255., 1.0, 0, 0])
assert cmap.values.shape[0] == 4
assert cmap.values[0] == 0
assert cmap.values[-1] == 1.0

assert cmap.colors.shape[0] == 4
assert cmap.colors.shape[1] == 4 # RGBA
np.testing.assert_equal(cmap.colors[0], [128 / 255., 1.0, 0, 0])
assert cmap.values.shape[0] == 4
assert cmap.values[0] == 0
assert cmap.values[-1] == 1.0

def test_cmap_from_trollimage(self):
"""Test that colormaps in trollimage can be loaded."""
Expand Down

0 comments on commit 4011541

Please sign in to comment.