diff --git a/CHANGES.md b/CHANGES.md index 1ed46afbd..5497777e4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -51,6 +51,11 @@ A UserWarning will be issued for the "stac" data store. +### Other changes + +* Renamed internal color mapping types from `"node"`, `"bound"`, `"key"` + into `"continuous"`, `"stepwise"`, `"categorical"`. + ## Changes in 1.6.0 ### Enhancements diff --git a/test/util/test_cmaps.py b/test/util/test_cmaps.py index 803eb10c0..14c64a9a9 100644 --- a/test/util/test_cmaps.py +++ b/test/util/test_cmaps.py @@ -106,13 +106,13 @@ def test_get_cmap_from_code_type_key(self): '[1, "#00000000"], ' '[2, "#ff0000aa"], ' '[5, "#ffffffff"]' - '], "type": "key"}' + '], "type": "categorical"}' ) self.assertIsInstance(cmap, matplotlib.colors.ListedColormap) self.assertIsInstance(cmap(np.linspace(0, 1, 10)), np.ndarray) self.assertIsInstance(colormap, Colormap) self.assertEqual("ucb783473", colormap.cm_name) - self.assertEqual("key", colormap.cm_type) + self.assertEqual("categorical", colormap.cm_type) self.assertEqual(CUSTOM_CATEGORY.name, colormap.cat_name) self.assertEqual([1, 2, 3, 5, 6], colormap.values) @@ -124,13 +124,13 @@ def test_get_cmap_from_code_type_bound(self): '[0.0, "#00000000"], ' '[0.6, "#ff0000aa"], ' '[1.0, "#ffffffff"]' - '], "type": "bound"}' + '], "type": "stepwise"}' ) self.assertIsInstance(cmap, matplotlib.colors.LinearSegmentedColormap) self.assertIsInstance(cmap(np.linspace(0, 1, 10)), np.ndarray) self.assertIsInstance(colormap, Colormap) self.assertEqual("ucb783474", colormap.cm_name) - self.assertEqual("bound", colormap.cm_type) + self.assertEqual("stepwise", colormap.cm_type) self.assertEqual(CUSTOM_CATEGORY.name, colormap.cat_name) self.assertEqual((0.0, 0.6, 1.0), colormap.values) @@ -148,7 +148,7 @@ def test_get_cmap_from_code_reversed_alpha(self): self.assertIsInstance(cmap(np.linspace(0, 1, 10)), np.ndarray) self.assertIsInstance(colormap, Colormap) self.assertEqual("ucb783475", colormap.cm_name) - self.assertEqual("node", colormap.cm_type) + self.assertEqual("continuous", colormap.cm_type) self.assertEqual(CUSTOM_CATEGORY.name, colormap.cat_name) self.assertEqual((0.0, 0.5, 1.0), colormap.values) @@ -160,7 +160,7 @@ def test_get_cmap_from_code_invalid(self): self.assertIsInstance(cmap, matplotlib.colors.LinearSegmentedColormap) self.assertIsInstance(colormap, Colormap) self.assertEqual("Reds", colormap.cm_name) - self.assertEqual("node", colormap.cm_type) + self.assertEqual("continuous", colormap.cm_type) self.assertEqual("Sequential", colormap.cat_name) self.assertIsNone(colormap.values) @@ -306,7 +306,7 @@ def setUp(self) -> None: def test_names(self): self.assertEqual("Diverging", self.colormap.cat_name) self.assertEqual("coolwarm", self.colormap.cm_name) - self.assertEqual("node", self.colormap.cm_type) + self.assertEqual("continuous", self.colormap.cm_type) def test_cmap(self): cmap = self.colormap.cmap diff --git a/xcube/core/tile.py b/xcube/core/tile.py index c427dd383..61d30ed37 100644 --- a/xcube/core/tile.py +++ b/xcube/core/tile.py @@ -502,7 +502,7 @@ def compute_rgba_tile( with measure_time("Encoding tile as RGBA image"): var_tile, value_range = var_tiles[0], value_ranges[0] - if colormap.cm_type == "key": + if colormap.cm_type == "categorical": assert isinstance(colormap.values, list) norm = matplotlib.colors.BoundaryNorm( colormap.values, ncolors=cmap.N, clip=False diff --git a/xcube/util/cmaps.py b/xcube/util/cmaps.py index d35c510c7..6e5109e24 100644 --- a/xcube/util/cmaps.py +++ b/xcube/util/cmaps.py @@ -18,7 +18,7 @@ from PIL import Image from xcube.constants import LOG -from xcube.util.assertions import assert_instance, assert_given +from xcube.util.assertions import assert_instance, assert_given, assert_in try: # noinspection PyPackageRequirements @@ -228,8 +228,12 @@ def __init__( norm: Optional[matplotlib.colors.Normalize] = None, values: Optional[Sequence[Union[int, float]]] = None, ): + assert_instance(cm_name, str) + if cm_type is None: + cm_type = "continuous" + assert_in(cm_type, ("continuous", "stepwise", "categorical")) self._cm_name = cm_name - self._cm_type = cm_type or "node" + self._cm_type = cm_type or "continuous" self._cat_name = cat_name self._cmap = cmap self._cmap_reversed = cmap_reversed @@ -246,7 +250,7 @@ def cm_name(self) -> str: @property def cm_type(self) -> str: - """The colormap type, always one of "node", "bound", "key".""" + """The colormap type, always one of "continuous", "stepwise", "categorical".""" return self._cm_type @property @@ -464,16 +468,15 @@ def _register_ocm_cmaps(self): def parse_cm_code(cm_code: str) -> tuple[str, Optional[Colormap]]: # Note, if we get performance issues here, we should - # cache cm_code -> colormap - values: Optional[list[Union[int, float]]] = None + # cache cm_code -> colormap. Currently, parsing takes less than 50 micros try: user_color_map: dict[str, Any] = json.loads(cm_code) cm_name = user_color_map["name"] cm_items = user_color_map["colors"] - cm_type = user_color_map.get("type", "node") + cm_type = user_color_map.get("type", "continuous") cm_base_name, _, _ = parse_cm_name(cm_name) n = len(cm_items) - if cm_type == "key": + if cm_type == "categorical": values: list[int] = [] colors: list[Union[str, tuple[float, ...]]] = [] bad = 0, 0, 0, 0 @@ -490,8 +493,7 @@ def parse_cm_code(cm_code: str) -> tuple[str, Optional[Colormap]]: colors.append(bad) cmap = matplotlib.colors.ListedColormap(colors, name=cm_base_name) cmap.set_extremes(bad=bad, under=bad, over=bad) - print(">>>>>>>>>>>> categorical cmap", cmap) - else: # cm_type == "bound" or cm_type == "node" + else: # cm_type == "continuous" or cm_type == "stepwise" values, colors = zip(*cm_items) vmin = cm_items[0][0] vmax = cm_items[-1][0] @@ -499,7 +501,7 @@ def parse_cm_code(cm_code: str) -> tuple[str, Optional[Colormap]]: # Normalize values of cm_items between 0 and 1 norm_values = (np.array(values) - vmin) / (vmax - vmin) cm_items = list(zip(norm_values, colors)) - if cm_type == "bound": + if cm_type == "stepwise": # Turn cm_items into discrete step function stepwise_cm_items = [] for i, (value, color) in enumerate(cm_items[0:-1]):