Skip to content

bounds

MODULE DESCRIPTION
indexing

Functions that wrap out-of-bound indices back in-bounds, according to some boundary condition.

padding

Reimplements torch.nn.functional.pad and torch.roll with a larger set of boundary conditions.

realtransforms

Implements the discrete sine and cosine transforms, variants I, II, III.

types

Defines names and aliases for different boundary conditions, as well as tools to convert between different naming conventions.

FUNCTION DESCRIPTION
pad

Pad a tensor

roll

Roll a tensor

ensure_shape

Pad/crop a tensor so that it has a given shape

to_enum

Convert any boundary type to BoundType

to_int

Convert any boundary type to BoundType-based integer values

to_fourier

Convert any boundary type to discrete transforms

to_scipy

Convert any boundary type to scipy.ndimage convention

to_torch

Convert any boundary type to torch.grid_sample convention

dct

One-dimensional Discrete Cosine Transform (DCT)

dst

One-dimensional Discrete Sine Transform (DST)

idct

One-dimensional Inverse Discrete Cosine Transform (DCT)

idst

One-dimensional Inverse Discrete Sine Transform (DST)

dctn

N-dimensional Discrete Cosine Transform (IDCT)

dstn

N-dimensional Discrete Sine Transform (IDST)

idctn

N-dimensional Inverse Discrete Cosine Transform (IDCT)

idstn

N-dimensional Inverse Discrete Sine Transform (IDST)

CLASS DESCRIPTION
BoundType

Enum type for bounds

ATTRIBUTE DESCRIPTION
BoundLike

A type hint for any boundary type

SequenceOrScalar

A type hint for values or sequences of values

SequenceOrScalar module-attribute

SequenceOrScalar = Union[T, Sequence[T]]

Either an element or type T, or a sequence of elements of type T.

BoundLike module-attribute

BoundLike = Union[BoundType, str, int]

A boundary mode.

Most conventions are handled (numpy, scipy, torch, see below). Can be one of:

  1. zero, zeros, constant or gridconstant;
  2. replicate, nearest, border or edge;
  3. dct1 or mirror;
  4. dct2, reflect, reflection, gridmirror or neumann;
  5. dst1 or antimirror;
  6. dst2, antireflect or dirichlet;
  7. dft, fft, wrap, gridwrap, circular or circulant.

Each of these modes can be a BoundType value (e.g., BoundType.mirror), or its string representation (e.g., "mirror").

The aliases dft, dct1, dct2, dst1 and dst2 exist because these boundary modes correspond to the implicit boundary conditions of each of these frequency transform:

The reason why so many aliases are supported is that there is no common convention across python packages to name boundary conditions. This table contains an extensive list of aliases:

Fourier

SciPy ndimage

Numpy pad

PyTorch pad

PyTorch grid_sample

Other

Description

nearest

edge

border

replicate

repeat

a a | a b c d | d d

constant,

grid-constant

constant

constant

zeros

zero

0 0 | a b c d | 0 0

dct1

mirror

reflect

reflect

reflection

(False)

c b | a b c d | c b

dct2

reflect,

grid-mirror

symmetric

reflection

(True)

neumann

b a | a b c d | d c

dst1

antimirror

-a 0 | a b c d | 0 -d

dst2

antireflect,
dirichlet

-b -a | a b c d | -d -c

dft

grid-wrap

wrap

circular

circulant

c d | a b c d | a b

wrap

c d | a b c d | b c

linear_ramp

minimum,

maximum,

mean,

median

Some of these conventions are inconsistant with each other. For example "wrap" in scipy.ndimage is different from "wrap" in numpy.pad, which corresponds to "grid-wrap" in scipy.ndimage. Also, "reflect" in numpy.pad and torch.pad is different from "reflect" in scipy.ndimage, which correspond to "symmetric" in numpy.pad.

BoundType

Bases: Enum

An Enum type that maps boundry modes of any convention to a unique set of values.

class BoundType(Enum):
    zero = zeros = constant = gridconstant = 0
    replicate = repeat = nearest = border = edge = 1
    dct1 = mirror = 2
    dct2 = reflect = reflection = gridmirror = neumann = 3
    dst1 = antimirror = 4
    dst2 = antireflect = dirichlet = 5
    dft = fft = wrap = gridwrap = circular = circulant = 6
    nocheck = -1

pad

pad(inp, padsize, mode='constant', value=0, side=None)

Pad a tensor.

This function is a bit more generic than torch's native pad (torch.nn.functional.pad), but probably a bit slower:

  • works with any input type
  • works with arbitrarily large padding size
  • crops the tensor for negative padding values
  • implements additional padding modes

When used with defaults parameters (side=None), it behaves exactly like torch.nn.functional.pad

Boundary modes

Like in PyTorch's pad, boundary modes include:

  • 'circular' (or 'dft')
  • 'mirror' (or 'dct1')
  • 'reflect' (or 'dct2')
  • 'replicate' (or 'nearest')
  • 'constant' (or 'zero')

