curvelets.numpy package¶
- class curvelets.numpy.MeyerWavelet(shape)¶
Bases:
objectMulti-dimensional Meyer wavelet transform with pre-computed filters.
This class provides forward and backward Meyer wavelet transforms with filters pre-computed during initialization for improved performance. The forward transform returns all subbands in a nested list structure, and the backward transform accepts this full structure for reconstruction.
The filter computation uses the same method as UDCT’s _create_bandpass_windows() for num_scales=2, ensuring compatibility when used with UDCT in wavelet mode with num_scales=2 and high_frequency_mode=”meyer”.
- Parameters:
shape (tuple[int, ...]) – Expected shape of input signals. Used for validation and to determine the number of dimensions. All dimensions must be even (divisible by 2).
- Raises:
ValueError – If any dimension in shape is odd (not divisible by 2).
Notes
This implementation requires all dimensions to be even. Odd-length signals are not supported due to the downsampling strategy used in the transform, which produces mismatched subband sizes that cannot be correctly reconstructed.
Examples
>>> import numpy as np >>> from curvelets.numpy import MeyerWavelet >>> wavelet = MeyerWavelet(shape=(64, 64)) >>> signal = np.random.randn(64, 64) >>> coefficients = wavelet.forward(signal) >>> len(coefficients) # 2 subband groups 2 >>> coefficients[0][0].shape # Lowpass subband (32, 32) >>> len(coefficients[1]) # Highpass subbands 3 >>> reconstructed = wavelet.backward(coefficients) >>> np.allclose(signal, reconstructed, atol=1e-10) True >>> # Odd dimensions raise an error >>> try: ... MeyerWavelet(shape=(65, 65)) ... except ValueError: ... print("Odd dimensions not supported") Odd dimensions not supported
- backward(coefficients)¶
Apply multi-dimensional Meyer wavelet inverse transform.
Reconstructs the original signal from the full coefficient structure returned by forward().
- Parameters:
coefficients (list[list[
npt.NDArray[F]|npt.NDArray[C]]]) –Full coefficient structure from forward() with 2 subband groups:
coefficients[0]: [lowpass] - single lowpass subband
coefficients[1]: [highpass_0, highpass_1, …] - all highpass subbands
- Returns:
Reconstructed signal with shape matching the original input.
- Return type:
npt.NDArray[F]|npt.NDArray[C]- Raises:
ValueError – If coefficients structure is invalid (must have 2 subband groups).
Examples
>>> import numpy as np >>> from curvelets.numpy import MeyerWavelet >>> wavelet = MeyerWavelet(shape=(64, 64)) >>> signal = np.random.randn(64, 64) >>> coefficients = wavelet.forward(signal) >>> reconstructed = wavelet.backward(coefficients) >>> np.allclose(signal, reconstructed, atol=1e-10) True
- forward(signal)¶
Apply multi-dimensional Meyer wavelet forward transform.
Decomposes the input signal into 2^dimension subbands organized into 2 subband groups. Returns all subbands in a nested list structure similar to UDCT.
- Parameters:
signal (
npt.NDArray[F]|npt.NDArray[C]) – Input array (real or complex). Must match the shape specified during initialization.- Returns:
All subbands organized into 2 subband groups:
coefficients[0]: [lowpass] - single lowpass subband (1 subband)
coefficients[1]: [highpass_0, highpass_1, …] - all highpass subbands (2^dimension - 1 subbands)
Each subband has shape approximately half the input shape in each dimension.
- Return type:
list[list[
npt.NDArray[F]|npt.NDArray[C]]]- Raises:
ValueError – If signal shape does not match expected shape.
Examples
>>> import numpy as np >>> from curvelets.numpy import MeyerWavelet >>> wavelet = MeyerWavelet(shape=(64, 64)) >>> signal = np.random.randn(64, 64) >>> coefficients = wavelet.forward(signal) >>> len(coefficients) # 2 subband groups 2 >>> coefficients[0][0].shape # Lowpass subband (32, 32) >>> len(coefficients[1]) # Highpass subbands 3
- class curvelets.numpy.UDCT(shape, angular_wedges_config=None, num_scales=None, wedges_per_direction=None, window_overlap=None, radial_frequency_params=None, window_threshold=1e-05, high_frequency_mode='curvelet', transform_kind='real')¶
Bases:
objectUniform Discrete Curvelet Transform (UDCT) implementation.
This class provides forward and backward curvelet transforms with support for both real and complex transforms.
- Parameters:
angular_wedges_config (
np.ndarray, optional) – Configuration array specifying the number of angular wedges per scale and dimension. Shape is (num_scales - 1, dimension), where num_scales includes the lowpass scale. If provided, cannot be used together with num_scales/wedges_per_direction. Default is None.num_scales (int, optional) – Total number of scales (including lowpass scale 0). Must be >= 2. Used when angular_wedges_config is not provided. Default is 3.
wedges_per_direction (int, optional) – Number of angular wedges per direction at the coarsest scale. The number of wedges doubles at each finer scale. Must be >= 3. Used when angular_wedges_config is not provided. Default is 3.
window_overlap (float, optional) – Window overlap parameter controlling the smoothness of window transitions. If None and using num_scales/wedges_per_direction, automatically chosen based on wedges_per_direction. Default is None (auto) or 0.15.
radial_frequency_params (tuple[float, float, float, float], optional) – Radial frequency parameters defining the frequency bands. Default is (\(\pi/3\), \(2\pi/3\), \(2\pi/3\), \(4\pi/3\)).
window_threshold (float, optional) – Threshold for sparse window storage (values below this are stored as sparse). Default is 1e-5.
high_frequency_mode ({"curvelet", "wavelet"}, optional) – High frequency mode. “curvelet” uses curvelets at all scales, “wavelet” creates a single ring-shaped window (bandpass filter only, no angular components) at the highest scale with decimation=1. Default is “curvelet”.
transform_kind ({"real", "complex", "monogenic"}, optional) –
Type of transform to use:
”real” (default): Real transform where each band captures both positive and negative frequencies combined.
”complex”: Complex transform which separates positive and negative frequency components into different bands. Each band is scaled by \(\sqrt{0.5}\).
”monogenic”: Monogenic transform that extends the curvelet transform by applying Riesz transforms, producing ndim+1 components per band (scalar plus all Riesz components).
- parameters¶
Internal UDCT parameters.
- Type:
ParamUDCT
- windows¶
Curvelet windows in sparse format.
- Type:
UDCTWindows
Examples
>>> import numpy as np >>> from curvelets.numpy import UDCT >>> # Create a 2D transform using num_scales (simplified interface) >>> transform = UDCT(shape=(64, 64), num_scales=3, wedges_per_direction=3) >>> data = np.random.randn(64, 64) >>> coeffs = transform.forward(data) >>> recon = transform.backward(coeffs) >>> np.allclose(data, recon, atol=1e-4) True >>> # Create using angular_wedges_config (advanced interface) >>> cfg = np.array([[3, 3], [6, 6]]) >>> transform2 = UDCT(shape=(64, 64), angular_wedges_config=cfg) >>> coeffs2 = transform2.forward(data) >>> recon2 = transform2.backward(coeffs2) >>> np.allclose(data, recon2, atol=1e-4) True
- backward(coefficients)¶
Apply backward curvelet transform (reconstruction).
- Parameters:
coefficients (list[list[list[
npt.NDArray[C]]]]) – Curvelet coefficients from forward transform.- Returns:
Reconstructed data with shape matching self.shape.
When transform_kind=”real”: Returns real array (reconstructed input \(f\))
When transform_kind=”complex”: Returns complex array (reconstructed input \(f\))
When transform_kind=”monogenic”: Returns tuple of ndim+1 real-valued arrays \(M_f = (f, -R_1f, -R_2f, \ldots, -R_nf)\) where \(R_k\) are the Riesz transforms. This is the monogenic signal \(M_f\), not just \(f\). To get only \(f\), use the first element of the tuple, or use
.monogenic()method directly.
- Return type:
np.ndarray| tuple[npt.NDArray[F], …]
Notes
For transform_kind=”monogenic”, the backward transform returns the monogenic signal \(M_f = (f, -R_1f, -R_2f, \ldots, -R_nf)\) rather than just the original function \(f\). This matches the output of the
.monogenic()method. The first component of the tuple is \(f\), and the remaining components are the Riesz transform components.Examples
>>> import numpy as np >>> from curvelets.numpy import UDCT >>> transform = UDCT(shape=(64, 64)) >>> data = np.random.randn(64, 64) >>> coeffs = transform.forward(data) >>> recon = transform.backward(coeffs) >>> np.allclose(data, recon, atol=1e-4) True
- forward(image)¶
Apply forward curvelet transform.
- Parameters:
image (
npt.NDArray[F]|npt.NDArray[C]) – Input data with shape matching self.shape. - For transform_kind=”real” or “monogenic”: must be real-valued (npt.NDArray[F]) - For transform_kind=”complex”: can be real-valued or complex-valued- Returns:
Curvelet coefficients as nested list structure. When transform_kind=”complex”, directions are doubled (first ndim directions for positive frequencies, next ndim for negative). Coefficients have complex dtype matching the input: - np.float32 input -> np.complex64 coefficients - np.float64 input -> np.complex128 coefficients - np.complex64 input -> np.complex64 coefficients - np.complex128 input -> np.complex128 coefficients
- Return type:
list[list[list[
npt.NDArray[C]]]]
Examples
>>> import numpy as np >>> from curvelets.numpy import UDCT >>> transform = UDCT(shape=(64, 64)) >>> data = np.random.randn(64, 64) >>> coeffs = transform.forward(data) >>> len(coeffs) # Number of scales 4
- monogenic(image)¶
Compute monogenic signal directly without curvelet transform.
This method computes the monogenic signal Mf = f + i₁(-R₁f) + i₂(-R₂f) + … + iₙ(-Rₙf) directly from the input function without performing the curvelet transform. The monogenic signal provides a representation that enables meaningful amplitude/phase decomposition for N-D signals.
The monogenic signal was originally defined for 2D signals by Storath 2010 [1] using quaternions, but this implementation extends it to arbitrary N-D signals by using all Riesz transform components.
- Parameters:
image (
npt.NDArray[F]) – Input image or volume. Must be real-valued (floating point dtype). Must have shape matching self.shape. Complex inputs are not supported as the monogenic transform is defined only for real-valued functions.- Returns:
Tuple of ndim+1 real-valued arrays with shape matching self.shape: - scalar: Original input \(f\) (unchanged) - riesz_k: \(-R_k f\) for \(k = 1, 2, \ldots, \text{ndim}\)
- Return type:
tuple[
npt.NDArray[F], …]- Raises:
ValueError – If input is complex-valued. Use forward() for complex inputs.
AssertionError – If input shape does not match self.shape.
Notes
This method computes the monogenic signal directly using Riesz transforms without performing the curvelet decomposition. It is mathematically equivalent to backward(forward(f)) with transform_kind=”monogenic” but computationally simpler.
The monogenic signal is defined as: Mf = f + i₁(-R₁f) + i₂(-R₂f) + … + iₙ(-Rₙf)
where R₁, R₂, …, Rₙ are the Riesz transforms. Since Python doesn’t have native quaternion or Clifford algebra types, this method returns the components as a tuple.
References
Examples
>>> import numpy as np >>> from curvelets.numpy import UDCT >>> transform = UDCT(shape=(64, 64)) >>> data = np.random.randn(64, 64) >>> components = transform.monogenic(data) >>> scalar = components[0] >>> scalar.shape (64, 64) >>> np.allclose(data, scalar) True >>> # Verify it matches backward(forward(f)) with transform_kind="monogenic" >>> transform_mono = UDCT(shape=(64, 64), transform_kind="monogenic") >>> coeffs = transform_mono.forward(data) >>> components2 = transform_mono.backward(coeffs) >>> np.allclose(scalar, components2[0], atol=1e-4) True >>> np.allclose(components[1], components2[1], atol=1e-4) True
- struct(coefficients_vec)¶
Convert vector representation to structured coefficients.
- Parameters:
coefficients_vec (
np.ndarray) – Flattened vector of coefficients.- Returns:
Structured curvelet coefficients. For monogenic transforms, each coefficient is a list of ndim+1 arrays.
- Return type:
list[list[list[
npt.NDArray[C]]]] | MUDCTCoefficients
Examples
>>> import numpy as np >>> from curvelets.numpy import UDCT >>> transform = UDCT(shape=(64, 64)) >>> data = np.random.randn(64, 64) >>> coeffs = transform.forward(data) >>> vec = transform.vect(coeffs) >>> coeffs_recon = transform.struct(vec) >>> len(coeffs_recon) == len(coeffs) True
- vect(coefficients)¶
Convert structured coefficients to vector representation.
- Parameters:
coefficients (list[list[list[
npt.NDArray[C]]]] | MUDCTCoefficients) – Structured curvelet coefficients. For monogenic transforms, each coefficient is a list of ndim+1 arrays.- Returns:
Flattened vector of all coefficients.
- Return type:
Examples
>>> import numpy as np >>> from curvelets.numpy import UDCT >>> transform = UDCT(shape=(64, 64)) >>> data = np.random.randn(64, 64) >>> coeffs = transform.forward(data) >>> vec = transform.vect(coeffs) >>> vec.shape (4096,)