Source code for darsia.signals.models.clipmodel
"""Module containing clipping operations."""
from typing import Literal, Optional
import numpy as np
import darsia
[docs]
class ClipModel(darsia.Model):
"""Model clipping away signal at some min and max values."""
def __init__(
self,
min_value: float | None = None,
max_value: float | None = None,
key: str | None = None,
**kwargs,
) -> None:
"""
Clipping model initialization.
Args:
min_value (float | None): lower clip value
max_value (float | None): upper clip value
key (str): additional key (prefix) for kwargs
kwargs (keyword arguments):
key + '_min_value': lower clip value
key + '_max_value': upper clip value
"""
if key is None:
self._min_value = min_value
self._max_value = max_value
else:
self._min_value = kwargs.get(key + "_min_value", None)
self._max_value = kwargs.get(key + "_max_value", None)
if self._min_value is None and self._max_value is None:
raise ValueError("at least one of min_value or max_value must be provided")
self.num_parameters = 2
[docs]
def update(
self,
min_value: Optional[float] = None,
max_value: Optional[float] = None,
) -> None:
"""
Update of internal parameters.
Args:
min_value (float, optional): lower clip value
max_value (float, optional): upper clip value
"""
if min_value is not None:
self._min_value = min_value
if max_value is not None:
self._max_value = max_value
[docs]
def update_model_parameters(
self,
parameters: np.ndarray,
dofs: Optional[list[Literal["min_value", "max_value"]] | Literal["all"]] = None,
) -> None:
"""
Short cut to update scaling and offset parameters using a
general function signature.
Args:
parameters (np.ndarray): 2-array containing min and max values.
"""
if (
dofs is None
or dofs == "all"
or set(dofs) == set(["min_value", "max_value"])
):
self.update(min_value=parameters[0], max_value=parameters[1])
elif set(dofs) == set(["min_value"]):
self.update(min_value=parameters[0])
elif set(dofs) == set(["max_value"]):
self.update(max_value=parameters[0])
else:
raise ValueError("invalid list of degrees of freedom")
def __call__(self, img: np.ndarray | darsia.Image) -> np.ndarray | darsia.Image:
"""
Application of clipping.
Args:
img (np.ndarray | Image): image
Returns:
np.ndarray | Image: converted signal; output type is the same as input type
"""
if isinstance(img, np.ndarray):
return np.clip(img, self._min_value, self._max_value)
elif isinstance(img, darsia.Image):
result = img.copy()
result.img = np.clip(result.img, self._min_value, self._max_value)
return result
else:
raise ValueError("invalid input type")