Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning][].
### Fixed

- Now dropping index when plotting shapes after spatial query (#177)
- User can now pass Colormap objects to the cmap argument in render_images. When only one cmap is given for 3 channels, it is now applied to each channel (#188, #194)

## [0.0.6] - 2023-11-06

Expand Down
3 changes: 0 additions & 3 deletions src/spatialdata_plot/pl/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,9 +362,6 @@ def render_images(
sdata = _verify_plotting_tree(sdata)
n_steps = len(sdata.plotting_tree.keys())

if channel is None and cmap is None:
cmap = "brg"

cmap_params: list[CmapParams] | CmapParams
if isinstance(cmap, list):
cmap_params = [
Expand Down
25 changes: 22 additions & 3 deletions src/spatialdata_plot/pl/render.py
Original file line number Diff line number Diff line change
Expand Up @@ -434,10 +434,29 @@ def _render_images(
if render_params.cmap_params[i].norm is not None:
layers[c] = render_params.cmap_params[i].norm(layers[c])

# 2A) Image has 3 channels, no palette/cmap info -> use RGB
if n_channels == 3 and render_params.palette is None and not got_multiple_cmaps:
# 2A) Image has 3 channels, no palette info, and no/only one cmap was given
if n_channels == 3 and render_params.palette is None and not isinstance(render_params.cmap_params, list):
if render_params.cmap_params.is_default: # -> use RGB
stacked = np.stack([layers[c] for c in channels], axis=-1)
else: # -> use given cmap for each channel
channel_cmaps = [render_params.cmap_params.cmap] * n_channels
# Apply cmaps to each channel, add up and normalize to [0, 1]
stacked = (
np.stack([channel_cmaps[i](layers[c]) for i, c in enumerate(channels)], 0).sum(0) / n_channels
)
# Remove alpha channel so we can overwrite it from render_params.alpha
stacked = stacked[:, :, :3]
logger.warning(
"One cmap was given for multiple channels and is now used for each channel. "
"You're blending multiple cmaps. "
"If the plot doesn't look like you expect, it might be because your "
"cmaps go from a given color to 'white', and not to 'transparent'. "
"Therefore, the 'white' of higher layers will overlay the lower layers. "
"Consider using 'palette' instead."
)

im = ax.imshow(
np.stack([layers[c] for c in channels], axis=-1),
stacked,
alpha=render_params.alpha,
)
im.set_transform(trans_data)
Expand Down
8 changes: 7 additions & 1 deletion src/spatialdata_plot/pl/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,13 @@ def _prepare_cmap_norm(
**kwargs: Any,
) -> CmapParams:
is_default = cmap is None
cmap = copy(matplotlib.colormaps[rcParams["image.cmap"] if cmap is None else cmap])
if cmap is None:
cmap = rcParams["image.cmap"]
if isinstance(cmap, str):
cmap = matplotlib.colormaps[cmap]

cmap = copy(cmap)

cmap.set_bad("lightgray" if na_color is None else na_color)

if isinstance(norm, Normalize) or not norm:
Expand Down
Binary file added tests/_images/Images_can_pass_cmap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/_images/Images_can_pass_cmap_list.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file added tests/_images/Images_can_pass_str_cmap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/_images/Images_can_pass_str_cmap_list.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 13 additions & 1 deletion tests/pl/test_render_images.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,21 @@ class TestImages(PlotTester, metaclass=PlotTesterMeta):
def test_plot_can_render_image(self, sdata_blobs: SpatialData):
sdata_blobs.pl.render_images(elements="blobs_image").pl.show()

def test_plot_can_pass_cmap_to_render_images(self, sdata_blobs: SpatialData):
def test_plot_can_pass_str_cmap(self, sdata_blobs: SpatialData):
sdata_blobs.pl.render_images(elements="blobs_image", cmap="seismic").pl.show()

def test_plot_can_pass_cmap(self, sdata_blobs: SpatialData):
sdata_blobs.pl.render_images(elements="blobs_image", cmap=matplotlib.colormaps["seismic"]).pl.show()

def test_plot_can_pass_str_cmap_list(self, sdata_blobs: SpatialData):
sdata_blobs.pl.render_images(elements="blobs_image", cmap=["seismic", "Reds", "Blues"]).pl.show()

def test_plot_can_pass_cmap_list(self, sdata_blobs: SpatialData):
sdata_blobs.pl.render_images(
elements="blobs_image",
cmap=[matplotlib.colormaps["seismic"], matplotlib.colormaps["Reds"], matplotlib.colormaps["Blues"]],
).pl.show()

def test_plot_can_render_a_single_channel_from_image(self, sdata_blobs: SpatialData):
sdata_blobs.pl.render_images(elements="blobs_image", channel=0).pl.show()

Expand Down