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
69 changes: 69 additions & 0 deletions src/spatialdata_plot/_utils.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
from __future__ import annotations

import functools
import warnings
from typing import Any, Callable, TypeVar

RT = TypeVar("RT")


def deprecation_alias(**aliases: str) -> Callable[[Callable[..., RT]], Callable[..., RT]]:
"""
Decorate a function to warn user of use of arguments set for deprecation.

Parameters
----------
aliases
Deprecation argument aliases to be mapped to the new arguments.

Returns
-------
A decorator that can be used to mark an argument for deprecation and substituting it with the new argument.

Raises
------
TypeError
If the provided aliases are not of string type.

Example
-------
Assuming we have an argument 'table' set for deprecation and we want to warn the user and substitute with 'tables':

```python
@deprecation_alias(table="tables")
def my_function(tables: AnnData | dict[str, AnnData]):
pass
```
"""

def deprecation_decorator(f: Callable[..., RT]) -> Callable[..., RT]:
@functools.wraps(f)
def wrapper(*args: Any, **kwargs: Any) -> RT:
class_name = f.__qualname__
rename_kwargs(f.__name__, kwargs, aliases, class_name)
return f(*args, **kwargs)

return wrapper

return deprecation_decorator


def rename_kwargs(func_name: str, kwargs: dict[str, Any], aliases: dict[str, str], class_name: None | str) -> None:
"""Rename function arguments set for deprecation and gives warning in case of usage of these arguments."""
for alias, new in aliases.items():
if alias in kwargs:
class_name = class_name + "." if class_name else ""
if new in kwargs:
raise TypeError(
f"{class_name}{func_name} received both {alias} and {new} as arguments!"
f" {alias} is being deprecated in spatialdata-plot version 0.3, only use {new} instead."
)
warnings.warn(
message=(
f"`{alias}` is being deprecated as an argument to `{class_name}{func_name}` in spatialdata-plot "
f"version 0.3, switch to `{new}` instead."
),
category=DeprecationWarning,
stacklevel=3,
)
kwargs[new] = kwargs.pop(alias)
70 changes: 39 additions & 31 deletions src/spatialdata_plot/pl/basic.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,6 +23,7 @@
from spatialdata._core.data_extent import get_extent