as well as the following new modes:

  • 'antimirror' (or 'dst1')
  • 'antireflect' (or 'dst2')

Side modes

Side modes are 'pre' (or 'left'), 'post' (or 'right'), 'both' or None.

  • If side is not None, inp.dim() values (or less) should be provided.
  • If side is None, twice as many values should be provided, indicating different padding sizes for the 'pre' and 'post' sides.
  • If the number of padding values is less than the dimension of the input tensor, zeros are prepended.
PARAMETER DESCRIPTION
inp

Input tensor

TYPE: tensor

padsize

Amount of padding in each dimension.

TYPE: SequenceOrScalar[int]

mode

Padding mode

TYPE: SequenceOrScalar[BoundLike] DEFAULT: 'constant'

value

Value to pad with in mode 'constant'.

TYPE: scalar DEFAULT: 0

side

Use padsize to pad on left side ('pre'), right side ('post') or both sides ('both'). If None, the padding side for the left and right sides should be provided in alternate order.

TYPE: {'pre', 'post', 'both', None} DEFAULT: None

RETURNS DESCRIPTION
out

Padded tensor.

TYPE: tensor

Source code in bounds/padding.py
def pad(
    inp: Tensor,
    padsize: SequenceOrScalar[int],
    mode: SequenceOrScalar[BoundLike] = 'constant',
    value: Number = 0,
    side: Optional[str] = None
):
    """Pad a tensor.

    This function is a bit more generic than torch's native pad
    (`torch.nn.functional.pad`), but probably a bit slower:

    - works with any input type
    - works with arbitrarily large padding size
    - crops the tensor for negative padding values
    - implements additional padding modes

    When used with defaults parameters (`side=None`), it behaves
    exactly like `torch.nn.functional.pad`

    !!! info "Boundary modes"
        Like in PyTorch's `pad`, boundary modes include:

        - `'circular'`  (or `'dft'`)
        - `'mirror'`    (or `'dct1'`)
        - `'reflect'`   (or `'dct2'`)
        - `'replicate'` (or `'nearest'`)
        - `'constant'`  (or `'zero'`)

        as well as the following new modes:

        - `'antimirror'`    (or `'dst1'`)
        - `'antireflect'`   (or `'dst2'`)

    !!! info "Side modes"
        Side modes are `'pre'` (or `'left'`), `'post'` (or `'right'`),
        `'both'` or `None`.

        - If side is not `None`, `inp.dim()` values (or less) should be
          provided.
        - If side is `None`, twice as many values should be provided,
          indicating different padding sizes for the `'pre'` and `'post'`
          sides.
        - If the number of padding values is less than the dimension of the
          input tensor, zeros are prepended.

    Parameters
    ----------
    inp : tensor
        Input tensor
    padsize : SequenceOrScalar[int]
        Amount of padding in each dimension.
    mode : SequenceOrScalar[BoundLike]
        Padding mode
    value : scalar
        Value to pad with in mode `'constant'`.
    side : "{'pre', 'post', 'both', None}"
        Use padsize to pad on left side (`'pre'`), right side (`'post'`) or
        both sides (`'both'`). If `None`, the padding side for the left and
        right sides should be provided in alternate order.

    Returns
    -------
    out : tensor
        Padded tensor.

    """
    # Argument checking
    mode = to_fourier(mode)
    mode = ensure_list(mode, len(padsize) // (1 if side else 2))

    padsize = tuple(padsize)
    if not side:
        if len(padsize) % 2:
            raise ValueError('Padding length must be divisible by 2')
        padpre = padsize[::2]
        padpost = padsize[1::2]
    else:
        side = side.lower()
        if side == 'both':
            padpre = padsize
            padpost = padsize
        elif side in ('pre', 'left'):
            padpre = padsize
            padpost = (0,) * len(padpre)
        elif side in ('post', 'right'):
            padpost = padsize
            padpre = (0,) * len(padpost)
        else:
            raise ValueError(f'Unknown side `{side}`')
    padpre = (0,) * max(0, inp.ndim-len(padpre)) + padpre
    padpost = (0,) * max(0, inp.ndim-len(padpost)) + padpost
    if inp.dim() != len(padpre) or inp.dim() != len(padpost):
        raise ValueError('Padding length too large')

    # Pad
    mode = ['nocheck'] * max(0, inp.ndim-len(mode)) + mode
    if all(m in ('zero', 'nocheck') for m in mode):
        return _pad_constant(inp, padpre, padpost, value)
    else:
        bound = [getattr(indexing, m) for m in mode]
        return _pad_bound(inp, padpre, padpost, bound)

ensure_shape

ensure_shape(inp, shape, mode='constant', value=0, side='post', ceil=False)

Pad/crop a tensor so that it has a given shape

PARAMETER DESCRIPTION
inp

Input tensor

TYPE: tensor

shape

Output shape

TYPE: SequenceOrScalar[int]

mode

Boundary mode

TYPE: SequenceOrScalar[BoundLike] DEFAULT: 'constant'

value

Value for mode 'constant'

TYPE: scalar DEFAULT: 0

side

Side to crop/pad

TYPE: {'pre', 'post', 'both'} DEFAULT: 'post'

RETURNS DESCRIPTION
out

Padded tensor with shape shape

TYPE: tensor

Source code in bounds/padding.py
def ensure_shape(
    inp: Tensor,
    shape: SequenceOrScalar[Optional[int]],
    mode: SequenceOrScalar[BoundLike] = 'constant',
    value: Number = 0,
    side: str = 'post',
    ceil: bool = False
):
    """Pad/crop a tensor so that it has a given shape

    Parameters
    ----------
    inp : tensor
        Input tensor
    shape : SequenceOrScalar[int]
        Output shape
    mode : SequenceOrScalar[BoundLike]
        Boundary mode
    value : scalar, default=0
        Value for mode `'constant'`
    side : "{'pre', 'post', 'both'}"
        Side to crop/pad

    Returns
    -------
    out : tensor
        Padded tensor with shape `shape`

    """
    if isinstance(shape, int):
        shape = [shape]
    shape = list(shape)
    shape = [None] * max(0, inp.ndim - len(shape)) + shape
    if inp.ndim < len(shape):
        inp = inp.reshape((1,) * max(0, len(shape) - inp.ndim) + inp.shape)
    inshape = inp.shape
    shape = [inshape[d] if shape[d] is None else shape[d]
             for d in range(len(shape))]
    ndim = len(shape)

    half = (lambda x: int(math.ceil(x/2))) if ceil else (lambda x: x//2)

    # crop
    if side == 'both':
        crop = [max(0, inshape[d] - shape[d]) for d in range(ndim)]
        index = tuple(slice(half(c), (half(c) - c) or None) for c in crop)
    elif side == 'pre':
        crop = [max(0, inshape[d] - shape[d]) for d in range(ndim)]
        index = tuple(slice(-c or None) for c in crop)
    else:  # side == 'post'
        index = tuple(slice(min(shape[d], inshape[d])) for d in range(ndim))
    inp = inp[index]

    # pad
    pad_size = [max(0, shape[d] - inshape[d]) for d in range(ndim)]
    if side == 'both':
        pad_size = [[half(p), p-half(p)] for p in pad_size]
        pad_size = [q for p in pad_size for q in p]
        side = None
    inp = pad(inp, tuple(pad_size), mode=mode, value=value, side=side)

    return inp

roll

roll(inp, shifts=1, dims=None, bound='circular')

Like torch.roll, but with any boundary condition

Warning

When dims is None, we do not flatten but shift all dimensions. This differs from the behavior of torch.roll .

PARAMETER DESCRIPTION
inp

Input

TYPE: tensor

shifts

Amount by which to roll. Positive shifts to the right, negative to the left.

TYPE: SequenceOrScalar[int] DEFAULT: 1

dims

Dimensions to roll. By default, shifts apply to all dimensions if a scalar, or to the last N if a sequence.

TYPE: SequenceOrScalar[int] DEFAULT: None

bound

Boundary condition

TYPE: SequenceOrScalar[BoundLike] DEFAULT: 'circular'

RETURNS DESCRIPTION
out

Rolled tensor

TYPE: tensor

Source code in bounds/padding.py
def roll(
    inp: Tensor,
    shifts: SequenceOrScalar[int] = 1,
    dims: Optional[SequenceOrScalar[int]] = None,
    bound: SequenceOrScalar[BoundLike] = 'circular'
):
    r"""Like `torch.roll`, but with any boundary condition

    !!! warning
        When `dims` is `None`, we do not flatten but shift all dimensions.
        This differs from the behavior of `torch.roll` .

    Parameters
    ----------
    inp : tensor
        Input
    shifts : SequenceOrScalar[int]
        Amount by which to roll.
        Positive shifts to the right, negative to the left.
    dims : SequenceOrScalar[int]
        Dimensions to roll.
        By default, shifts apply to all dimensions if a scalar,
        or to the last N if a sequence.
    bound : SequenceOrScalar[BoundLike]
        Boundary condition

    Returns
    -------
    out : tensor
        Rolled tensor

    """
    if dims is None:
        if isinstance(shifts, int):
            dims = list(range(inp.dim()))
        else:
            shifts = ensure_list(shifts)
            dims = list(range(-len(shifts), 0))
    dims = ensure_list(dims)
    shifts = ensure_list(shifts, len(dims))
    bound = map(to_fourier, ensure_list(bound, len(dims)))
    bound = [getattr(indexing, b + '_') for b in bound]

    grid = [torch.arange(n, device=inp.device) for n in inp.shape]
    mult = [1] * inp.dim()
    for d, s, b in zip(dims, shifts, bound):
        grid[d] -= s
        grid[d], mult[d] = b(grid[d], inp.shape[d])
    grid = list(meshgrid_list_ij(grid))
    if any(map(torch.is_tensor, mult)):
        mult = meshgrid_list_ij(mult)
    mult = prod(mult)
    grid = sub2ind_list(grid, inp.shape)

    out = inp.flatten()[grid]
    out *= mult
    return out

to_enum

to_enum(bound)

Convert boundary type to enum type.

PARAMETER DESCRIPTION
bound

Boundary condition in any convention

TYPE: SequenceOrScalar[BoundLike]

RETURNS DESCRIPTION
bound

Boundary condition

TYPE: SequenceOrScalar[BoundType]

Source code in bounds/types.py
def to_enum(bound: SequenceOrScalar[BoundLike]) -> SequenceOrScalar[BoundType]:
    """Convert boundary type to enum type.

    !!! note "See also"
        * [`to_fourier`][bounds.types.to_fourier]
        * [`to_scipy`][bounds.types.to_scipy]
        * [`to_torch`][bounds.types.to_torch]
        * [`to_int`][bounds.types.to_int]

    Parameters
    ----------
    bound : SequenceOrScalar[BoundLike]
        Boundary condition in any convention

    Returns
    -------
    bound : SequenceOrScalar[BoundType]
        Boundary condition

    """
    intype = type(bound)
    if not isinstance(bound, (list, tuple)):
        bound = [bound]
    obound = []
    for b in bound:
        if isinstance(b, str):
            b = b.lower()
        if b in (*zero_bounds, BoundType.zero, 0):
            obound.append(BoundType.zero)
        elif b in (*rept_bounds, BoundType.border, 1):
            obound.append(BoundType.replicate)
        elif b in (*dct1_bounds, BoundType.dct1, 2):
            obound.append(BoundType.dct1)
        elif b in (*dct2_bounds, BoundType.dct2, 3):
            obound.append(BoundType.dct2)
        elif b in (*dst1_bounds, BoundType.dst1, 4):
            obound.append(BoundType.dst1)
        elif b in (*dst2_bounds, BoundType.dst2, 5):
            obound.append(BoundType.dst2)
        elif b in (*dft_bounds, BoundType.dft, 6):
            obound.append(BoundType.dft)
        elif b in ('nocheck', BoundType.nocheck, -1):
            obound.append(BoundType.nocheck)
        else:
            raise ValueError(f'Unknown boundary condition {b}')
    if issubclass(intype, (list, tuple)):
        obound = intype(obound)
    else:
        obound = obound[0]
    return obound

to_int

to_int(bound)

Convert boundary type to enum integer.

PARAMETER DESCRIPTION
bound

Boundary condition in any convention

TYPE: SequenceOrScalar[BoundLike]

RETURNS DESCRIPTION
bound

Boundary condition

TYPE: SequenceOrScalar[{0..6}]

Source code in bounds/types.py
def to_int(bound: SequenceOrScalar[BoundLike]) -> SequenceOrScalar[int]:
    """Convert boundary type to enum integer.

    !!! note "See also"
        * [`to_enum`][bounds.types.to_enum]
        * [`to_fourier`][bounds.types.to_fourier]
        * [`to_scipy`][bounds.types.to_scipy]
        * [`to_torch`][bounds.types.to_torch]

    Parameters
    ----------
    bound : SequenceOrScalar[BoundLike]
        Boundary condition in any convention

    Returns
    -------
    bound : SequenceOrScalar[{0..6}]
        Boundary condition

    """
    bound = to_enum(bound)
    if isinstance(bound, (list, tuple)):
        bound = type(bound)(map(lambda x: x.value, bound))
    else:
        bound = bound.value
    return bound

to_fourier

to_fourier(bound)

Convert boundary type to discrete transforms.

PARAMETER DESCRIPTION
bound

Boundary condition in any convention

TYPE: SequenceOrScalar[BoundLike]

RETURNS DESCRIPTION
bound

Boundary condition in terms of discrete transforms

TYPE: SequenceOrScalar[{replicate, zero, dct2, dct1, dst2, dst1, dft}]

Source code in bounds/types.py
def to_fourier(bound: SequenceOrScalar[BoundLike]) -> SequenceOrScalar[str]:
    """Convert boundary type to discrete transforms.

    !!! note "See also"
        * [`to_enum`][bounds.types.to_enum]
        * [`to_scipy`][bounds.types.to_scipy]
        * [`to_torch`][bounds.types.to_torch]
        * [`to_int`][bounds.types.to_int]

    Parameters
    ----------
    bound : SequenceOrScalar[BoundLike]
        Boundary condition in any convention

    Returns
    -------
    bound : SequenceOrScalar[{'replicate', 'zero', 'dct2', 'dct1', 'dst2', 'dst1', 'dft'}]
        Boundary condition in terms of discrete transforms

    """  # noqa: E501
    intype = type(bound)
    if not isinstance(bound, (list, tuple)):
        bound = [bound]
    obound = []
    for b in bound:
        if isinstance(b, str):
            b = b.lower()
        if b in (*zero_bounds, BoundType.zero, 0):
            obound.append('zero')
        elif b in (*rept_bounds, BoundType.border, 1):
            obound.append('replicate')
        elif b in (*dct1_bounds, BoundType.dct1, 2):
            obound.append('dct1')
        elif b in (*dct2_bounds, BoundType.dct2, 3):
            obound.append('dct2')
        elif b in (*dst1_bounds, BoundType.dst1, 4):
            obound.append('dst1')
        elif b in (*dst2_bounds, BoundType.dst2, 5):
            obound.append('dst2')
        elif b in (*dft_bounds, BoundType.dft, 6):
            obound.append('dft')
        elif b in ('nocheck', BoundType.nocheck, -1):
            obound.append('nocheck')
        else:
            raise ValueError(f'Unknown boundary condition {b}')
    if issubclass(intype, (list, tuple)):
        obound = intype(obound)
    else:
        obound = obound[0]
    return obound

to_scipy

to_scipy(bound)

Convert boundary type to SciPy's convention.

PARAMETER DESCRIPTION
bound

Boundary condition in any convention

TYPE: SequenceOrScalar[BoundLike]

RETURNS DESCRIPTION
bound

Boundary condition in SciPy's convention

TYPE: SequenceOrScalar[{border, constant, reflect, mirror, wrap}]

Source code in bounds/types.py
def to_scipy(bound: SequenceOrScalar[BoundLike]) -> SequenceOrScalar[str]:
    """Convert boundary type to SciPy's convention.

    !!! note "See also"
        * [`to_enum`][bounds.types.to_enum]
        * [`to_fourier`][bounds.types.to_fourier]
        * [`to_torch`][bounds.types.to_torch]
        * [`to_int`][bounds.types.to_int]

    Parameters
    ----------
    bound : SequenceOrScalar[BoundLike]
        Boundary condition in any convention

    Returns
    -------
    bound : SequenceOrScalar[{'border', 'constant', 'reflect', 'mirror', 'wrap'}]
        Boundary condition in SciPy's convention

    """  # noqa: E501
    intype = type(bound)
    if not isinstance(bound, (list, tuple)):
        bound = [bound]
    obound = []
    for b in bound:
        if isinstance(b, str):
            b = b.lower()
        if b in (*zero_bounds, BoundType.zero, 0):
            obound.append('constant')
        elif b in (*rept_bounds, BoundType.border, 1):
            obound.append('border')
        elif b in (*dct1_bounds, BoundType.dct1, 2):
            obound.append('mirror')
        elif b in (*dct2_bounds, BoundType.dct2, 3):
            obound.append('reflect')
        elif b in (*dst1_bounds, BoundType.dst1, 4):
            raise ValueError(f'Boundary condition {b} not available in SciPy.')
        elif b in (*dst2_bounds, BoundType.dst2, 5):
            raise ValueError(f'Boundary condition {b} not available in SciPy.')
        elif b in (*dft_bounds, BoundType.dft, 6):
            obound.append('wrap')
        elif b in ('nocheck', BoundType.nocheck, -1):
            raise ValueError(f'Boundary condition {b} not available in SciPy.')
        else:
            raise ValueError(f'Unknown boundary condition {b}')
    if issubclass(intype, (list, tuple)):
        obound = intype(obound)
    else:
        obound = obound[0]
    return obound

to_torch

to_torch(bound)

Convert boundary type to PyTorch's convention.

PARAMETER DESCRIPTION
bound

Boundary condition in any convention

TYPE: SequenceOrScalar[BoundLike]

RETURNS DESCRIPTION
bound

The first element is the boundary condition in PyTorchs's convention, and the second element is the value of align_corners.

TYPE: SequenceOrScalar[{nearest, zero, reflection}, bool]

Source code in bounds/types.py
def to_torch(bound: SequenceOrScalar[BoundLike]) -> SequenceOrScalar[str]:
    """Convert boundary type to PyTorch's convention.

    !!! note "See also"
        * [`to_enum`][bounds.types.to_enum]
        * [`to_fourier`][bounds.types.to_fourier]
        * [`to_scipy`][bounds.types.to_scipy]
        * [`to_int`][bounds.types.to_int]

    Parameters
    ----------
    bound : SequenceOrScalar[BoundLike]
        Boundary condition in any convention

    Returns
    -------
    bound : SequenceOrScalar[({'nearest', 'zero', 'reflection'}, bool)]
        The first element is the boundary condition in PyTorchs's
        convention, and the second element is the value of `align_corners`.

    """
    intype = type(bound)
    if not isinstance(bound, (list, tuple)):
        bound = [bound]
    obound = []
    for b in bound:
        if isinstance(b, str):
            b = b.lower()
        if b in (*zero_bounds, BoundType.zero, 0):
            obound.append(('zero', None))
        elif b in (*rept_bounds, BoundType.border, 1):
            obound.append(('nearest', None))
        elif b in (*dct1_bounds, BoundType.dct1, 2):
            obound.append(('reflection', False))
        elif b in (*dct2_bounds, BoundType.dct2, 3):
            obound.append(('reflection', True))
        elif b in (*dst1_bounds, BoundType.dst1, 4):
            raise ValueError(f'Boundary condition {b} not available in Torch.')
        elif b in (*dst2_bounds, BoundType.dst2, 5):
            raise ValueError(f'Boundary condition {b} not available in Torch.')
        elif b in (*dft_bounds, BoundType.dft, 6):
            raise ValueError(f'Boundary condition {b} not available in Torch.')
        elif b in ('nocheck', BoundType.nocheck, -1):
            raise ValueError(f'Boundary condition {b} not available in Torch.')
        else:
            raise ValueError(f'Unknown boundary condition {b}')
    if issubclass(intype, (list, tuple)):
        obound = intype(obound)
    else:
        obound = obound[0]
    return obound

dct

dct(x, dim=-1, norm='backward', type=2)

Return the Discrete Cosine Transform

Type IV not implemented

PARAMETER DESCRIPTION
x

The input tensor

TYPE: tensor

dim

Dimensions over which the DCT is computed. Default is the last one.

TYPE: int DEFAULT: -1

norm

Normalization mode. Default is "backward".

TYPE: (backward, ortho, forward) DEFAULT: "backward"

type

Type of the DCT. Default type is 2.

TYPE: int DEFAULT: 2

RETURNS DESCRIPTION
y

The transformed tensor.

TYPE: tensor

Source code in bounds/realtransforms.py
def dct(
    x: Tensor,
    dim: int = -1,
    norm: str = 'backward',
    type: int = 2,
) -> Tensor:
    """Return the Discrete Cosine Transform

    !!! warning "Type IV not implemented"

    Parameters
    ----------
    x : tensor
        The input tensor
    dim : int
        Dimensions over which the DCT is computed.
        Default is the last one.
    norm : {"backward", "ortho", "forward"}
        Normalization mode. Default is "backward".
    type: {1, 2, 3, 4}
        Type of the DCT. Default type is 2.

    Returns
    -------
    y : tensor
        The transformed tensor.

    """
    if dim is None:
        dim = -1
    if type in _IMPLEMENTED_TYPES:
        return DCTN.apply(x, type, dim, norm)
    else:
        raise ValueError('DCT only implemented for types I-IV')

idct

idct(x, dim=-1, norm='backward', type=2)

Return the Inverse Discrete Cosine Transform

Warning

Type IV not implemented

PARAMETER DESCRIPTION
x

The input tensor

TYPE: tensor

dim

Dimensions over which the DCT is computed. Default is the last one.

TYPE: int DEFAULT: -1

norm

Normalization mode. Default is "backward".

TYPE: (backward, ortho, forward) DEFAULT: "backward"

type

Type of the DCT. Default type is 2.

TYPE: int DEFAULT: 2

RETURNS DESCRIPTION
y

The transformed tensor.

TYPE: tensor

Source code in bounds/realtransforms.py
def idct(
    x: Tensor,
    dim: int = -1,
    norm: str = 'backward',
    type: int = 2,
) -> Tensor:
    """Return the Inverse Discrete Cosine Transform

    !!! warning
        Type IV not implemented

    Parameters
    ----------
    x : tensor
        The input tensor
    dim : int
        Dimensions over which the DCT is computed.
        Default is the last one.
    norm : {"backward", "ortho", "forward"}
        Normalization mode. Default is "backward".
    type: {1, 2, 3, 4}
        Type of the DCT. Default type is 2.

    Returns
    -------
    y : tensor
        The transformed tensor.

    """
    if dim is None:
        dim = -1
    norm = flipnorm[norm or "backward"]
    type = fliptype[type]
    return dct(x, dim, norm, type)

dst

dst(x, dim=-1, norm='backward', type=2)

Return the Discrete Sine Transform

Type IV not implemented

Warning

dst(..., norm="ortho") yields a different result than scipy and cupy for types 2 and 3. This is because their DST is not properly orthogonalized. Use norm="ortho_scipy" to get results matching their implementation.

PARAMETER DESCRIPTION
x

The input tensor

TYPE: tensor

dim

Dimensions over which the DCT is computed. Default is the last one.

TYPE: int DEFAULT: -1

norm

Normalization mode. Default is "backward".

TYPE: (backward, ortho, forward, ortho_scipy) DEFAULT: "backward"

type

Type of the DCT. Default type is 2.

TYPE: int DEFAULT: 2

RETURNS DESCRIPTION
y

The transformed tensor.

TYPE: tensor

Source code in bounds/realtransforms.py
def dst(
    x: Tensor,
    dim: int = -1,
    norm: str = 'backward',
    type: int = 2,
) -> Tensor:
    """Return the Discrete Sine Transform

    !!! warning "Type IV not implemented"

    !!! warning
        `dst(..., norm="ortho")` yields a different result than `scipy`
        and `cupy` for types 2 and 3. This is because their DST is not
        properly orthogonalized. Use `norm="ortho_scipy"` to get results
        matching their implementation.

    Parameters
    ----------
    x : tensor
        The input tensor
    dim : int
        Dimensions over which the DCT is computed.
        Default is the last one.
    norm : {"backward", "ortho", "forward", "ortho_scipy"}
        Normalization mode. Default is "backward".
    type: {1, 2, 3, 4}
        Type of the DCT. Default type is 2.

    Returns
    -------
    y : tensor
        The transformed tensor.

    """
    if dim is None:
        dim = -1
    if type in _IMPLEMENTED_TYPES:
        return DSTN.apply(x, type, dim, norm)
    else:
        raise ValueError('DST only implemented for types I-IV')

idst

idst(x, dim=-1, norm='backward', type=2)

Return the Inverse Discrete Sine Transform

Type IV not implemented

Warning

idst(..., norm="ortho") yields a different result than scipy and cupy for types 2 and 3. This is because their DST is not properly orthogonalized. Use norm="ortho_scipy" to get results matching their implementation.

PARAMETER DESCRIPTION
x

The input tensor

TYPE: tensor

dim

Dimensions over which the DCT is computed. Default is the last one.

TYPE: int DEFAULT: -1

norm

Normalization mode. Default is "backward".

TYPE: (backward, ortho, forward, ortho_scipy) DEFAULT: "backward"

type

Type of the DCT. Default type is 2.

TYPE: int DEFAULT: 2

RETURNS DESCRIPTION
y

The transformed tensor.

TYPE: tensor

Source code in bounds/realtransforms.py
def idst(
    x: Tensor,
    dim: int = -1,
    norm: str = 'backward',
    type: int = 2,
) -> Tensor:
    """Return the Inverse Discrete Sine Transform

    !!! warning "Type IV not implemented"

    !!! warning
        `idst(..., norm="ortho")` yields a different result than `scipy`
        and `cupy` for types 2 and 3. This is because their DST is not
        properly orthogonalized. Use `norm="ortho_scipy"` to get results
        matching their implementation.

    Parameters
    ----------
    x : tensor
        The input tensor
    dim : int
        Dimensions over which the DCT is computed.
        Default is the last one.
    norm : {"backward", "ortho", "forward", "ortho_scipy"}
        Normalization mode. Default is "backward".
    type: {1, 2, 3, 4}
        Type of the DCT. Default type is 2.

    Returns
    -------
    y : tensor
        The transformed tensor.

    """
    if dim is None:
        dim = -1
    norm = flipnorm[norm or "backward"]
    type = fliptype[type]
    return dst(x, dim, norm, type)

dctn

dctn(x, dim=None, norm='backward', type=2)

Return multidimensional Discrete Cosine Transform along the specified axes.

Type IV not implemented

PARAMETER DESCRIPTION
x

The input tensor

TYPE: tensor

dim

Dimensions over which the DCT is computed. If not given, all dimensions are used.

TYPE: [sequence of] int DEFAULT: None

norm

Normalization mode. Default is "backward".

TYPE: (backward, ortho, forward) DEFAULT: "backward"

type

Type of the DCT. Default type is 2.

TYPE: int DEFAULT: 2

RETURNS DESCRIPTION
y

The transformed tensor.

TYPE: tensor

Source code in bounds/realtransforms.py
def dctn(
    x: Tensor,
    dim: Optional[int] = None,
    norm: str = 'backward',
    type: int = 2,
) -> Tensor:
    """Return multidimensional Discrete Cosine Transform
    along the specified axes.

    !!! warning "Type IV not implemented"

    Parameters
    ----------
    x : tensor
        The input tensor
    dim : [sequence of] int
        Dimensions over which the DCT is computed.
        If not given, all dimensions are used.
    norm : {"backward", "ortho", "forward"}
        Normalization mode. Default is "backward".
    type: {1, 2, 3, 4}
        Type of the DCT. Default type is 2.

    Returns
    -------
    y : tensor
        The transformed tensor.

    """
    if dim is None:
        dim = list(range(x.ndim))
    if type in _IMPLEMENTED_TYPES:
        return DCTN.apply(x, type, dim, norm)
    else:
        raise ValueError('DCT only implemented for types I-IV')

idctn

idctn(x, dim=None, norm='backward', type=2)

Return multidimensional Inverse Discrete Cosine Transform along the specified axes.

Type IV not implemented

PARAMETER DESCRIPTION
x

The input tensor

TYPE: tensor

dim

Dimensions over which the DCT is computed. If not given, all dimensions are used.

TYPE: [sequence of] int DEFAULT: None

norm

Normalization mode. Default is "backward".

TYPE: (backward, ortho, forward) DEFAULT: "backward"

type

Type of the DCT. Default type is 2.

TYPE: int DEFAULT: 2

RETURNS DESCRIPTION
y

The transformed tensor.

TYPE: tensor

Source code in bounds/realtransforms.py
def idctn(
    x: Tensor,
    dim: Optional[int] = None,
    norm: str = 'backward',
    type: int = 2,
) -> Tensor:
    """Return multidimensional Inverse Discrete Cosine Transform
    along the specified axes.

    !!! warning "Type IV not implemented"

    Parameters
    ----------
    x : tensor
        The input tensor
    dim : [sequence of] int
        Dimensions over which the DCT is computed.
        If not given, all dimensions are used.
    norm : {"backward", "ortho", "forward"}
        Normalization mode. Default is "backward".
    type: {1, 2, 3, 4}
        Type of the DCT. Default type is 2.

    Returns
    -------
    y : tensor
        The transformed tensor.

    """
    if dim is None:
        dim = list(range(x.ndim))
    norm = flipnorm[norm or "backward"]
    type = fliptype[type]
    return dctn(x, dim, norm, type)

dstn

dstn(x, dim=None, norm='backward', type=2)

Return multidimensional Discrete Sine Transform along the specified axes.

Type IV not implemented

Warning

dstn(..., norm="ortho") yields a different result than scipy and cupy for types 2 and 3. This is because their DST is not properly orthogonalized. Use norm="ortho_scipy" to get results matching their implementation.

PARAMETER DESCRIPTION
x

The input tensor

TYPE: tensor

dim

Dimensions over which the DCT is computed. If not given, all dimensions are used.

TYPE: [sequence of] int DEFAULT: None

norm

Normalization mode. Default is "backward".

TYPE: (backward, ortho, forward, ortho_scipy) DEFAULT: "backward"

type

Type of the DCT. Default type is 2.

TYPE: int DEFAULT: 2

RETURNS DESCRIPTION
y

The transformed tensor.

TYPE: tensor

Source code in bounds/realtransforms.py
def dstn(
    x: Tensor,
    dim: Optional[int] = None,
    norm: str = 'backward',
    type: int = 2,
) -> Tensor:
    """Return multidimensional Discrete Sine Transform
    along the specified axes.

    !!! warning "Type IV not implemented"

    !!! warning
        `dstn(..., norm="ortho")` yields a different result than `scipy`
        and `cupy` for types 2 and 3. This is because their DST is not
        properly orthogonalized. Use `norm="ortho_scipy"` to get results
        matching their implementation.

    Parameters
    ----------
    x : tensor
        The input tensor
    dim : [sequence of] int
        Dimensions over which the DCT is computed.
        If not given, all dimensions are used.
    norm : {"backward", "ortho", "forward", "ortho_scipy"}
        Normalization mode. Default is "backward".
    type: {1, 2, 3, 4}
        Type of the DCT. Default type is 2.

    Returns
    -------
    y : tensor
        The transformed tensor.

    """
    if dim is None:
        dim = list(range(x.ndim))
    if type in _IMPLEMENTED_TYPES:
        return DSTN.apply(x, type, dim, norm)
    else:
        raise ValueError('DST only implemented for types I-IV')

idstn

idstn(x, dim=None, norm='backward', type=2)

Return multidimensional Inverse Discrete Sine Transform along the specified axes.

Type IV not implemented

Warning

idstn(..., norm="ortho") yields a different result than scipy and cupy for types 2 and 3. This is because their DST is not properly orthogonalized. Use norm="ortho_scipy" to get results matching their implementation.

PARAMETER DESCRIPTION
x

The input tensor

TYPE: tensor

dim

Dimensions over which the DCT is computed. If not given, all dimensions are used.

TYPE: [sequence of] int DEFAULT: None

norm

Normalization mode. Default is "backward".

TYPE: "backward", "ortho", "forward", "ortho_scipy DEFAULT: "backward"

type

Type of the DCT. Default type is 2.

TYPE: int DEFAULT: 2

RETURNS DESCRIPTION
y

The transformed tensor.

TYPE: tensor

Source code in bounds/realtransforms.py
def idstn(
    x: Tensor,
    dim: Optional[int] = None,
    norm: str = 'backward',
    type: int = 2,
) -> Tensor:
    """Return multidimensional Inverse Discrete Sine Transform
    along the specified axes.

    !!! warning "Type IV not implemented"

    !!! warning
        `idstn(..., norm="ortho")` yields a different result than `scipy`
        and `cupy` for types 2 and 3. This is because their DST is not
        properly orthogonalized. Use `norm="ortho_scipy"` to get results
        matching their implementation.

    Parameters
    ----------
    x : tensor
        The input tensor
    dim : [sequence of] int
        Dimensions over which the DCT is computed.
        If not given, all dimensions are used.
    norm : {"backward", "ortho", "forward", "ortho_scipy}
        Normalization mode. Default is "backward".
    type: {1, 2, 3, 4}
        Type of the DCT. Default type is 2.

    Returns
    -------
    y : tensor
        The transformed tensor.

    """
    if dim is None:
        dim = list(range(x.ndim))
    norm = flipnorm[norm or "backward"]
    type = fliptype[type]
    return dstn(x, dim, norm, type)