From 8297b37a43ba079160b1db32406e2d9e142bbcae Mon Sep 17 00:00:00 2001 From: Tim Treis Date: Thu, 3 Aug 2023 11:12:45 +0000 Subject: [PATCH 1/4] Fix for shapes --- src/spatialdata_plot/pl/basic.py | 2 +- src/spatialdata_plot/pl/render.py | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/spatialdata_plot/pl/basic.py b/src/spatialdata_plot/pl/basic.py index ae4ff340..119c48de 100644 --- a/src/spatialdata_plot/pl/basic.py +++ b/src/spatialdata_plot/pl/basic.py @@ -151,7 +151,7 @@ def render_shapes( layer: str | None = None, palette: ListedColormap | str | None = None, cmap: Colormap | str | None = None, - norm: None | Normalize = None, + norm: bool | Normalize = True, na_color: str | tuple[float, ...] | None = "lightgrey", outline_alpha: float = 1.0, fill_alpha: float = 1.0, diff --git a/src/spatialdata_plot/pl/render.py b/src/spatialdata_plot/pl/render.py index 274f65df..33a5a170 100644 --- a/src/spatialdata_plot/pl/render.py +++ b/src/spatialdata_plot/pl/render.py @@ -176,6 +176,11 @@ def _get_collection_shape( outline_alpha=render_params.outline_alpha # **kwargs, ) + + # Sets the limits of the colorbar to the values instead of [0, 1] + if not norm: + _cax.set_clim(min(color_vector), max(color_vector)) + cax = ax.add_collection(_cax) palette = ListedColormap(set(color_vector)) if render_params.palette is None else render_params.palette From b2c0193d20ae7d25c563f468a0e93e2dfb8443e3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 09:13:00 +0000 Subject: [PATCH 2/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/spatialdata_plot/pl/render.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/spatialdata_plot/pl/render.py b/src/spatialdata_plot/pl/render.py index e331050e..79ac6e7d 100644 --- a/src/spatialdata_plot/pl/render.py +++ b/src/spatialdata_plot/pl/render.py @@ -90,11 +90,9 @@ def _render_shapes( alpha=render_params.fill_alpha, ) - # Sets the limits of the colorbar to the values instead of [0, 1] if not norm: _cax.set_clim(min(color_vector), max(color_vector)) - # color_source_vector is None when the values aren't categorical if color_source_vector is None and render_params.transfunc is not None: From 23ae544f78b32cd1fc7b48100f77cda9fc2baeab Mon Sep 17 00:00:00 2001 From: Tim Treis Date: Mon, 4 Sep 2023 12:03:35 +0200 Subject: [PATCH 3/4] Added tests --- src/spatialdata_plot/pl/basic.py | 2 +- src/spatialdata_plot/pl/render.py | 14 +++++++------- src/spatialdata_plot/pl/utils.py | 4 +++- .../Shapes_colorbar_can_be_normalised.png | Bin 0 -> 7772 bytes .../Shapes_colorbar_respects_input_limits.png | Bin 0 -> 8195 bytes tests/pl/test_render_shapes.py | 8 ++++++++ 6 files changed, 19 insertions(+), 9 deletions(-) create mode 100644 tests/_images/Shapes_colorbar_can_be_normalised.png create mode 100644 tests/_images/Shapes_colorbar_respects_input_limits.png diff --git a/src/spatialdata_plot/pl/basic.py b/src/spatialdata_plot/pl/basic.py index 62b58296..e228f2ac 100644 --- a/src/spatialdata_plot/pl/basic.py +++ b/src/spatialdata_plot/pl/basic.py @@ -152,7 +152,7 @@ def render_shapes( layer: str | None = None, palette: ListedColormap | str | None = None, cmap: Colormap | str | None = None, - norm: bool | Normalize = True, + norm: bool | Normalize = False, na_color: str | tuple[float, ...] | None = "lightgrey", outline_alpha: float = 1.0, fill_alpha: float = 1.0, diff --git a/src/spatialdata_plot/pl/render.py b/src/spatialdata_plot/pl/render.py index 79ac6e7d..c849be41 100644 --- a/src/spatialdata_plot/pl/render.py +++ b/src/spatialdata_plot/pl/render.py @@ -90,12 +90,10 @@ def _render_shapes( alpha=render_params.fill_alpha, ) - # Sets the limits of the colorbar to the values instead of [0, 1] - if not norm: - _cax.set_clim(min(color_vector), max(color_vector)) + values_are_categorical = color_source_vector is not None # color_source_vector is None when the values aren't categorical - if color_source_vector is None and render_params.transfunc is not None: + if values_are_categorical and render_params.transfunc is not None: color_vector = render_params.transfunc(color_vector) norm = copy(render_params.cmap_params.norm) @@ -117,6 +115,10 @@ def _render_shapes( # **kwargs, ) + # Sets the limits of the colorbar to the values instead of [0, 1] + if not norm and not values_are_categorical: + _cax.set_clim(min(color_vector), max(color_vector)) + cax = ax.add_collection(_cax) # Using dict.fromkeys here since set returns in arbitrary order @@ -124,8 +126,6 @@ def _render_shapes( ListedColormap(dict.fromkeys(color_vector)) if render_params.palette is None else render_params.palette ) - # print(len(set(color_vector)) == 1) - # print(set(color_source_vector[0]) == to_hex(render_params.cmap_params.na_color)) if not ( len(set(color_vector)) == 1 and list(set(color_vector))[0] == to_hex(render_params.cmap_params.na_color) ): @@ -194,7 +194,7 @@ def _render_points( key=render_params.color, palette=render_params.palette, ) - # print(p) + color_source_vector, color_vector, _ = _set_color_source_vec( sdata=sdata_filt, element=points, diff --git a/src/spatialdata_plot/pl/utils.py b/src/spatialdata_plot/pl/utils.py index d60e53a1..981701dd 100644 --- a/src/spatialdata_plot/pl/utils.py +++ b/src/spatialdata_plot/pl/utils.py @@ -564,7 +564,7 @@ def _get_scalebar( def _prepare_cmap_norm( cmap: Colormap | str | None = None, - norm: Normalize | Sequence[Normalize] | None = None, + norm: Normalize | bool = False, na_color: str | tuple[float, ...] = (0.0, 0.0, 0.0, 0.0), vmin: float | None = None, vmax: float | None = None, @@ -576,6 +576,8 @@ def _prepare_cmap_norm( if isinstance(norm, Normalize): pass # TODO + elif not norm: + pass elif vcenter is None: norm = Normalize(vmin=vmin, vmax=vmax) else: diff --git a/tests/_images/Shapes_colorbar_can_be_normalised.png b/tests/_images/Shapes_colorbar_can_be_normalised.png new file mode 100644 index 0000000000000000000000000000000000000000..cd4ffd74490a19064b4f539af69895cc4fbe955b GIT binary patch literal 7772 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 literal 0 HcmV?d00001 diff --git a/tests/_images/Shapes_colorbar_respects_input_limits.png b/tests/_images/Shapes_colorbar_respects_input_limits.png new file mode 100644 index 0000000000000000000000000000000000000000..d0c3cce0ad9c3885afbed683c15925f9a531f946 GIT binary patch literal 8195 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 UpsCW=fFX~dD61w@1u_f$A23)B_5c6? literal 0 HcmV?d00001 diff --git a/tests/pl/test_render_shapes.py b/tests/pl/test_render_shapes.py index 25379fb2..0a703b2f 100644 --- a/tests/pl/test_render_shapes.py +++ b/tests/pl/test_render_shapes.py @@ -100,3 +100,11 @@ def test_plot_can_color_from_geodataframe(self, sdata_blobs: SpatialData): def test_plot_can_scale_shapes(self, sdata_blobs: SpatialData): sdata_blobs.pl.render_shapes(elements="blobs_circles", scale=0.5).pl.show() + + def test_plot_colorbar_respects_input_limits(self, sdata_blobs: SpatialData): + sdata_blobs.shapes["blobs_polygons"]["cluster"] = [1, 2, 3, 5, 20] + sdata_blobs.pl.render_shapes("blobs_polygons", color="cluster", groups=["c1"]).pl.show() + + def test_plot_colorbar_can_be_normalised(self, sdata_blobs: SpatialData): + sdata_blobs.shapes["blobs_polygons"]["cluster"] = [1, 2, 3, 5, 20] + sdata_blobs.pl.render_shapes("blobs_polygons", color="cluster", groups=["c1"], norm=True).pl.show() From d31fcb8a357209fdebb8ed22ba55b3dfc3a41b4f Mon Sep 17 00:00:00 2001 From: Tim Treis Date: Mon, 4 Sep 2023 12:09:12 +0200 Subject: [PATCH 4/4] Updated Changelog; Replaced image with updated colorbar --- CHANGELOG.md | 3 ++- .../Shapes_can_color_from_geodataframe.png | Bin 7797 -> 8254 bytes 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b138c91..27fedfc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,14 +12,15 @@ and this project adheres to [Semantic Versioning][]. ### Added -- Multipolygons are now handled correctly (#93) - Can now scale shapes (#152) - Can now plot columns from GeoDataFrame (#149) ### Fixed +- Multipolygons are now handled correctly (#93) - Legend order is now deterministic (#143) - Images no longer normalised by default (#150) +- Colorbar no longer autoscales to [0, 1] (#155) ## [0.0.4] - 2023-08-11 diff --git a/tests/_images/Shapes_can_color_from_geodataframe.png b/tests/_images/Shapes_can_color_from_geodataframe.png index c9718063be71cc8b02093a8d046e031d06036ddf..403d67c9226852a31d764360ae49ea7e2848925a 100644 GIT binary patch literal 8254 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