API#
curvelops#
curvelops.curvelops#
Provides a LinearOperator for the 2D and 3D curvelet transforms.
- class curvelops.curvelops.FDCT(dims, axes, nbscales=None, nbangles_coarse=16, allcurvelets=True, dtype='complex128')[source]#
Bases:
LinearOperator2D/3D dimensional Curvelet operator. Apply 2D/3D Curvelet Transform along two
axesof a multi-dimensional array of sizedims.Parameters#
- dims
tuple Number of samples for each dimension.
- axes
tuple, optional Axes along which FDCT is applied.
- nbscales
int, optional Number of scales (including the coarsest level); Defaults to ceil(log2(min(input_dims)) - 3).
- nbangles_coarse
int, optional Number of angles at 2nd coarsest scale.
- allcurvelets
bool, optional Use curvelets at the finest (last) scale. If
False, a wavelet transform will be used for the finest scale. The coarsest scale is always a wavelet transform; the ones between the coarsest and the finest are all curvelet transforms. This option only affects the finest scale.- dtype
DTypeLike, optional dtypeof the transform.
- inverse(x)[source]#
Inverse Curvelet Transform
Parameters#
- xNDArray
Input vector
Returns#
- NDArray
FDCT.H @ x
- struct(x)[source]#
Convert curvelet flattened vector to curvelet structure.
The FDCT always returns a 1D vector that has all curvelet coefficients. These coefficients can be organized into scales, wedges and spatial positions. Applying this function to a 1D vector generates this structure.
Parameters#
- x
NDArray Input flattened vector.
Returns#
FDCTStructLikeCurvelet structure, a list of lists of multidimensional arrays. The first index corresponds to scale, the second corresponds to angular wedge.
- x
- vect(x)[source]#
Convert curvelet structure to curvelet flattened vector.
The FDCT always returns a 1D vector that has all curvelet coefficients. These coefficients can be organized into scales, wedges and spatial positions. Applying this function to a curvelet structure returns the flattened vector.
Parameters#
- x
FDCTStructLike Input curvelet structure.
Returns#
NDArrayFlattened vector.
- x
- dims
- class curvelops.curvelops.FDCT2D(dims, axes=(-2, -1), nbscales=None, nbangles_coarse=16, allcurvelets=True, dtype='complex128')[source]#
Bases:
FDCT2D dimensional Curvelet operator. Apply 2D Curvelet Transform along two
axesof a multi-dimensional array of sizedims.Parameters#
- dims
tuple Number of samples for each dimension.
- axes
tuple, optional Axes along which FDCT is applied.
- nbscales
int, optional Number of scales (including the coarsest level); Defaults to ceil(log2(min(input_dims)) - 3).
- nbangles_coarse
int, optional Number of angles at 2nd coarsest scale.
- allcurvelets
bool, optional Use curvelets at the finest (last) scale. If
False, a wavelet transform will be used for the finest scale. The coarsest scale is always a wavelet transform; the ones between the coarsest and the finest are all curvelet transforms. This option only affects the finest scale.- dtype
DTypeLike, optional dtypeof the transform.
- dims
- class curvelops.curvelops.FDCT3D(dims, axes=(-3, -2, -1), nbscales=None, nbangles_coarse=16, allcurvelets=True, dtype='complex128')[source]#
Bases:
FDCT3D dimensional Curvelet operator. Apply 3D Curvelet Transform along two
axesof a multi-dimensional array of sizedims.Parameters#
- dims
tuple Number of samples for each dimension.
- axes
tuple, optional Axes along which FDCT is applied.
- nbscales
int, optional Number of scales (including the coarsest level); Defaults to ceil(log2(min(input_dims)) - 3).
- nbangles_coarse
int, optional Number of angles at 2nd coarsest scale.
- allcurvelets
bool, optional Use curvelets at the finest (last) scale. If
False, a wavelet transform will be used for the finest scale. The coarsest scale is always a wavelet transform; the ones between the coarsest and the finest are all curvelet transforms. This option only affects the finest scale.- dtype
DTypeLike, optional dtypeof the transform.
- dims
plot#
curvelops.plot#
Auxiliary functions for plotting.
- curvelops.plot.create_axes_grid(rows, cols, kwargs_figure=None, kwargs_gridspec=None, kwargs_subplots=None)[source]#
Creates a grid of axes.
Parameters#
- rows
int Number of rows.
- cols
int Number of columns.
- kwargs_figure
Optional[dict], optional Arguments to be passed to
matplotlib.pyplot.figure.- kwargs_gridspec
Optional[dict], optional Arguments to be passed to
matplotlib.gridspec.GridSpec.- kwargs_subplots
Optional[dict], optional Arguments to be passed to
matplotlib.figure.Figure.add_subplot.
Returns#
Examples#
>>> from curvelops.plot import create_axes_grid >>> rows, cols = 2, 3 >>> fig, axs = create_axes_grid( >>> rows, >>> cols, >>> kwargs_figure=dict(figsize=(8, 8)), >>> kwargs_gridspec=dict(wspace=0.3, hspace=0.3), >>> ) >>> for irow in range(rows): >>> for icol in range(cols): >>> axs[irow][icol].plot(np.cos((2 + irow + icol**2) * np.linspace(0, 1))) >>> axs[irow][icol].set(title=f"Row, Col: ({irow}, {icol})")
- rows
- curvelops.plot.create_colorbar(im, ax, size=0.05, pad=0.1, orientation='vertical')[source]#
Create a colorbar.
Divides axis and attaches a colorbar to it.
Parameters#
- im
AxesImage Image from which the colorbar will be created. Commonly the output of
matplotlib.pyplot.imshow.- ax
Axes Axis which to split.
- size
float, optional Size of split, by default 0.05. Effectively sets the size of the colorbar.
- pad
float, optional` Padding between colorbar axis and input axis, by default 0.1.
- orientation
str, optional Orientation of the colorbar, by default “vertical”.
Returns#
Examples#
>>> import matplotlib.pyplot as plt >>> from matplotlib.ticker import MultipleLocator >>> from curvelops.plot import create_colorbar >>> fig, ax = plt.subplots() >>> im = ax.imshow([[0]], vmin=-1, vmax=1, cmap="gray") >>> cax, cb = create_colorbar(im, ax) >>> cax.yaxis.set_major_locator(MultipleLocator(0.1)) >>> print(cb.vmin) -1.0
- im
- curvelops.plot.create_inset_axes_grid(ax, rows, cols, height=0.5, width=0.5, kwargs_inset_axes=None)[source]#
Create a grid of insets.
The input axis will be overlaid with a grid of insets. Numbering of the axes is top to bottom (rows) and left to right (cols).
Parameters#
- ax
Axes Input axis.
- rows
int Number of rows.
- cols
int Number of columns.
- width
float, optional Width of each axis, as a percentage of
cols, by default 0.5.- height
float, optional Height of each axis, as a percentage of
rows, by default 0.5.- kwargs_inset_axes
Optional[dict], optional Arguments to be passed to
matplotlib.axes.Axes.inset_axes.
Returns#
Examples#
>>> import matplotlib.pyplot as plt >>> import numpy as np >>> from curvelops.plot import create_inset_axes_grid >>> fig, ax = plt.subplots(figsize=(6, 6)) >>> ax.imshow([[0]], extent=[-2, 2, 2, -2], vmin=-1, vmax=1, cmap="gray") >>> rows, cols = 2, 3 >>> inset_axes = create_inset_axes_grid( >>> ax, >>> rows, >>> cols, >>> width=0.5, >>> height=0.5, >>> kwargs_inset_axes=dict(projection="polar"), >>> ) >>> nscales = 4 >>> lw = 0.1 >>> for irow in range(rows): >>> for icol in range(cols): >>> for iscale in range(1, nscales): >>> inset_axes[irow][icol].bar( >>> x=0, >>> height=lw, >>> width=2 * np.pi, >>> bottom=((iscale + 1) - 0.5 * lw) / (nscales - 1), >>> color="r", >>> ) >>> inset_axes[irow][icol].set(title=f"Row, Col: ({irow}, {icol})") >>> inset_axes[irow][icol].axis("off")
- ax
- curvelops.plot.curveshow(c_struct, k_space=False, basesize=5, showaxis=False, real=True, kwargs_imshow=None)[source]#
Display curvelet coefficients in each wedge as images.
For each curvelet scale, display a figure with each wedge plotted as an image in its own axis.
Parameters#
- c_struct
FDCTStructLike Curvelet structure.
- k_space
bool, optional Show curvelet coefficient (False) or its 2D FFT transform (True), by default False.
- basesize
int, optional Base fize of figure, by default 5. Each figure will be sized
(basesize * cols, basesize * rows), whererows = floor(sqrt(nangles))andcols = ceil(nangles / rows)- showaxis
bool, optional Turn on axis lines and labels, by default False.
- real
bool, optional Plot real or imaginary part of curvelet coefficients. Only applicable when
k_spaceis False.- kwargs_imshow
Optional[dict], optional Arguments to be passed to
matplotlib.pyplot.imshow.
Examples#
>>> import numpy as np >>> from curvelops import FDCT2D >>> from curvelops.utils import apply_along_wedges, energy >>> from curvelops.plot import curveshow >>> d = np.random.randn(101, 101) >>> C = FDCT2D(d.shape, nbscales=2, nbangles_coarse=8) >>> y = C.struct(C @ d) >>> y_norm = apply_along_wedges(y, lambda w, *_: w / energy(w)) >>> curveshow( >>> y_norm, >>> basesize=2, >>> kwargs_imshow=dict(aspect="auto", vmin=-1, vmax=1, cmap="RdBu") >>> )
Returns#
- List[
Figure] One figure per scale.
- c_struct
- curvelops.plot.overlay_arrows(vectors, ax, arrowprops=None)[source]#
Overlay arrows on an axis.
Parameters#
- vectors
NDArray Array shaped
(rows, cols, 2), corresponding to a 2D vector field.- ax
Axes Axis on which to overlay the arrows.
- arrowprops
Optional[dict], optional Arrow properties, to be passed to
matplotlib.pyplot.annotate. By default will be set todict(facecolor="black", shrink=0.05).
Examples#
>>> import matplotlib.pyplot as plt >>> import numpy as np >>> from curvelops.plot import overlay_arrows >>> fig, ax = plt.subplots(figsize=(8, 10)) >>> ax.imshow([[0]], vmin=-1, vmax=1, extent=[0, 1, 1, 0], cmap="gray") >>> rows, cols = 3, 4 >>> kvecs = np.array( >>> [ >>> [(1 + x, x * y) for x in (0.5 + np.arange(cols)) / cols] >>> for y in (0.5 + np.arange(rows)) / rows >>> ] >>> ) >>> overlay_arrows( >>> 0.05 * kvecs, >>> ax, >>> arrowprops=dict( >>> facecolor="r", >>> shrink=0.05, >>> width=10 / cols, >>> headwidth=10, >>> headlength=10, >>> ), >>> )
- vectors
- curvelops.plot.overlay_disks(c_struct, axes, linewidth=0.5, linecolor='r', map_cmap=True, cmap='gray_r', alpha=1.0, pclip=1.0, map_alpha=False, min_alpha=0.05, normalize='all', annotate=False)[source]#
Overlay curvelet disks over a 2D grid of axes.
Its intended usage is to display the strength of curvelet coefficients of a certain image with a disk display. Given an
axes2D array, each curvelet wedge will be split intorows, cols = axes.shapesub-wedges. The energy of each of these sub-wedges will be mapped to a colormap color and/or transparency.See Also#
energy_split: Splits a wedge into(rows, cols)wedges and computes the energy of each of these subdivisions.create_inset_axes_grid: Create a grid of insets.create_axes_grid: Creates a grid of axes.curveshow: Display curvelet coefficients in each wedge as images.Parameters#
- c_struct
FDCTStructLike: Curvelet coefficients of underlying image.
- axes
NDArray 2D grid of axes for which disks will be computed.
- linewidth
float, optional Width of line separating scales, by default 0.5. Will be scaled by
0.1 / nscalesinternally. Set to zero to disable.- linecolor
str, optional Color of line separating scales, by default “r”.
- map_cmap
bool, optional When enabled, energy will be mapped to the colormap, by default True.
- cmapUnion[
str,Colormap], optional Colormap, by default
"gray_r".- alpha
float, optional When using
map_cmap, sets a transparecy for all wedges. Has no effect whenmap_alphais enabled. By default 1.0.- pclip
float, optional Clips the maximum amplitude by this percentage. By default 1.0. Should be between 0.0 and 1.0.
- map_alpha
bool, optional When enabled, energy will be mapped to the transparency, by default False.
- min_alpha
float, optional When using
map_alpha, sets a minimum transparency value. Has no effect whenmap_alphais disabled. By default 0.05.- normalize
str, optional Normalize wedges by:
"all"(default)Colormap/alpha value of 1.0 will correspond to the maximum energy found across all wedges
"scale"Colormap/alpha value of 1.0 will correspond to the maximum energy found across all wedges in the same scale.
- annotate
bool, optional When true, will display in the middle of the wedge a pair of numbers
iscale, iwedge, the index of that scale and that wedge, both starting from zero. This option is useful to understand which directions each wedge corresponds to. By default False.
Examples#
>>> import matplotlib.pyplot as plt >>> import numpy as np >>> from curvelops import FDCT2D >>> from curvelops.utils import apply_along_wedges >>> from curvelops.plot import create_axes_grid, overlay_disks >>> x = np.random.randn(50, 100) >>> C = FDCT2D(x.shape, nbscales=4, nbangles_coarse=8) >>> y = C.struct(C @ x) >>> y_ones = apply_along_wedges(y, lambda w, *_: np.ones_like(w)) >>> fig, axes = create_axes_grid( >>> 1, >>> 1, >>> kwargs_subplots=dict(projection="polar"), >>> kwargs_figure=dict(figsize=(8, 8)), >>> ) >>> overlay_disks(y_ones, axes, annotate=True, cmap="gray")
>>> import matplotlib as mpl >>> import matplotlib.pyplot as plt >>> import numpy as np >>> from mpl_toolkits.axes_grid1 import make_axes_locatable >>> from curvelops import FDCT2D >>> from curvelops.plot import create_inset_axes_grid, overlay_disks >>> from curvelops.utils import apply_along_wedges >>> plt.rcParams.update({"image.interpolation": "blackman"}) >>> # Construct signal >>> xlim = [-1.0, 1.0] >>> ylim = [-0.5, 0.5] >>> x = np.linspace(*xlim, 201) >>> z = np.linspace(*ylim, 101) >>> xm, zm = np.meshgrid(x, z, indexing="ij") >>> freq = 5 >>> d = np.cos(2 * np.pi * freq * (xm + np.cos(xm) * zm) ** 3) >>> # Compute curvelet coefficients >>> C = FDCT2D(d.shape, nbangles_coarse=8, allcurvelets=False) >>> d_c = C.struct(C @ d) >>> # Plot original signal >>> fig, ax = plt.subplots(figsize=(8, 4 )) >>> ax.imshow(d.T, extent=[*xlim, *(ylim[::-1])], cmap="RdYlBu", vmin=-1, vmax=1) >>> ax.axis("off") >>> # Overlay disks >>> rows, cols = 3, 6 >>> axesin = create_inset_axes_grid( >>> ax, rows, cols, width=0.75, kwargs_inset_axes=dict(projection="polar") >>> ) >>> pclip = 0.2 >>> cmap = "gray_r" >>> overlay_disks(d_c, axesin, linewidth=0.0, pclip=pclip, cmap=cmap) >>> # Display disk colorbar >>> divider = make_axes_locatable(ax) >>> cax = divider.append_axes("right", size="5%", pad=0.1) >>> mpl.colorbar.ColorbarBase( >>> cax, cmap=cmap, norm=mpl.colors.Normalize(vmin=0, vmax=pclip) >>> )
- c_struct
typing#
curvelops.typing#
Typing submodule.
utils#
curvelops.utils#
Utility functions for processing curvelets.
- curvelops.utils.apply_along_wedges(c_struct, fun)[source]#
Applies a function to each individual wedge.
Parameters#
Returns#
- List[List[T]]
Struct containing the result of applying fun to each wedge.
Examples#
>>> import numpy as np >>> from curvelops import FDCT2D >>> from curvelops.utils import apply_along_wedges >>> x = np.zeros((32, 32)) >>> C = FDCT2D(x.shape, nbscales=3, nbangles_coarse=8, allcurvelets=False) >>> y = C.struct(C @ x) >>> apply_along_wedges(y, lambda w, *_: w.shape) [[(11, 11)], [(23, 11), (23, 11), (11, 23), (11, 23), (23, 11), (23, 11), (11, 23), (11, 23)], [(32, 32)]]
- curvelops.utils.array_split_nd(ary, *args)[source]#
Split an array into multiple sub-arrays recursively, possibly unevenly.
See Also#
numpy.array_split: Split an array into multiple sub-arrays.split_nd: Evenly split an array into multiple sub-arrays recursively.Parameters#
- ary
NDArray Input array.
- args
int, optional Number of splits for each axis of ary. Axis 0 will be split into args[0] subarrays, axis 1 will be into args[1] subarrays, etc. An axis of length l = ary.shape[axis] that should be split into n = args[axis] sections, will return l % n sub-arrays of size l//n + 1 and the rest of size l//n.
Returns#
RecursiveListNDArrayRecursive lists of lists of
NDArray. The number of recursions is equivalent to the number arguments in args.
Examples#
>>> from curvelops.utils import array_split_nd >>> ary = np.outer(1 + np.arange(2), 2 + np.arange(3)) array([[2, 3, 4], [4, 6, 8]]) >>> array_split_nd(ary, 2, 3) [[array([[2]]), array([[3]]), array([[4]])], [array([[4]]), array([[6]]), array([[8]])]]
>>> from curvelops.utils import array_split_nd >>> ary = np.outer(np.arange(3), np.arange(5)) >>> array_split_nd(ary, 2, 3) [[array([[0, 0], [0, 1]]), array([[0, 0], [2, 3]]), array([[0], [4]])], [array([[0, 2]]), array([[4, 6]]), array([[8]])]]
- ary
- curvelops.utils.energy(ary)[source]#
Computes the energy of an n-dimensional wedge.
The energy of a vector (flattened n-dimensional array) \((a_0,\ldots,a_{N-1})\) is defined as
\[\sqrt{\frac{1}{N}\sum\limits_{i=0}^{N-1} |a_i|^2}.\]Parameters#
- ary
NDArray Input wedge.
Returns#
floatEnergy.
- ary
- curvelops.utils.energy_split(ary, rows, cols)[source]#
Splits a wedge into
(rows, cols)wedges and computes the energy of each of these subdivisions.See Also#
energy: Computes the energy of a wedge.Parameters#
Returns#
NDArrayMatrix of shape
(rows, cols)containing the energy of each subdivision of the input wedge.
- curvelops.utils.ndargmax(ary)[source]#
N-dimensional argmax of array.
Parameters#
- ary
NDArray Input array
Examples#
>>> import numpy as np >>> from curvelops.utils import ndargmax >>> x = np.zeros((10, 10, 10)) >>> x[1, 1, 1] = 1.0 >>> ndargmax(x) (1, 1, 1)
Returns#
- tuple
N-dimensional index of the maximum of
ary.
- ary
- curvelops.utils.split_nd(ary, *args)[source]#
Evenly split an array into multiple sub-arrays recursively.
See Also#
numpy.split: Split an array into multiple sub-arrays.array_split_nd: Split an array into multiple sub-arrays recursively, possibly unevenly.Parameters#
Returns#
RecursiveListNDArrayRecursive lists of lists of
NDArray. The number of recursions is equivalent to the number arguments in args.
Examples#
>>> from curvelops.utils import split_nd >>> ary = np.outer(1 + np.arange(2), 2 + np.arange(3)) array([[2, 3, 4], [4, 6, 8]]) >>> split_nd(ary, 2, 3) [[array([[2]]), array([[3]]), array([[4]])], [array([[4]]), array([[6]]), array([[8]])]]
>>> from curvelops.utils import split_nd >>> ary = np.outer(np.arange(3), np.arange(5)) >>> split_nd(ary, 2, 3) ValueError: array split does not result in an equal division