Source code for torx.analysis.smoothing.smoothing_2d_m
"""
Provides smoothing functionality for 2D arrays (field data).
All Fourier-based filters pad the array edges before filtering and strip
the padding afterwards, since Fourier methods degrade near array boundaries.
Increase edge_pad or upsample the array first for stronger filtering.
"""
import numpy as np
import scipy.ndimage
from numpy.fft import fft2, ifft2
from torx.arrays import pad_array
from torx.decorators import autodoc_function
[docs]
@autodoc_function
def smooth_2d_gaussian(
image: np.ndarray,
filter_strength: float = 10.0,
edge_pad: int = 100,
) -> np.ndarray:
"""
Apply a Gaussian filter in the Fourier domain to a 2D array.
The array is multiplied by the Fourier transform of a Gaussian kernel.
Higher filter_strength removes more high-frequency content.
Parameters
----------
image:
2D input array.
filter_strength:
Standard deviation of the Gaussian kernel (in pixels).
edge_pad:
Number of points to pad on each edge before filtering.
"""
padded = pad_array(image, left=edge_pad, right=edge_pad, top=edge_pad, bottom=edge_pad)
filtered = ifft2(
scipy.ndimage.fourier_gaussian(fft2(padded), sigma=filter_strength)
).real
return filtered[edge_pad:-edge_pad, edge_pad:-edge_pad] if edge_pad else filtered
[docs]
@autodoc_function
def smooth_2d_ellipsoid(
image: np.ndarray,
filter_strength: float = 20.0,
edge_pad: int = 100,
) -> np.ndarray:
"""
Apply an ellipsoid filter in the Fourier domain to a 2D array.
The array is multiplied by the Fourier transform of an ellipsoid of given size.
Parameters
----------
image:
2D input array.
filter_strength:
Size of the ellipsoid kernel (in pixels).
edge_pad:
Number of points to pad on each edge before filtering.
"""
padded = pad_array(image, left=edge_pad, right=edge_pad, top=edge_pad, bottom=edge_pad)
filtered = ifft2(
scipy.ndimage.fourier_ellipsoid(fft2(padded), size=filter_strength)
).real
return filtered[edge_pad:-edge_pad, edge_pad:-edge_pad] if edge_pad else filtered
[docs]
@autodoc_function
def smooth_2d_butterworth(
image: np.ndarray,
cutoff: float = 10.0,
order: int = 2,
edge_pad: int = 100
) -> np.ndarray:
"""
Apply a low-pass 2D Butterworth Fourier filter.
This filter attenuates high frequencies and preserves low frequencies.
It is ideal for removing high-frequency noise, smoothing out sharp
transitions or pixelated artifacts.
It gives you a smooth result without introducing unwanted distortion.
Parameters
----------
image:
2D input array.
cutoff:
Butterworth cutoff (in multiples of the lowest discrete frequency).
Lower values apply stronger filtering.
order:
Determines how sharp is the cutoff transition.
Lower order (~1-2) behaves like a Gaussian filter - smooth transition.
Higher order (>5) behaves like an ideal filter.
edge_pad:
Number of points to pad on each edge before filtering.
"""
if edge_pad:
image = pad_array(
image, left=edge_pad, right=edge_pad, top=edge_pad, bottom=edge_pad
)
ny, nx = image.shape
freq_y = np.fft.fftfreq(ny)
freq_x = np.fft.fftfreq(nx)
freq_mesh_x, freq_mesh_y = np.meshgrid(freq_x, freq_y)
lowest_freq = 1.0 / max(nx, ny)
cutoff_freq = cutoff * lowest_freq
freq = np.sqrt(freq_mesh_x**2 + freq_mesh_y**2)
mask = 1.0 / (1.0 + (freq / cutoff_freq)**(2 * order))
filtered_image = ifft2(fft2(image) * mask).real
if edge_pad > 0:
return filtered_image[edge_pad:-edge_pad, edge_pad:-edge_pad]
return filtered_image