Multiscale#

This module provides functionality for pyramid decomposition (downsampling/up-sampling) and wavelet transforms (analysis and synthesis) based on spline models.

Pyramid Module#

The splineops.multiscale.pyramid module implements 1-D and 2-D REDUCE/EXPAND operations with mirror boundary handling. Two-dimensional axis passes operate on whole selected axes rather than dispatching a Python call for each row or column. Explicit spatial_axes preserve and independently process any remaining batch or channel dimensions. These operations form the foundation for many wavelet constructions.

Reduction uses floor(n / 2) for odd lengths, so pyramid reduce/expand is not a reversible shape operation in that case. Wavelet analysis is stricter: both dimensions must be divisible by 2**scales.

Perfect reconstruction is established for Haar and the cubic spline filter on the tested even rectangular shapes. Order 1 has small truncation error and order 5 is approximate because its inherited taps have limited precision; see the multiscale user guide for the measured bounds.

Inputs must be finite, real, and non-empty. Floating inputs preserve their precision; integer inputs promote to float64. Scalar images need no axis argument. Higher-rank arrays require two explicit spatial axes; dimensions are never inferred as batch or channel merely from rank.

Key functionalities:

  • get_pyramid_filter Retrieve filter coefficients (g for REDUCE, h for EXPAND) plus a “centered” flag.

  • reduce_1d, expand_1d Down/upsample a 1D signal using the specified filters and mirror reflection.

  • reduce_2d, expand_2d Down/upsample two selected image axes with vectorized separable passes.

Example (pyramid usage)#

from splineops.multiscale.pyramid import get_pyramid_filter, reduce_1d, expand_1d
import numpy as np

# Retrieve filter for a spline of order 3
g, h, centered = get_pyramid_filter("Spline", 3)

# 1D reduce/expand
x = np.array([0,1,2,3,2,1,0,-2,-4,-6], dtype=float)
x_reduced = reduce_1d(x, g, centered)
x_expanded = expand_1d(x_reduced, h, centered)

print("Original:", x)
print("Reduced: ", x_reduced)
print("Expanded:", x_expanded)

# 2D reduce/expand
arr = np.random.rand(8,8).astype(np.float32)
arr_reduced = reduce_2d(arr, g, centered)
arr_expanded = expand_2d(arr_reduced, h, centered)

API Reference: Pyramid#

pyramid.py#

Implements pyramid decomposition (reduce & expand) in 1D and 2D using filters derived from spline expansions. Boundary handling is done via mirror reflection, closely mimicking original C routines:

  • “ReduceStandard_1D” / “ExpandStandard_1D”

  • “ReduceCentered_1D” / “ExpandCentered_1D”

Usage Example#

from splineops.multiscale.pyramid import (
    get_pyramid_filter,
    reduce_1d, expand_1d,
    reduce_2d, expand_2d
)
import numpy as np

# Retrieve filter
g, h, is_centered = get_pyramid_filter("Spline", 3)

# 1D reduce/expand
x = np.array([0, 1, 2, 3, 2, 1, 0, -2, -4, -6], dtype=float)
x_reduced = reduce_1d(x, g, is_centered)
x_expanded = expand_1d(x_reduced, h, is_centered)

# 2D reduce/expand
arr = np.random.rand(8, 8).astype(np.float32)
arr_reduced = reduce_2d(arr, g, is_centered)
arr_expanded = expand_2d(arr_reduced, h, is_centered)
splineops.multiscale.pyramid.get_pyramid_filter(name: str, order: int)#

Retrieve the reduce/expand filters for a particular spline family and order.

Parameters:
  • name (str) – Filter family name, e.g. “Spline”, “Centered Spline”.

  • order (int) – Spline order (e.g. 3).

Returns:

  • g (np.ndarray) – 1D filter for REDUCE operation.

  • h (np.ndarray) – 1D filter for EXPAND operation.

  • is_centered (bool) – True if the filter is a centered variant; False otherwise.

Raises:

ValueError – If the combination of name/order is not implemented.

splineops.multiscale.pyramid.wrap_reflect(i: int, n: int) int#

Mirror boundary reflection of index i into the range [0..n-1].

If n >= 2, uses period = 2*(n-1). If n < 2, everything maps to 0.

Parameters:
  • i (int) – Original index (may be out of bounds).

  • n (int) – Length of the signal.

Returns:

Reflected index within [0..n-1].

Return type:

int

splineops.multiscale.pyramid.reduce_1d(signal: ndarray, g: ndarray, centered: bool) ndarray#

Reduce a 1D signal by factor of 2 using filter g.

Parameters:
  • signal (np.ndarray) – Input 1D signal of length >= 2.

  • g (np.ndarray) – Filter for reduction (REDUCE).

  • centered (bool) – Indicates if the filter is a centered variant.

Returns:

Reduced signal of length roughly n/2.

Return type:

np.ndarray

splineops.multiscale.pyramid.expand_1d(signal: ndarray, h: ndarray, centered: bool) ndarray#

Expand a 1D signal by factor of 2 using filter h.