from spatialdata_plot._accessor import register_spatial_data_accessor
from spatialdata_plot._utils import deprecation_alias
from spatialdata_plot.pl.render import (
_render_images,
_render_labels,
Expand DownExpand Up@@ -50,6 +51,7 @@
_prepare_params_plot,
_set_outline,
_update_params,
_validate_image_render_params,
_validate_render_params,
_validate_show_parameters,
save_fig,
Expand DownExpand Up@@ -390,59 +392,63 @@ def render_points(

return sdata

@deprecation_alias(elements="element", quantiles_for_norm="percentiles_for_norm", version="version 0.3.0")
def render_images(
self,
elements: list[str] | str | None = None,
element: str | None = None,
channel: list[str] | list[int] | str | int | None = None,
cmap: list[Colormap] | Colormap | str | None = None,
cmap: list[Colormap | str] | Colormap | str | None = None,
norm: Normalize | None = None,
na_color: ColorLike | None = (0.0, 0.0, 0.0, 0.0),
palette: list[list[str | None]] | list[str | None] | str | None = None,
palette: list[str] | str | None = None,
alpha: float | int = 1.0,
quantiles_for_norm: tuple[float | None, float | None] | None = None,
scale: list[str] | str | None = None,
percentiles_for_norm: tuple[float, float] | None = None,
scale: str | None = None,
**kwargs: Any,
) -> sd.SpatialData:
"""
Render image elements in SpatialData.

In case of no elements specified, "broadcasting" of parameters is applied. This means that for any particular
SpatialElement, we validate whether a given parameter is valid. If not valid for a particular SpatialElement the
specific parameter for that particular SpatialElement will be ignored. If you want to set specific parameters
for specific elements please chain the render functions: `pl.render_images(...).pl.render_images(...).pl.show()`
.

Parameters
----------
elements : list[str] | str | None, optional
The name(s) of the image element(s) to render. If `None`, all image
elements in the `SpatialData` object will be used. If a string is provided,
it is converted into a single-element list.
channel : list[str] | list[int] | str | int | None, optional
element : str | None
The name of the image element to render. If `None`, all image
elements in the `SpatialData` object will be used.
channels : list[str] | list[int] | str | int | None, optional
To select specific channels to plot. Can be a single channel name/int or a
list of channel names/ints. If `None`, all channels will be used.
cmap : list[Colormap] | Colormap | str | None, optional
cmap : list[Colormap | str] | Colormap | str | None, optional
Colormap or list of colormaps for continuous annotations, see :class:`matplotlib.colors.Colormap`.
Each colormap applies to a corresponding channel.
norm : Normalize | None, optional
Colormap normalization for continuous annotations, see :class:`matplotlib.colors.Normalize`.
Applies to all channels if set.
na_color : ColorLike | None, default (0.0, 0.0, 0.0, 0.0)
Color to be used for NA values. Accepts color-like values (string, hex, RGB(A)).
palette : list[list[str | None]] | list[str | None] | str | None
palette : list[str] | None
Palette to color images. In the case of a list of
lists means that there is one list per element to be plotted in the list and this list contains the string
indicating the palette to be used. If not provided as list of lists, broadcasting behaviour is
attempted (use the same values for all elements).
alpha : float | int, default 1.0
Alpha value for the images. Must be a numeric between 0 and 1.
quantiles_for_norm : tuple[float | None, float | None] | None, optional
percentiles_for_norm : tuple[float, float] | None
Optional pair of floats (pmin < pmax, 0-100) which will be used for quantile normalization.
scale : list[str] | str | None, optional
scale : str | None
Influences the resolution of the rendering. Possibilities include:
1) `None` (default): The image is rasterized to fit the canvas size. For
multiscale images, the best scale is selected before rasterization.
2) A scale name: Renders the specified scale as-is (with adjustments for dpi
in `show()`).
2) A scale name: Renders the specified scale ( of a multiscale image) as-is
(with adjustments for dpi in `show()`).
3) "full": Renders the full image without rasterization. In the case of
multiscale images, the highest resolution scale is selected. Note that
this may result in long computing times for large images.
4) A list matching the list of elements. Can contain `None`, scale names, or
"full". Each scale applies to the corresponding element.
kwargs
Additional arguments to be passed to cmap, norm, and other rendering functions.

Expand All@@ -451,19 +457,19 @@ def render_images(
sd.SpatialData
The SpatialData object with the rendered images.
"""
params_dict = _validate_render_params(
"images",
params_dict = _validate_image_render_params(
self._sdata,
elements=elements,
element=element,
channel=channel,
alpha=alpha,
palette=palette,
na_color=na_color,
cmap=cmap,
norm=norm,
scale=scale,
quantiles_for_norm=quantiles_for_norm,
percentiles_for_norm=percentiles_for_norm,
)

sdata = self._copy()
sdata = _verify_plotting_tree(sdata)
n_steps = len(sdata.plotting_tree.keys())
Expand All@@ -488,15 +494,17 @@ def render_images(
**kwargs,
)

sdata.plotting_tree[f"{n_steps+1}_render_images"] = ImageRenderParams(
elements=params_dict["elements"],
channel=channel,
cmap_params=cmap_params,
palette=params_dict["palette"],
alpha=alpha,
quantiles_for_norm=params_dict["quantiles_for_norm"],
scale=params_dict["scale"],
)
for element, param_values in params_dict.items():
sdata.plotting_tree[f"{n_steps+1}_render_images"] = ImageRenderParams(
element=element,
channel=param_values["channel"],
cmap_params=cmap_params,
palette=param_values["palette"],
alpha=param_values["alpha"],
percentiles_for_norm=param_values["percentiles_for_norm"],
scale=param_values["scale"],
)
n_steps += 1

return sdata

Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
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
69 changes: 69 additions & 0 deletions src/spatialdata_plot/_utils.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
from __future__ import annotations

import functools
import warnings
from typing import Any, Callable, TypeVar

RT = TypeVar("RT")


def deprecation_alias(**aliases: str) -> Callable[[Callable[..., RT]], Callable[..., RT]]:
"""
Decorate a function to warn user of use of arguments set for deprecation.

Parameters
----------
aliases
Deprecation argument aliases to be mapped to the new arguments.

Returns
-------
A decorator that can be used to mark an argument for deprecation and substituting it with the new argument.

Raises
------
TypeError
If the provided aliases are not of string type.

Example
-------
Assuming we have an argument 'table' set for deprecation and we want to warn the user and substitute with 'tables':

```python
@deprecation_alias(table="tables")
def my_function(tables: AnnData | dict[str, AnnData]):
pass
```
"""

def deprecation_decorator(f: Callable[..., RT]) -> Callable[..., RT]:
@functools.wraps(f)
def wrapper(*args: Any, **kwargs: Any) -> RT:
class_name = f.__qualname__
rename_kwargs(f.__name__, kwargs, aliases, class_name)
return f(*args, **kwargs)

return wrapper

return deprecation_decorator


def rename_kwargs(func_name: str, kwargs: dict[str, Any], aliases: dict[str, str], class_name: None | str) -> None:
"""Rename function arguments set for deprecation and gives warning in case of usage of these arguments."""
for alias, new in aliases.items():
if alias in kwargs:
class_name = class_name + "." if class_name else ""
if new in kwargs:
raise TypeError(
f"{class_name}{func_name} received both {alias} and {new} as arguments!"
f" {alias} is being deprecated in spatialdata-plot version 0.3, only use {new} instead."
)
warnings.warn(
message=(
f"`{alias}` is being deprecated as an argument to `{class_name}{func_name}` in spatialdata-plot "
f"version 0.3, switch to `{new}` instead."
),
category=DeprecationWarning,
stacklevel=3,
)
kwargs[new] = kwargs.pop(alias)
70 changes: 39 additions & 31 deletions src/spatialdata_plot/pl/basic.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,6 +23,7 @@
from spatialdata._core.data_extent import get_extent

from spatialdata_plot._accessor import register_spatial_data_accessor
from spatialdata_plot._utils import deprecation_alias
from spatialdata_plot.pl.render import (
_render_images,
_render_labels,
Expand DownExpand Up@@ -50,6 +51,7 @@
_prepare_params_plot,
_set_outline,
_update_params,
_validate_image_render_params,
_validate_render_params,
_validate_show_parameters,
save_fig,
Expand DownExpand Up@@ -390,59 +392,63 @@ def render_points(

return sdata

@deprecation_alias(elements="element", quantiles_for_norm="percentiles_for_norm", version="version 0.3.0")
def render_images(
self,
elements: list[str] | str | None = None,
element: str | None = None,
channel: list[str] | list[int] | str | int | None = None,
cmap: list[Colormap] | Colormap | str | None = None,
cmap: list[Colormap | str] | Colormap | str | None = None,
norm: Normalize | None = None,
na_color: ColorLike | None = (0.0, 0.0, 0.0, 0.0),
palette: list[list[str | None]] | list[str | None] | str | None = None,
palette: list[str] | str | None = None,
alpha: float | int = 1.0,
quantiles_for_norm: tuple[float | None, float | None] | None = None,
scale: list[str] | str | None = None,
percentiles_for_norm: tuple[float, float] | None = None,
scale: str | None = None,
**kwargs: Any,
) -> sd.SpatialData:
"""
Render image elements in SpatialData.

In case of no elements specified, "broadcasting" of parameters is applied. This means that for any particular
SpatialElement, we validate whether a given parameter is valid. If not valid for a particular SpatialElement the
specific parameter for that particular SpatialElement will be ignored. If you want to set specific parameters
for specific elements please chain the render functions: `pl.render_images(...).pl.render_images(...).pl.show()`
.

Parameters
----------
elements : list[str] | str | None, optional
The name(s) of the image element(s) to render. If `None`, all image
elements in the `SpatialData` object will be used. If a string is provided,
it is converted into a single-element list.
channel : list[str] | list[int] | str | int | None, optional
element : str | None
The name of the image element to render. If `None`, all image
elements in the `SpatialData` object will be used.
channels : list[str] | list[int] | str | int | None, optional
To select specific channels to plot. Can be a single channel name/int or a
list of channel names/ints. If `None`, all channels will be used.
cmap : list[Colormap] | Colormap | str | None, optional
cmap : list[Colormap | str] | Colormap | str | None, optional
Colormap or list of colormaps for continuous annotations, see :class:`matplotlib.colors.Colormap`.
Each colormap applies to a corresponding channel.
norm : Normalize | None, optional
Colormap normalization for continuous annotations, see :class:`matplotlib.colors.Normalize`.
Applies to all channels if set.
na_color : ColorLike | None, default (0.0, 0.0, 0.0, 0.0)
Color to be used for NA values. Accepts color-like values (string, hex, RGB(A)).
palette : list[list[str | None]] | list[str | None] | str | None
palette : list[str] | None
Palette to color images. In the case of a list of
lists means that there is one list per element to be plotted in the list and this list contains the string
indicating the palette to be used. If not provided as list of lists, broadcasting behaviour is
attempted (use the same values for all elements).
alpha : float | int, default 1.0
Alpha value for the images. Must be a numeric between 0 and 1.
quantiles_for_norm : tuple[float | None, float | None] | None, optional
percentiles_for_norm : tuple[float, float] | None
Optional pair of floats (pmin < pmax, 0-100) which will be used for quantile normalization.
scale : list[str] | str | None, optional
scale : str | None
Influences the resolution of the rendering. Possibilities include:
1) `None` (default): The image is rasterized to fit the canvas size. For
multiscale images, the best scale is selected before rasterization.
2) A scale name: Renders the specified scale as-is (with adjustments for dpi
in `show()`).
2) A scale name: Renders the specified scale ( of a multiscale image) as-is
(with adjustments for dpi in `show()`).
3) "full": Renders the full image without rasterization. In the case of
multiscale images, the highest resolution scale is selected. Note that
this may result in long computing times for large images.
4) A list matching the list of elements. Can contain `None`, scale names, or
"full". Each scale applies to the corresponding element.
kwargs
Additional arguments to be passed to cmap, norm, and other rendering functions.

Expand All@@ -451,19 +457,19 @@ def render_images(
sd.SpatialData
The SpatialData object with the rendered images.
"""
params_dict = _validate_render_params(
"images",
params_dict = _validate_image_render_params(
self._sdata,
elements=elements,
element=element,
channel=channel,
alpha=alpha,
palette=palette,
na_color=na_color,
cmap=cmap,
norm=norm,
scale=scale,
quantiles_for_norm=quantiles_for_norm,
percentiles_for_norm=percentiles_for_norm,
)

sdata = self._copy()
sdata = _verify_plotting_tree(sdata)
n_steps = len(sdata.plotting_tree.keys())
Expand All@@ -488,15 +494,17 @@ def render_images(
**kwargs,
)

sdata.plotting_tree[f"{n_steps+1}_render_images"] = ImageRenderParams(
elements=params_dict["elements"],
channel=channel,
cmap_params=cmap_params,
palette=params_dict["palette"],
alpha=alpha,
quantiles_for_norm=params_dict["quantiles_for_norm"],
scale=params_dict["scale"],
)
for element, param_values in params_dict.items():
sdata.plotting_tree[f"{n_steps+1}_render_images"] = ImageRenderParams(
element=element,
channel=param_values["channel"],
cmap_params=cmap_params,
palette=param_values["palette"],
alpha=param_values["alpha"],
percentiles_for_norm=param_values["percentiles_for_norm"],
scale=param_values["scale"],
)
n_steps += 1

return sdata

Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
69 changes: 69 additions & 0 deletions src/spatialdata_plot/_utils.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
from __future__ import annotations

import functools
import warnings
from typing import Any, Callable, TypeVar

RT = TypeVar("RT")


def deprecation_alias(**aliases: str) -> Callable[[Callable[..., RT]], Callable[..., RT]]:
"""
Decorate a function to warn user of use of arguments set for deprecation.

Parameters
----------
aliases
Deprecation argument aliases to be mapped to the new arguments.

Returns
-------
A decorator that can be used to mark an argument for deprecation and substituting it with the new argument.

Raises
------
TypeError
If the provided aliases are not of string type.

Example
-------
Assuming we have an argument 'table' set for deprecation and we want to warn the user and substitute with 'tables':

```python
@deprecation_alias(table="tables")
def my_function(tables: AnnData | dict[str, AnnData]):
pass
```
"""

def deprecation_decorator(f: Callable[..., RT]) -> Callable[..., RT]:
@functools.wraps(f)
def wrapper(*args: Any, **kwargs: Any) -> RT:
class_name = f.__qualname__
rename_kwargs(f.__name__, kwargs, aliases, class_name)
return f(*args, **kwargs)

return wrapper

return deprecation_decorator


def rename_kwargs(func_name: str, kwargs: dict[str, Any], aliases: dict[str, str], class_name: None | str) -> None:
"""Rename function arguments set for deprecation and gives warning in case of usage of these arguments."""
for alias, new in aliases.items():
if alias in kwargs:
class_name = class_name + "." if class_name else ""
if new in kwargs:
raise TypeError(
f"{class_name}{func_name} received both {alias} and {new} as arguments!"
f" {alias} is being deprecated in spatialdata-plot version 0.3, only use {new} instead."
)
warnings.warn(
message=(
f"`{alias}` is being deprecated as an argument to `{class_name}{func_name}` in spatialdata-plot "
f"version 0.3, switch to `{new}` instead."
),
category=DeprecationWarning,
stacklevel=3,
)
kwargs[new] = kwargs.pop(alias)
70 changes: 39 additions & 31 deletions src/spatialdata_plot/pl/basic.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,6 +23,7 @@
from spatialdata._core.data_extent import get_extent

from spatialdata_plot._accessor import register_spatial_data_accessor
from spatialdata_plot._utils import deprecation_alias
from spatialdata_plot.pl.render import (
_render_images,
_render_labels,
Expand DownExpand Up@@ -50,6 +51,7 @@
_prepare_params_plot,
_set_outline,
_update_params,
_validate_image_render_params,
_validate_render_params,
_validate_show_parameters,
save_fig,
Expand DownExpand Up@@ -390,59 +392,63 @@ def render_points(

return sdata

@deprecation_alias(elements="element", quantiles_for_norm="percentiles_for_norm", version="version 0.3.0")
def render_images(
self,
elements: list[str] | str | None = None,
element: str | None = None,
channel: list[str] | list[int] | str | int | None = None,
cmap: list[Colormap] | Colormap | str | None = None,
cmap: list[Colormap | str] | Colormap | str | None = None,
norm: Normalize | None = None,
na_color: ColorLike | None = (0.0, 0.0, 0.0, 0.0),
palette: list[list[str | None]] | list[str | None] | str | None = None,
palette: list[str] | str | None = None,
alpha: float | int = 1.0,
quantiles_for_norm: tuple[float | None, float | None] | None = None,
scale: list[str] | str | None = None,
percentiles_for_norm: tuple[float, float] | None = None,
scale: str | None = None,
**kwargs: Any,
) -> sd.SpatialData:
"""
Render image elements in SpatialData.

In case of no elements specified, "broadcasting" of parameters is applied. This means that for any particular
SpatialElement, we validate whether a given parameter is valid. If not valid for a particular SpatialElement the
specific parameter for that particular SpatialElement will be ignored. If you want to set specific parameters
for specific elements please chain the render functions: `pl.render_images(...).pl.render_images(...).pl.show()`
.

Parameters
----------
elements : list[str] | str | None, optional
The name(s) of the image element(s) to render. If `None`, all image
elements in the `SpatialData` object will be used. If a string is provided,
it is converted into a single-element list.
channel : list[str] | list[int] | str | int | None, optional
element : str | None
The name of the image element to render. If `None`, all image
elements in the `SpatialData` object will be used.
channels : list[str] | list[int] | str | int | None, optional
To select specific channels to plot. Can be a single channel name/int or a
list of channel names/ints. If `None`, all channels will be used.
cmap : list[Colormap] | Colormap | str | None, optional
cmap : list[Colormap | str] | Colormap | str | None, optional
Colormap or list of colormaps for continuous annotations, see :class:`matplotlib.colors.Colormap`.
Each colormap applies to a corresponding channel.
norm : Normalize | None, optional
Colormap normalization for continuous annotations, see :class:`matplotlib.colors.Normalize`.
Applies to all channels if set.
na_color : ColorLike | None, default (0.0, 0.0, 0.0, 0.0)
Color to be used for NA values. Accepts color-like values (string, hex, RGB(A)).
palette : list[list[str | None]] | list[str | None] | str | None
palette : list[str] | None
Palette to color images. In the case of a list of
lists means that there is one list per element to be plotted in the list and this list contains the string
indicating the palette to be used. If not provided as list of lists, broadcasting behaviour is
attempted (use the same values for all elements).
alpha : float | int, default 1.0
Alpha value for the images. Must be a numeric between 0 and 1.
quantiles_for_norm : tuple[float | None, float | None] | None, optional
percentiles_for_norm : tuple[float, float] | None
Optional pair of floats (pmin < pmax, 0-100) which will be used for quantile normalization.
scale : list[str] | str | None, optional
scale : str | None
Influences the resolution of the rendering. Possibilities include:
1) `None` (default): The image is rasterized to fit the canvas size. For
multiscale images, the best scale is selected before rasterization.
2) A scale name: Renders the specified scale as-is (with adjustments for dpi
in `show()`).
2) A scale name: Renders the specified scale ( of a multiscale image) as-is
(with adjustments for dpi in `show()`).
3) "full": Renders the full image without rasterization. In the case of
multiscale images, the highest resolution scale is selected. Note that
this may result in long computing times for large images.
4) A list matching the list of elements. Can contain `None`, scale names, or
"full". Each scale applies to the corresponding element.
kwargs
Additional arguments to be passed to cmap, norm, and other rendering functions.

Expand All@@ -451,19 +457,19 @@ def render_images(
sd.SpatialData
The SpatialData object with the rendered images.
"""
params_dict = _validate_render_params(
"images",
params_dict = _validate_image_render_params(
self._sdata,
elements=elements,
element=element,
channel=channel,
alpha=alpha,
palette=palette,
na_color=na_color,
cmap=cmap,
norm=norm,
scale=scale,
quantiles_for_norm=quantiles_for_norm,
percentiles_for_norm=percentiles_for_norm,
)

sdata = self._copy()
sdata = _verify_plotting_tree(sdata)
n_steps = len(sdata.plotting_tree.keys())
Expand All@@ -488,15 +494,17 @@ def render_images(
**kwargs,
)

sdata.plotting_tree[f"{n_steps+1}_render_images"] = ImageRenderParams(
elements=params_dict["elements"],
channel=channel,
cmap_params=cmap_params,
palette=params_dict["palette"],
alpha=alpha,
quantiles_for_norm=params_dict["quantiles_for_norm"],
scale=params_dict["scale"],
)
for element, param_values in params_dict.items():
sdata.plotting_tree[f"{n_steps+1}_render_images"] = ImageRenderParams(
element=element,
channel=param_values["channel"],
cmap_params=cmap_params,
palette=param_values["palette"],
alpha=param_values["alpha"],
percentiles_for_norm=param_values["percentiles_for_norm"],
scale=param_values["scale"],
)
n_steps += 1

return sdata

Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
69 changes: 69 additions & 0 deletions src/spatialdata_plot/_utils.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
from __future__ import annotations

import functools
import warnings
from typing import Any, Callable, TypeVar

RT = TypeVar("RT")


def deprecation_alias(**aliases: str) -> Callable[[Callable[..., RT]], Callable[..., RT]]:
"""
Decorate a function to warn user of use of arguments set for deprecation.

Parameters
----------
aliases
Deprecation argument aliases to be mapped to the new arguments.

Returns
-------
A decorator that can be used to mark an argument for deprecation and substituting it with the new argument.

Raises
------
TypeError
If the provided aliases are not of string type.

Example
-------
Assuming we have an argument 'table' set for deprecation and we want to warn the user and substitute with 'tables':

```python
@deprecation_alias(table="tables")
def my_function(tables: AnnData | dict[str, AnnData]):
pass
```
"""

def deprecation_decorator(f: Callable[..., RT]) -> Callable[..., RT]:
@functools.wraps(f)
def wrapper(*args: Any, **kwargs: Any) -> RT:
class_name = f.__qualname__
rename_kwargs(f.__name__, kwargs, aliases, class_name)
return f(*args, **kwargs)

return wrapper

return deprecation_decorator


def rename_kwargs(func_name: str, kwargs: dict[str, Any], aliases: dict[str, str], class_name: None | str) -> None:
"""Rename function arguments set for deprecation and gives warning in case of usage of these arguments."""
for alias, new in aliases.items():
if alias in kwargs:
class_name = class_name + "." if class_name else ""
if new in kwargs:
raise TypeError(
f"{class_name}{func_name} received both {alias} and {new} as arguments!"
f" {alias} is being deprecated in spatialdata-plot version 0.3, only use {new} instead."
)
warnings.warn(
message=(
f"`{alias}` is being deprecated as an argument to `{class_name}{func_name}` in spatialdata-plot "
f"version 0.3, switch to `{new}` instead."
),
category=DeprecationWarning,
stacklevel=3,
)
kwargs[new] = kwargs.pop(alias)
70 changes: 39 additions & 31 deletions src/spatialdata_plot/pl/basic.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,6 +23,7 @@
from spatialdata._core.data_extent import get_extent

from spatialdata_plot._accessor import register_spatial_data_accessor
from spatialdata_plot._utils import deprecation_alias
from spatialdata_plot.pl.render import (
_render_images,
_render_labels,
Expand DownExpand Up@@ -50,6 +51,7 @@
_prepare_params_plot,
_set_outline,
_update_params,
_validate_image_render_params,
_validate_render_params,
_validate_show_parameters,
save_fig,
Expand DownExpand Up@@ -390,59 +392,63 @@ def render_points(

return sdata

@deprecation_alias(elements="element", quantiles_for_norm="percentiles_for_norm", version="version 0.3.0")
def render_images(
self,
elements: list[str] | str | None = None,
element: str | None = None,
channel: list[str] | list[int] | str | int | None = None,
cmap: list[Colormap] | Colormap | str | None = None,
cmap: list[Colormap | str] | Colormap | str | None = None,
norm: Normalize | None = None,
na_color: ColorLike | None = (0.0, 0.0, 0.0, 0.0),
palette: list[list[str | None]] | list[str | None] | str | None = None,
palette: list[str] | str | None = None,
alpha: float | int = 1.0,
quantiles_for_norm: tuple[float | None, float | None] | None = None,
scale: list[str] | str | None = None,
percentiles_for_norm: tuple[float, float] | None = None,
scale: str | None = None,
**kwargs: Any,
) -> sd.SpatialData:
"""
Render image elements in SpatialData.

In case of no elements specified, "broadcasting" of parameters is applied. This means that for any particular
SpatialElement, we validate whether a given parameter is valid. If not valid for a particular SpatialElement the
specific parameter for that particular SpatialElement will be ignored. If you want to set specific parameters
for specific elements please chain the render functions: `pl.render_images(...).pl.render_images(...).pl.show()`
.

Parameters
----------
elements : list[str] | str | None, optional
The name(s) of the image element(s) to render. If `None`, all image
elements in the `SpatialData` object will be used. If a string is provided,
it is converted into a single-element list.
channel : list[str] | list[int] | str | int | None, optional
element : str | None
The name of the image element to render. If `None`, all image
elements in the `SpatialData` object will be used.
channels : list[str] | list[int] | str | int | None, optional
To select specific channels to plot. Can be a single channel name/int or a
list of channel names/ints. If `None`, all channels will be used.
cmap : list[Colormap] | Colormap | str | None, optional
cmap : list[Colormap | str] | Colormap | str | None, optional
Colormap or list of colormaps for continuous annotations, see :class:`matplotlib.colors.Colormap`.
Each colormap applies to a corresponding channel.
norm : Normalize | None, optional
Colormap normalization for continuous annotations, see :class:`matplotlib.colors.Normalize`.
Applies to all channels if set.
na_color : ColorLike | None, default (0.0, 0.0, 0.0, 0.0)
Color to be used for NA values. Accepts color-like values (string, hex, RGB(A)).
palette : list[list[str | None]] | list[str | None] | str | None
palette : list[str] | None
Palette to color images. In the case of a list of
lists means that there is one list per element to be plotted in the list and this list contains the string
indicating the palette to be used. If not provided as list of lists, broadcasting behaviour is
attempted (use the same values for all elements).
alpha : float | int, default 1.0
Alpha value for the images. Must be a numeric between 0 and 1.
quantiles_for_norm : tuple[float | None, float | None] | None, optional
percentiles_for_norm : tuple[float, float] | None
Optional pair of floats (pmin < pmax, 0-100) which will be used for quantile normalization.
scale : list[str] | str | None, optional
scale : str | None
Influences the resolution of the rendering. Possibilities include:
1) `None` (default): The image is rasterized to fit the canvas size. For
multiscale images, the best scale is selected before rasterization.
2) A scale name: Renders the specified scale as-is (with adjustments for dpi
in `show()`).
2) A scale name: Renders the specified scale ( of a multiscale image) as-is
(with adjustments for dpi in `show()`).
3) "full": Renders the full image without rasterization. In the case of
multiscale images, the highest resolution scale is selected. Note that
this may result in long computing times for large images.
4) A list matching the list of elements. Can contain `None`, scale names, or
"full". Each scale applies to the corresponding element.
kwargs
Additional arguments to be passed to cmap, norm, and other rendering functions.

Expand All@@ -451,19 +457,19 @@ def render_images(
sd.SpatialData
The SpatialData object with the rendered images.
"""
params_dict = _validate_render_params(
"images",
params_dict = _validate_image_render_params(
self._sdata,
elements=elements,
element=element,
channel=channel,
alpha=alpha,
palette=palette,
na_color=na_color,
cmap=cmap,
norm=norm,
scale=scale,
quantiles_for_norm=quantiles_for_norm,
percentiles_for_norm=percentiles_for_norm,
)

sdata = self._copy()
sdata = _verify_plotting_tree(sdata)
n_steps = len(sdata.plotting_tree.keys())
Expand All@@ -488,15 +494,17 @@ def render_images(
**kwargs,
)

sdata.plotting_tree[f"{n_steps+1}_render_images"] = ImageRenderParams(
elements=params_dict["elements"],
channel=channel,
cmap_params=cmap_params,
palette=params_dict["palette"],
alpha=alpha,
quantiles_for_norm=params_dict["quantiles_for_norm"],
scale=params_dict["scale"],
)
for element, param_values in params_dict.items():
sdata.plotting_tree[f"{n_steps+1}_render_images"] = ImageRenderParams(
element=element,
channel=param_values["channel"],
cmap_params=cmap_params,
palette=param_values["palette"],
alpha=param_values["alpha"],
percentiles_for_norm=param_values["percentiles_for_norm"],
scale=param_values["scale"],
)
n_steps += 1

return sdata

Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
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
69 changes: 69 additions & 0 deletions src/spatialdata_plot/_utils.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
from __future__ import annotations

import functools
import warnings
from typing import Any, Callable, TypeVar

RT = TypeVar("RT")


def deprecation_alias(**aliases: str) -> Callable[[Callable[..., RT]], Callable[..., RT]]:
"""
Decorate a function to warn user of use of arguments set for deprecation.

Parameters
----------
aliases
Deprecation argument aliases to be mapped to the new arguments.

Returns
-------
A decorator that can be used to mark an argument for deprecation and substituting it with the new argument.

Raises
------
TypeError
If the provided aliases are not of string type.

Example
-------
Assuming we have an argument 'table' set for deprecation and we want to warn the user and substitute with 'tables':

```python
@deprecation_alias(table="tables")
def my_function(tables: AnnData | dict[str, AnnData]):
pass
```
"""

def deprecation_decorator(f: Callable[..., RT]) -> Callable[..., RT]:
@functools.wraps(f)
def wrapper(*args: Any, **kwargs: Any) -> RT:
class_name = f.__qualname__
rename_kwargs(f.__name__, kwargs, aliases, class_name)
return f(*args, **kwargs)

return wrapper

return deprecation_decorator


def rename_kwargs(func_name: str, kwargs: dict[str, Any], aliases: dict[str, str], class_name: None | str) -> None:
"""Rename function arguments set for deprecation and gives warning in case of usage of these arguments."""
for alias, new in aliases.items():
if alias in kwargs:
class_name = class_name + "." if class_name else ""
if new in kwargs:
raise TypeError(
f"{class_name}{func_name} received both {alias} and {new} as arguments!"
f" {alias} is being deprecated in spatialdata-plot version 0.3, only use {new} instead."
)
warnings.warn(
message=(
f"`{alias}` is being deprecated as an argument to `{class_name}{func_name}` in spatialdata-plot "
f"version 0.3, switch to `{new}` instead."
),
category=DeprecationWarning,
stacklevel=3,
)
kwargs[new] = kwargs.pop(alias)
70 changes: 39 additions & 31 deletions src/spatialdata_plot/pl/basic.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,6 +23,7 @@
from spatialdata._core.data_extent import get_extent

from spatialdata_plot._accessor import register_spatial_data_accessor
from spatialdata_plot._utils import deprecation_alias
from spatialdata_plot.pl.render import (
_render_images,
_render_labels,
Expand DownExpand Up@@ -50,6 +51,7 @@
_prepare_params_plot,
_set_outline,
_update_params,
_validate_image_render_params,
_validate_render_params,
_validate_show_parameters,
save_fig,
Expand DownExpand Up@@ -390,59 +392,63 @@ def render_points(

return sdata

@deprecation_alias(elements="element", quantiles_for_norm="percentiles_for_norm", version="version 0.3.0")
def render_images(
self,
elements: list[str] | str | None = None,
element: str | None = None,
channel: list[str] | list[int] | str | int | None = None,
cmap: list[Colormap] | Colormap | str | None = None,
cmap: list[Colormap | str] | Colormap | str | None = None,
norm: Normalize | None = None,
na_color: ColorLike | None = (0.0, 0.0, 0.0, 0.0),
palette: list[list[str | None]] | list[str | None] | str | None = None,
palette: list[str] | str | None = None,
alpha: float | int = 1.0,
quantiles_for_norm: tuple[float | None, float | None] | None = None,
scale: list[str] | str | None = None,
percentiles_for_norm: tuple[float, float] | None = None,
scale: str | None = None,
**kwargs: Any,
) -> sd.SpatialData:
"""
Render image elements in SpatialData.

In case of no elements specified, "broadcasting" of parameters is applied. This means that for any particular
SpatialElement, we validate whether a given parameter is valid. If not valid for a particular SpatialElement the
specific parameter for that particular SpatialElement will be ignored. If you want to set specific parameters
for specific elements please chain the render functions: `pl.render_images(...).pl.render_images(...).pl.show()`
.

Parameters
----------
elements : list[str] | str | None, optional
The name(s) of the image element(s) to render. If `None`, all image
elements in the `SpatialData` object will be used. If a string is provided,
it is converted into a single-element list.
channel : list[str] | list[int] | str | int | None, optional
element : str | None
The name of the image element to render. If `None`, all image
elements in the `SpatialData` object will be used.
channels : list[str] | list[int] | str | int | None, optional
To select specific channels to plot. Can be a single channel name/int or a
list of channel names/ints. If `None`, all channels will be used.
cmap : list[Colormap] | Colormap | str | None, optional
cmap : list[Colormap | str] | Colormap | str | None, optional
Colormap or list of colormaps for continuous annotations, see :class:`matplotlib.colors.Colormap`.
Each colormap applies to a corresponding channel.
norm : Normalize | None, optional
Colormap normalization for continuous annotations, see :class:`matplotlib.colors.Normalize`.
Applies to all channels if set.
na_color : ColorLike | None, default (0.0, 0.0, 0.0, 0.0)
Color to be used for NA values. Accepts color-like values (string, hex, RGB(A)).
palette : list[list[str | None]] | list[str | None] | str | None
palette : list[str] | None
Palette to color images. In the case of a list of
lists means that there is one list per element to be plotted in the list and this list contains the string
indicating the palette to be used. If not provided as list of lists, broadcasting behaviour is
attempted (use the same values for all elements).
alpha : float | int, default 1.0
Alpha value for the images. Must be a numeric between 0 and 1.
quantiles_for_norm : tuple[float | None, float | None] | None, optional
percentiles_for_norm : tuple[float, float] | None
Optional pair of floats (pmin < pmax, 0-100) which will be used for quantile normalization.
scale : list[str] | str | None, optional
scale : str | None
Influences the resolution of the rendering. Possibilities include:
1) `None` (default): The image is rasterized to fit the canvas size. For
multiscale images, the best scale is selected before rasterization.
2) A scale name: Renders the specified scale as-is (with adjustments for dpi
in `show()`).
2) A scale name: Renders the specified scale ( of a multiscale image) as-is
(with adjustments for dpi in `show()`).
3) "full": Renders the full image without rasterization. In the case of
multiscale images, the highest resolution scale is selected. Note that
this may result in long computing times for large images.
4) A list matching the list of elements. Can contain `None`, scale names, or
"full". Each scale applies to the corresponding element.
kwargs
Additional arguments to be passed to cmap, norm, and other rendering functions.

Expand All@@ -451,19 +457,19 @@ def render_images(
sd.SpatialData
The SpatialData object with the rendered images.
"""
params_dict = _validate_render_params(
"images",
params_dict = _validate_image_render_params(
self._sdata,
elements=elements,
element=element,
channel=channel,
alpha=alpha,
palette=palette,
na_color=na_color,
cmap=cmap,
norm=norm,
scale=scale,
quantiles_for_norm=quantiles_for_norm,
percentiles_for_norm=percentiles_for_norm,
)

sdata = self._copy()
sdata = _verify_plotting_tree(sdata)
n_steps = len(sdata.plotting_tree.keys())
Expand All@@ -488,15 +494,17 @@ def render_images(
**kwargs,
)

sdata.plotting_tree[f"{n_steps+1}_render_images"] = ImageRenderParams(
elements=params_dict["elements"],
channel=channel,
cmap_params=cmap_params,
palette=params_dict["palette"],
alpha=alpha,
quantiles_for_norm=params_dict["quantiles_for_norm"],
scale=params_dict["scale"],
)
for element, param_values in params_dict.items():
sdata.plotting_tree[f"{n_steps+1}_render_images"] = ImageRenderParams(
element=element,
channel=param_values["channel"],
cmap_params=cmap_params,
palette=param_values["palette"],
alpha=param_values["alpha"],
percentiles_for_norm=param_values["percentiles_for_norm"],
scale=param_values["scale"],
)
n_steps += 1

return sdata

Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
69 changes: 69 additions & 0 deletions src/spatialdata_plot/_utils.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
from __future__ import annotations

import functools
import warnings
from typing import Any, Callable, TypeVar

RT = TypeVar("RT")


def deprecation_alias(**aliases: str) -> Callable[[Callable[..., RT]], Callable[..., RT]]:
"""
Decorate a function to warn user of use of arguments set for deprecation.

Parameters
----------
aliases
Deprecation argument aliases to be mapped to the new arguments.

Returns
-------
A decorator that can be used to mark an argument for deprecation and substituting it with the new argument.

Raises
------
TypeError
If the provided aliases are not of string type.

Example
-------
Assuming we have an argument 'table' set for deprecation and we want to warn the user and substitute with 'tables':

```python
@deprecation_alias(table="tables")
def my_function(tables: AnnData | dict[str, AnnData]):
pass
```
"""

def deprecation_decorator(f: Callable[..., RT]) -> Callable[..., RT]:
@functools.wraps(f)
def wrapper(*args: Any, **kwargs: Any) -> RT:
class_name = f.__qualname__
rename_kwargs(f.__name__, kwargs, aliases, class_name)
return f(*args, **kwargs)

return wrapper

return deprecation_decorator


def rename_kwargs(func_name: str, kwargs: dict[str, Any], aliases: dict[str, str], class_name: None | str) -> None:
"""Rename function arguments set for deprecation and gives warning in case of usage of these arguments."""
for alias, new in aliases.items():
if alias in kwargs:
class_name = class_name + "." if class_name else ""
if new in kwargs:
raise TypeError(
f"{class_name}{func_name} received both {alias} and {new} as arguments!"
f" {alias} is being deprecated in spatialdata-plot version 0.3, only use {new} instead."
)
warnings.warn(
message=(
f"`{alias}` is being deprecated as an argument to `{class_name}{func_name}` in spatialdata-plot "
f"version 0.3, switch to `{new}` instead."
),
category=DeprecationWarning,
stacklevel=3,
)
kwargs[new] = kwargs.pop(alias)
70 changes: 39 additions & 31 deletions src/spatialdata_plot/pl/basic.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,6 +23,7 @@
from spatialdata._core.data_extent import get_extent

from spatialdata_plot._accessor import register_spatial_data_accessor
from spatialdata_plot._utils import deprecation_alias
from spatialdata_plot.pl.render import (
_render_images,
_render_labels,
Expand DownExpand Up@@ -50,6 +51,7 @@
_prepare_params_plot,
_set_outline,
_update_params,
_validate_image_render_params,
_validate_render_params,
_validate_show_parameters,
save_fig,
Expand DownExpand Up@@ -390,59 +392,63 @@ def render_points(

return sdata

@deprecation_alias(elements="element", quantiles_for_norm="percentiles_for_norm", version="version 0.3.0")
def render_images(
self,
elements: list[str] | str | None = None,
element: str | None = None,
channel: list[str] | list[int] | str | int | None = None,
cmap: list[Colormap] | Colormap | str | None = None,
cmap: list[Colormap | str] | Colormap | str | None = None,
norm: Normalize | None = None,
na_color: ColorLike | None = (0.0, 0.0, 0.0, 0.0),
palette: list[list[str | None]] | list[str | None] | str | None = None,
palette: list[str] | str | None = None,
alpha: float | int = 1.0,
quantiles_for_norm: tuple[float | None, float | None] | None = None,
scale: list[str] | str | None = None,
percentiles_for_norm: tuple[float, float] | None = None,
scale: str | None = None,
**kwargs: Any,
) -> sd.SpatialData:
"""
Render image elements in SpatialData.

In case of no elements specified, "broadcasting" of parameters is applied. This means that for any particular
SpatialElement, we validate whether a given parameter is valid. If not valid for a particular SpatialElement the
specific parameter for that particular SpatialElement will be ignored. If you want to set specific parameters
for specific elements please chain the render functions: `pl.render_images(...).pl.render_images(...).pl.show()`
.

Parameters
----------
elements : list[str] | str | None, optional
The name(s) of the image element(s) to render. If `None`, all image
elements in the `SpatialData` object will be used. If a string is provided,
it is converted into a single-element list.
channel : list[str] | list[int] | str | int | None, optional
element : str | None
The name of the image element to render. If `None`, all image
elements in the `SpatialData` object will be used.
channels : list[str] | list[int] | str | int | None, optional
To select specific channels to plot. Can be a single channel name/int or a
list of channel names/ints. If `None`, all channels will be used.
cmap : list[Colormap] | Colormap | str | None, optional
cmap : list[Colormap | str] | Colormap | str | None, optional
Colormap or list of colormaps for continuous annotations, see :class:`matplotlib.colors.Colormap`.
Each colormap applies to a corresponding channel.
norm : Normalize | None, optional
Colormap normalization for continuous annotations, see :class:`matplotlib.colors.Normalize`.
Applies to all channels if set.
na_color : ColorLike | None, default (0.0, 0.0, 0.0, 0.0)
Color to be used for NA values. Accepts color-like values (string, hex, RGB(A)).
palette : list[list[str | None]] | list[str | None] | str | None
palette : list[str] | None
Palette to color images. In the case of a list of
lists means that there is one list per element to be plotted in the list and this list contains the string
indicating the palette to be used. If not provided as list of lists, broadcasting behaviour is
attempted (use the same values for all elements).
alpha : float | int, default 1.0
Alpha value for the images. Must be a numeric between 0 and 1.
quantiles_for_norm : tuple[float | None, float | None] | None, optional
percentiles_for_norm : tuple[float, float] | None
Optional pair of floats (pmin < pmax, 0-100) which will be used for quantile normalization.
scale : list[str] | str | None, optional
scale : str | None
Influences the resolution of the rendering. Possibilities include:
1) `None` (default): The image is rasterized to fit the canvas size. For
multiscale images, the best scale is selected before rasterization.
2) A scale name: Renders the specified scale as-is (with adjustments for dpi
in `show()`).
2) A scale name: Renders the specified scale ( of a multiscale image) as-is
(with adjustments for dpi in `show()`).
3) "full": Renders the full image without rasterization. In the case of
multiscale images, the highest resolution scale is selected. Note that
this may result in long computing times for large images.
4) A list matching the list of elements. Can contain `None`, scale names, or
"full". Each scale applies to the corresponding element.
kwargs
Additional arguments to be passed to cmap, norm, and other rendering functions.

Expand All@@ -451,19 +457,19 @@ def render_images(
sd.SpatialData
The SpatialData object with the rendered images.
"""
params_dict = _validate_render_params(
"images",
params_dict = _validate_image_render_params(
self._sdata,
elements=elements,
element=element,
channel=channel,
alpha=alpha,
palette=palette,
na_color=na_color,
cmap=cmap,
norm=norm,
scale=scale,
quantiles_for_norm=quantiles_for_norm,
percentiles_for_norm=percentiles_for_norm,
)

sdata = self._copy()
sdata = _verify_plotting_tree(sdata)
n_steps = len(sdata.plotting_tree.keys())
Expand All@@ -488,15 +494,17 @@ def render_images(
**kwargs,
)

sdata.plotting_tree[f"{n_steps+1}_render_images"] = ImageRenderParams(
elements=params_dict["elements"],
channel=channel,
cmap_params=cmap_params,
palette=params_dict["palette"],
alpha=alpha,
quantiles_for_norm=params_dict["quantiles_for_norm"],
scale=params_dict["scale"],
)
for element, param_values in params_dict.items():
sdata.plotting_tree[f"{n_steps+1}_render_images"] = ImageRenderParams(
element=element,
channel=param_values["channel"],
cmap_params=cmap_params,
palette=param_values["palette"],
alpha=param_values["alpha"],
percentiles_for_norm=param_values["percentiles_for_norm"],
scale=param_values["scale"],
)
n_steps += 1

return sdata

Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
69 changes: 69 additions & 0 deletions src/spatialdata_plot/_utils.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
from __future__ import annotations

import functools
import warnings
from typing import Any, Callable, TypeVar

RT = TypeVar("RT")


def deprecation_alias(**aliases: str) -> Callable[[Callable[..., RT]], Callable[..., RT]]:
"""
Decorate a function to warn user of use of arguments set for deprecation.

Parameters
----------
aliases
Deprecation argument aliases to be mapped to the new arguments.

Returns
-------
A decorator that can be used to mark an argument for deprecation and substituting it with the new argument.

Raises
------
TypeError
If the provided aliases are not of string type.

Example
-------
Assuming we have an argument 'table' set for deprecation and we want to warn the user and substitute with 'tables':

```python
@deprecation_alias(table="tables")
def my_function(tables: AnnData | dict[str, AnnData]):
pass
```
"""

def deprecation_decorator(f: Callable[..., RT]) -> Callable[..., RT]:
@functools.wraps(f)
def wrapper(*args: Any, **kwargs: Any) -> RT:
class_name = f.__qualname__
rename_kwargs(f.__name__, kwargs, aliases, class_name)
return f(*args, **kwargs)

return wrapper

return deprecation_decorator


def rename_kwargs(func_name: str, kwargs: dict[str, Any], aliases: dict[str, str], class_name: None | str) -> None:
"""Rename function arguments set for deprecation and gives warning in case of usage of these arguments."""
for alias, new in aliases.items():
if alias in kwargs:
class_name = class_name + "." if class_name else ""
if new in kwargs:
raise TypeError(
f"{class_name}{func_name} received both {alias} and {new} as arguments!"
f" {alias} is being deprecated in spatialdata-plot version 0.3, only use {new} instead."
)
warnings.warn(
message=(
f"`{alias}` is being deprecated as an argument to `{class_name}{func_name}` in spatialdata-plot "
f"version 0.3, switch to `{new}` instead."
),
category=DeprecationWarning,
stacklevel=3,
)
kwargs[new] = kwargs.pop(alias)
70 changes: 39 additions & 31 deletions src/spatialdata_plot/pl/basic.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,6 +23,7 @@
from spatialdata._core.data_extent import get_extent

from spatialdata_plot._accessor import register_spatial_data_accessor
from spatialdata_plot._utils import deprecation_alias
from spatialdata_plot.pl.render import (
_render_images,
_render_labels,
Expand DownExpand Up@@ -50,6 +51,7 @@
_prepare_params_plot,
_set_outline,
_update_params,
_validate_image_render_params,
_validate_render_params,
_validate_show_parameters,
save_fig,
Expand DownExpand Up@@ -390,59 +392,63 @@ def render_points(

return sdata

@deprecation_alias(elements="element", quantiles_for_norm="percentiles_for_norm", version="version 0.3.0")
def render_images(
self,
elements: list[str] | str | None = None,
element: str | None = None,
channel: list[str] | list[int] | str | int | None = None,
cmap: list[Colormap] | Colormap | str | None = None,
cmap: list[Colormap | str] | Colormap | str | None = None,
norm: Normalize | None = None,
na_color: ColorLike | None = (0.0, 0.0, 0.0, 0.0),
palette: list[list[str | None]] | list[str | None] | str | None = None,
palette: list[str] | str | None = None,
alpha: float | int = 1.0,
quantiles_for_norm: tuple[float | None, float | None] | None = None,
scale: list[str] | str | None = None,
percentiles_for_norm: tuple[float, float] | None = None,
scale: str | None = None,
**kwargs: Any,
) -> sd.SpatialData:
"""
Render image elements in SpatialData.

In case of no elements specified, "broadcasting" of parameters is applied. This means that for any particular
SpatialElement, we validate whether a given parameter is valid. If not valid for a particular SpatialElement the
specific parameter for that particular SpatialElement will be ignored. If you want to set specific parameters
for specific elements please chain the render functions: `pl.render_images(...).pl.render_images(...).pl.show()`
.

Parameters
----------
elements : list[str] | str | None, optional
The name(s) of the image element(s) to render. If `None`, all image
elements in the `SpatialData` object will be used. If a string is provided,
it is converted into a single-element list.
channel : list[str] | list[int] | str | int | None, optional
element : str | None
The name of the image element to render. If `None`, all image
elements in the `SpatialData` object will be used.
channels : list[str] | list[int] | str | int | None, optional
To select specific channels to plot. Can be a single channel name/int or a
list of channel names/ints. If `None`, all channels will be used.
cmap : list[Colormap] | Colormap | str | None, optional
cmap : list[Colormap | str] | Colormap | str | None, optional
Colormap or list of colormaps for continuous annotations, see :class:`matplotlib.colors.Colormap`.
Each colormap applies to a corresponding channel.
norm : Normalize | None, optional
Colormap normalization for continuous annotations, see :class:`matplotlib.colors.Normalize`.
Applies to all channels if set.
na_color : ColorLike | None, default (0.0, 0.0, 0.0, 0.0)
Color to be used for NA values. Accepts color-like values (string, hex, RGB(A)).
palette : list[list[str | None]] | list[str | None] | str | None
palette : list[str] | None
Palette to color images. In the case of a list of
lists means that there is one list per element to be plotted in the list and this list contains the string
indicating the palette to be used. If not provided as list of lists, broadcasting behaviour is
attempted (use the same values for all elements).
alpha : float | int, default 1.0
Alpha value for the images. Must be a numeric between 0 and 1.
quantiles_for_norm : tuple[float | None, float | None] | None, optional
percentiles_for_norm : tuple[float, float] | None
Optional pair of floats (pmin < pmax, 0-100) which will be used for quantile normalization.
scale : list[str] | str | None, optional
scale : str | None
Influences the resolution of the rendering. Possibilities include:
1) `None` (default): The image is rasterized to fit the canvas size. For
multiscale images, the best scale is selected before rasterization.
2) A scale name: Renders the specified scale as-is (with adjustments for dpi
in `show()`).
2) A scale name: Renders the specified scale ( of a multiscale image) as-is
(with adjustments for dpi in `show()`).
3) "full": Renders the full image without rasterization. In the case of
multiscale images, the highest resolution scale is selected. Note that
this may result in long computing times for large images.
4) A list matching the list of elements. Can contain `None`, scale names, or
"full". Each scale applies to the corresponding element.
kwargs
Additional arguments to be passed to cmap, norm, and other rendering functions.

Expand All@@ -451,19 +457,19 @@ def render_images(
sd.SpatialData
The SpatialData object with the rendered images.
"""
params_dict = _validate_render_params(
"images",
params_dict = _validate_image_render_params(
self._sdata,
elements=elements,
element=element,
channel=channel,
alpha=alpha,
palette=palette,
na_color=na_color,
cmap=cmap,
norm=norm,
scale=scale,
quantiles_for_norm=quantiles_for_norm,
percentiles_for_norm=percentiles_for_norm,
)

sdata = self._copy()
sdata = _verify_plotting_tree(sdata)
n_steps = len(sdata.plotting_tree.keys())
Expand All@@ -488,15 +494,17 @@ def render_images(
**kwargs,
)

sdata.plotting_tree[f"{n_steps+1}_render_images"] = ImageRenderParams(
elements=params_dict["elements"],
channel=channel,
cmap_params=cmap_params,
palette=params_dict["palette"],
alpha=alpha,
quantiles_for_norm=params_dict["quantiles_for_norm"],
scale=params_dict["scale"],
)
for element, param_values in params_dict.items():
sdata.plotting_tree[f"{n_steps+1}_render_images"] = ImageRenderParams(
element=element,
channel=param_values["channel"],
cmap_params=cmap_params,
palette=param_values["palette"],
alpha=param_values["alpha"],
percentiles_for_norm=param_values["percentiles_for_norm"],
scale=param_values["scale"],
)
n_steps += 1

return sdata

Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
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
69 changes: 69 additions & 0 deletions src/spatialdata_plot/_utils.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
from __future__ import annotations

import functools
import warnings
from typing import Any, Callable, TypeVar

RT = TypeVar("RT")


def deprecation_alias(**aliases: str) -> Callable[[Callable[..., RT]], Callable[..., RT]]:
"""
Decorate a function to warn user of use of arguments set for deprecation.

Parameters
----------
aliases
Deprecation argument aliases to be mapped to the new arguments.

Returns
-------
A decorator that can be used to mark an argument for deprecation and substituting it with the new argument.

Raises
------
TypeError
If the provided aliases are not of string type.

Example
-------
Assuming we have an argument 'table' set for deprecation and we want to warn the user and substitute with 'tables':

```python
@deprecation_alias(table="tables")
def my_function(tables: AnnData | dict[str, AnnData]):
pass
```
"""

def deprecation_decorator(f: Callable[..., RT]) -> Callable[..., RT]:
@functools.wraps(f)
def wrapper(*args: Any, **kwargs: Any) -> RT:
class_name = f.__qualname__
rename_kwargs(f.__name__, kwargs, aliases, class_name)
return f(*args, **kwargs)

return wrapper

return deprecation_decorator


def rename_kwargs(func_name: str, kwargs: dict[str, Any], aliases: dict[str, str], class_name: None | str) -> None:
"""Rename function arguments set for deprecation and gives warning in case of usage of these arguments."""
for alias, new in aliases.items():
if alias in kwargs:
class_name = class_name + "." if class_name else ""
if new in kwargs:
raise TypeError(
f"{class_name}{func_name} received both {alias} and {new} as arguments!"
f" {alias} is being deprecated in spatialdata-plot version 0.3, only use {new} instead."
)
warnings.warn(
message=(
f"`{alias}` is being deprecated as an argument to `{class_name}{func_name}` in spatialdata-plot "
f"version 0.3, switch to `{new}` instead."
),
category=DeprecationWarning,
stacklevel=3,
)
kwargs[new] = kwargs.pop(alias)
70 changes: 39 additions & 31 deletions src/spatialdata_plot/pl/basic.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,6 +23,7 @@
from spatialdata._core.data_extent import get_extent

from spatialdata_plot._accessor import register_spatial_data_accessor
from spatialdata_plot._utils import deprecation_alias
from spatialdata_plot.pl.render import (
_render_images,
_render_labels,
Expand DownExpand Up@@ -50,6 +51,7 @@
_prepare_params_plot,
_set_outline,
_update_params,
_validate_image_render_params,
_validate_render_params,
_validate_show_parameters,
save_fig,
Expand DownExpand Up@@ -390,59 +392,63 @@ def render_points(

return sdata

@deprecation_alias(elements="element", quantiles_for_norm="percentiles_for_norm", version="version 0.3.0")
def render_images(
self,
elements: list[str] | str | None = None,
element: str | None = None,
channel: list[str] | list[int] | str | int | None = None,
cmap: list[Colormap] | Colormap | str | None = None,
cmap: list[Colormap | str] | Colormap | str | None = None,
norm: Normalize | None = None,
na_color: ColorLike | None = (0.0, 0.0, 0.0, 0.0),
palette: list[list[str | None]] | list[str | None] | str | None = None,
palette: list[str] | str | None = None,
alpha: float | int = 1.0,
quantiles_for_norm: tuple[float | None, float | None] | None = None,
scale: list[str] | str | None = None,
percentiles_for_norm: tuple[float, float] | None = None,
scale: str | None = None,
**kwargs: Any,
) -> sd.SpatialData:
"""
Render image elements in SpatialData.

In case of no elements specified, "broadcasting" of parameters is applied. This means that for any particular
SpatialElement, we validate whether a given parameter is valid. If not valid for a particular SpatialElement the
specific parameter for that particular SpatialElement will be ignored. If you want to set specific parameters
for specific elements please chain the render functions: `pl.render_images(...).pl.render_images(...).pl.show()`
.

Parameters
----------
elements : list[str] | str | None, optional
The name(s) of the image element(s) to render. If `None`, all image
elements in the `SpatialData` object will be used. If a string is provided,
it is converted into a single-element list.
channel : list[str] | list[int] | str | int | None, optional
element : str | None
The name of the image element to render. If `None`, all image
elements in the `SpatialData` object will be used.
channels : list[str] | list[int] | str | int | None, optional
To select specific channels to plot. Can be a single channel name/int or a
list of channel names/ints. If `None`, all channels will be used.
cmap : list[Colormap] | Colormap | str | None, optional
cmap : list[Colormap | str] | Colormap | str | None, optional
Colormap or list of colormaps for continuous annotations, see :class:`matplotlib.colors.Colormap`.
Each colormap applies to a corresponding channel.
norm : Normalize | None, optional
Colormap normalization for continuous annotations, see :class:`matplotlib.colors.Normalize`.
Applies to all channels if set.
na_color : ColorLike | None, default (0.0, 0.0, 0.0, 0.0)
Color to be used for NA values. Accepts color-like values (string, hex, RGB(A)).
palette : list[list[str | None]] | list[str | None] | str | None
palette : list[str] | None
Palette to color images. In the case of a list of
lists means that there is one list per element to be plotted in the list and this list contains the string
indicating the palette to be used. If not provided as list of lists, broadcasting behaviour is
attempted (use the same values for all elements).
alpha : float | int, default 1.0
Alpha value for the images. Must be a numeric between 0 and 1.
quantiles_for_norm : tuple[float | None, float | None] | None, optional
percentiles_for_norm : tuple[float, float] | None
Optional pair of floats (pmin < pmax, 0-100) which will be used for quantile normalization.
scale : list[str] | str | None, optional
scale : str | None
Influences the resolution of the rendering. Possibilities include:
1) `None` (default): The image is rasterized to fit the canvas size. For
multiscale images, the best scale is selected before rasterization.
2) A scale name: Renders the specified scale as-is (with adjustments for dpi
in `show()`).
2) A scale name: Renders the specified scale ( of a multiscale image) as-is
(with adjustments for dpi in `show()`).
3) "full": Renders the full image without rasterization. In the case of
multiscale images, the highest resolution scale is selected. Note that
this may result in long computing times for large images.
4) A list matching the list of elements. Can contain `None`, scale names, or
"full". Each scale applies to the corresponding element.
kwargs
Additional arguments to be passed to cmap, norm, and other rendering functions.

Expand All@@ -451,19 +457,19 @@ def render_images(
sd.SpatialData
The SpatialData object with the rendered images.
"""
params_dict = _validate_render_params(
"images",
params_dict = _validate_image_render_params(
self._sdata,
elements=elements,
element=element,
channel=channel,
alpha=alpha,
palette=palette,
na_color=na_color,
cmap=cmap,
norm=norm,
scale=scale,
quantiles_for_norm=quantiles_for_norm,
percentiles_for_norm=percentiles_for_norm,
)

sdata = self._copy()
sdata = _verify_plotting_tree(sdata)
n_steps = len(sdata.plotting_tree.keys())
Expand All@@ -488,15 +494,17 @@ def render_images(
**kwargs,
)

sdata.plotting_tree[f"{n_steps+1}_render_images"] = ImageRenderParams(
elements=params_dict["elements"],
channel=channel,
cmap_params=cmap_params,
palette=params_dict["palette"],
alpha=alpha,
quantiles_for_norm=params_dict["quantiles_for_norm"],
scale=params_dict["scale"],
)
for element, param_values in params_dict.items():
sdata.plotting_tree[f"{n_steps+1}_render_images"] = ImageRenderParams(
element=element,
channel=param_values["channel"],
cmap_params=cmap_params,
palette=param_values["palette"],
alpha=param_values["alpha"],
percentiles_for_norm=param_values["percentiles_for_norm"],
scale=param_values["scale"],
)
n_steps += 1

return sdata

Expand Down
Loading