Source code for ddd_pylib.image_manip._rescale_operator
from ddd_pylib._base import ImageOperator
import xarray as xr
import numpy as np
from scipy.ndimage import zoom
[docs]
class RescaleOperator(ImageOperator):
"""
Applies rescaling to the input image based on the specified scale factors for each axis
and the chosen interpolation method. The time axis cannot be rescaled. Different interpolation
methods are available, including 'Nearest', 'Linear', and 'Cubic'.
"""
_INTERPOLATION = {"Nearest": 0, "Linear": 1, "Cubic": 3}
def __init__(self):
super().__init__()
self._scale = self.defaultScale()
self._interpolation = self.defaultInterpolation()
[docs]
@staticmethod
def defaultInterpolation() -> str:
return "Linear"
[docs]
@staticmethod
def defaultScale() -> dict:
return {"Z": 1.0, "Y": 1.0, "X": 1.0}
[docs]
def getPrefix(self) -> str:
return f"Rescaled[{self._interpolation}]-"
[docs]
def setScale(self, scale: dict):
"""
Set the scale factor of each dimensions
Args:
scale: Dictionary with axis as keys and their scale factor as values
"""
if scale is None or not (
np.issubdtype(np.array(list(scale.values())).dtype, np.integer)
or np.issubdtype(np.array(list(scale.values())).dtype, np.floating)
):
raise ValueError("Wrong scale type")
conservedValues = self._scale.copy()
for axis in conservedValues.keys():
conservedValues[axis] = scale.get(axis, conservedValues[axis])
self._scale = conservedValues
[docs]
def setInterpolation(self, interpolation: str):
"""
Set the interpolation method.
Args:
interpolation: 'Nearest', 'Linear', or 'Cubic'
"""
if interpolation not in self._INTERPOLATION:
raise ValueError(f"Interpolation method '{interpolation}' is not valid.")
self._interpolation = interpolation
[docs]
def getInterpolation(self) -> str:
"""
Return the active interpolation method
"""
return self._interpolation
[docs]
def getScale(self) -> dict:
"""
Return the new scale in which the image will be rescaled
"""
return self._scale
[docs]
def sanityCheck(self):
super().sanityCheck()
if self._interpolation not in self._INTERPOLATION:
raise ValueError(
f"Interpolation method '{self._interpolation}' is not valid."
)
if any(np.isclose(scale, 0.0) for scale in self._scale.values()):
raise ValueError("Scale factors must not be null")
def _rescaleImage(
self, image: xr.DataArray, scale: dict, interpolation: str
) -> xr.DataArray:
zoom_factors = [scale.get(dim, 1.0) for dim in image.dims]
order = self._INTERPOLATION.get(interpolation, 1)
rescaled_data = zoom(image.data, zoom_factors, order=order)
new_attrs = image.attrs.copy()
if "scale" in new_attrs:
for ax in new_attrs["scale"]:
new_attrs["scale"][ax] /= scale.get(ax, 1.0)
return xr.DataArray(data=rescaled_data, dims=image.dims, attrs=new_attrs)
def _applyToFrame(self, frameData, t, nT):
imA = frameData[0].copy()
return self._rescaleImage(imA, self._scale, self._interpolation)