Parameters:
  • signal (np.ndarray) – Input 1D signal (coarse scale).

  • h (np.ndarray) – Filter for expansion (EXPAND).

  • centered (bool) – Indicates if the filter is a centered variant.

Returns:

Expanded signal of length ~ 2*n.

Return type:

np.ndarray

splineops.multiscale.pyramid.reduce_2d(image: ndarray, g: ndarray, centered: bool, *, spatial_axes=None) ndarray#

Reduce two selected image axes by a factor of two.

Parameters:
  • image (np.ndarray) – Input scalar image or array containing batch/channel dimensions.

  • g (np.ndarray) – 1D reduce filter.

  • centered (bool) – True if using centered reduce logic.

  • spatial_axes (sequence of int, optional) – Exactly two dimensions to reduce. Required for higher-rank arrays; every other dimension is preserved.

Returns:

Array with selected lengths reduced to floor(length / 2) when the length is at least two. Singleton selected dimensions stay singleton.

Return type:

np.ndarray

splineops.multiscale.pyramid.expand_2d(image: ndarray, h: ndarray, centered: bool, *, spatial_axes=None) ndarray#

Expand two selected image axes by a factor of two.

Parameters:
  • image (np.ndarray) – Input scalar image or array containing batch/channel dimensions.

  • h (np.ndarray) – 1D expand filter.

  • centered (bool) – True if using centered expand logic.

  • spatial_axes (sequence of int, optional) – Exactly two dimensions to expand. Required for higher-rank arrays; every other dimension is preserved.

Returns:

Array with selected lengths doubled when they exceed one. Singleton selected dimensions stay singleton.

Return type:

np.ndarray

Wavelet Modules#

The splineops.multiscale.wavelets subpackage provides Haar and spline-based wavelet transforms using whole-axis separable passes. Their multi-scale methods also accept two explicit spatial_axes for batched arrays. Small planes use cache-sized vectorized groups; large planes avoid whole-array transpose copies through direct independent dispatch. Classes also expose their reconstruction classification; the limited-precision order-5 table is explicitly a bounded approximation. Classes typically define:

  • analysis (multi-scale forward transform)

  • synthesis (multi-scale inverse transform)

Submodules:

API Reference: Wavelets#

abstract_wavelets.py#

Defines a base class for wavelet analysis & synthesis on 2D (or 3D) signals.

class splineops.multiscale.wavelets.abstract_wavelets.AbstractWavelets(scales=3)#

Bases: object

Base class for wavelet decomposition with multi-scale analysis & synthesis.

Subclasses must override:
  • analysis1() (single-scale wavelet decomposition)

  • synthesis1() (single-scale wavelet reconstruction)

Parameters:

scales (int) – Number of scales for multi-scale decomposition.

scales#

Number of scales for repeated analysis/synthesis steps.

Type:

int

analysis(inp: ndarray, *, spatial_axes=None) ndarray#

Multi-scale wavelet analysis on two selected dimensions. Repeatedly calls analysis1() from fine to coarse.

Parameters:
  • inp (np.ndarray) – Scalar image or array containing batch/channel dimensions.

  • spatial_axes (sequence of int, optional) – Exactly two wavelet dimensions. Required for higher-rank arrays; every remaining slice is transformed independently.

Returns:

Full wavelet decomposition (in-place layout).

Return type:

np.ndarray

analysis1(inp: ndarray) ndarray#

Single-scale wavelet transform of inp -> out. Must be overridden.

Parameters:

inp (np.ndarray) – Input array (2D or 3D typically).

Returns:

Transformed array (same shape).

Return type:

np.ndarray

get_documentation() str#

Returns a short description of the wavelet.

get_name() str#

Returns a descriptive name for the wavelet transform.

set_scale(scale: int)#

Update the number of scales.

Parameters:

scale (int) – New scale value.

synthesis(inp: ndarray, *, spatial_axes=None) ndarray#

Multi-scale wavelet synthesis on two selected dimensions. Repeatedly calls synthesis1() from coarsest to finest.

Parameters:
  • inp (np.ndarray) – Wavelet decomposition array (same shape as original).

  • spatial_axes (sequence of int, optional) – Exactly two wavelet dimensions. Required for higher-rank arrays; every remaining slice is reconstructed independently.

Returns:

Reconstructed array (same shape as input).

Return type:

np.ndarray

synthesis1(inp: ndarray) ndarray#

Single-scale inverse wavelet transform of inp -> out. Must be overridden.

Parameters:

inp (np.ndarray) – Input wavelet coefficients (single scale).

Returns:

Reconstructed array at that scale.

Return type:

np.ndarray

haar.py#

Implements a 2D Haar wavelet transform via row->column decomposition (analysis) and column->row synthesis. Requires ny >= 2 and nx >= 2.

class splineops.multiscale.wavelets.haar.HaarWavelets(scales=3)#

Bases: AbstractWavelets

A 2D Haar wavelet transform for images with shape (ny, nx).

Parameters:

scales (int) – Number of scales (defaults to 3).

q#

Normalization factor, sqrt(2).

Type:

float

Raises:

ValueError – If ny < 2 or nx < 2 at any scale.

Notes

Single-scale steps:
  1. row-wise split

  2. column-wise split

Synthesis:
  1. column-wise merge

  2. row-wise merge

analysis1(inp: ndarray) ndarray#

Single-scale 2D Haar analysis (row-split, then col-split).

Parameters:

inp (np.ndarray) – 2D array with shape (ny, nx), both >= 2.

Returns:

Transformed array (same shape).

Return type:

np.ndarray

get_documentation()#

Return short docstring for Haar wavelets.

get_name()#

Return ‘Haar2D’.

synthesis1(inp: ndarray) ndarray#

Single-scale 2D Haar synthesis (inverse of analysis1).

Parameters:

inp (np.ndarray) – 2D array (ny, nx), both >= 2.

Returns:

Reconstructed array.

Return type:

np.ndarray

spline_wavelets.py#

Implements Spline wavelet transforms of orders 1, 3, 5.

class splineops.multiscale.wavelets.spline_wavelets.Spline1Wavelets(scales=3)#

Bases: SplineWavelets

Spline Wavelets of order=1.

get_documentation()#

Return a short docstring describing the spline wavelet order.

get_name()#

Return ‘Spline{order}’.

class splineops.multiscale.wavelets.spline_wavelets.Spline3Wavelets(scales=3)#

Bases: SplineWavelets

Spline Wavelets of order=3.

get_documentation()#

Return a short docstring describing the spline wavelet order.

get_name()#

Return ‘Spline{order}’.

class splineops.multiscale.wavelets.spline_wavelets.Spline5Wavelets(scales=3)#

Bases: SplineWavelets

Approximate order-5 spline wavelets using limited-precision source taps.

get_documentation()#

Return a short docstring describing the spline wavelet order.

get_name()#

Return ‘Spline{order}’.

class splineops.multiscale.wavelets.spline_wavelets.SplineWavelets(scales=3, order=3)#

Bases: AbstractWavelets

A generic spline wavelet class that references a given ‘order’ (1,3,5). Uses row->column passes with mirror boundary to compute detail.

Parameters:
  • scales (int) – Number of scales.

  • order (int) – Spline order (1,3,5).

filter#

Holds the arrays h[] (lowpass) and g[] (highpass).

Type:

SplineFilter

analysis1(inp: ndarray) ndarray#

Single-scale 2D spline wavelet analysis pass: - Row pass (splitMirror) - Column pass (splitMirror)

Parameters:

inp (np.ndarray) – 2D array.

Returns:

Transformed 2D array (same shape).

Return type:

np.ndarray

property exact_reconstruction#

Whether the bundled tap precision supports a perfect-reconstruction claim.

get_documentation()#

Return a short docstring describing the spline wavelet order.

get_name()#

Return ‘Spline{order}’.

property reconstruction_contract#

Published reconstruction classification for the selected filter.

synthesis1(inp: ndarray) ndarray#

Single-scale 2D spline wavelet synthesis pass: - Column pass (mergeMirror) - Row pass (mergeMirror)

Parameters:

inp (np.ndarray) – 2D array of wavelet coefficients (one scale).

Returns:

Reconstructed array (same shape).

Return type:

np.ndarray

spline_wavelets_tool.py#

Uses a SplineFilter to get h[] and g[], then does ‘splitMirror’ and ‘mergeMirror’ passes on rows, then columns.

class splineops.multiscale.wavelets.spline_wavelets_tool.SplineWaveletsTool(scale: int, order: int)#

Bases: object

Equivalent of SplineWaveletsTool.java for 2D analysis/synthesis.

Parameters:
  • scale (int) – Number of scales (used externally, if needed).

  • order (int) – Spline order, e.g. 3.

filters#

Holds arrays h (lowpass) and g (highpass).

Type:

SplineFilter

analysis1(inp)#

Single-scale 2D analysis (row pass then column pass).

synthesis1(inp)#

Single-scale 2D synthesis (inverse).

splineops.multiscale.wavelets.spline_wavelets_tool.merge_mirror_1d(vin: ndarray, h: ndarray, g: ndarray) ndarray#

Inverse of split_mirror_1d. Recombines lowpass and highpass into original signal.

Parameters:
  • vin (np.ndarray) – 1D array, half is lowpass, half is highpass.

  • h (np.ndarray) – Lowpass filter.

  • g (np.ndarray) – Highpass filter.

Returns:

1D reconstructed array.

Return type:

np.ndarray

splineops.multiscale.wavelets.spline_wavelets_tool.split_mirror_1d(vin: ndarray, h: ndarray, g: ndarray) ndarray#

1D mirror-based ‘split’ producing lowpass + highpass sub-bands.

Parameters:
  • vin (np.ndarray) – 1D input array.

  • h (np.ndarray) – Lowpass filter coefficients.

  • g (np.ndarray) – Highpass filter coefficients.

Returns:

1D array same length as vin, first half = lowpass, second half = detail.

Return type:

np.ndarray