# -*- coding: utf-8 -*-
# Copyright (C) 2026 by SCICO Developers
# All rights reserved. BSD 3-clause License.
# This file is part of the SCICO package. Details of the copyright and
# user license can be found in the 'LICENSE' file distributed with the
# package.
"""Plotting/visualization functions.
Optional alternative high-level interface to selected :mod:`matplotlib`
plotting functions.
"""
import warnings
try:
import komplot as kplt
have_komplot = True
except:
have_komplot = False
try:
import matplotlib.pyplot as plt
from matplotlib.pyplot import figure, gca, gcf, savefig, subplot, subplots # noqa
from mpl_toolkits.mplot3d import Axes3D # noqa
have_matplotlib = True
except:
have_matplotlib = False
__all__ = [
"plot",
"surf",
"contour",
"imview",
"close",
"set_ipython_plot_backend",
"set_notebook_plot_backend",
"config_notebook_plotting",
]
[docs]
def plot(y, x=None, ptyp="plot", xlbl=None, ylbl=None, title=None, lgnd=None, lglc=None, **kwargs):
"""Plot points or lines in 2D.
Plot points or lines in 2D. If a figure object is specified then the
plot is drawn in that figure, and `fig.show()` is not called. The
figure is closed on key entry 'q'.
Args:
y (array_like): 1d or 2d array of data to plot. If a 2d array,
each column is plotted as a separate curve.
x (array_like, optional (default ``None``)): Values for x-axis of
the plot.
ptyp (string, optional (default 'plot')): Plot type specification
(options are 'plot', 'semilogx', 'semilogy', and 'loglog').
xlbl (string, optional (default ``None``)): Label for x-axis.
ylbl (string, optional (default ``None``)): Label for y-axis.
title (string, optional (default ``None``)): Figure title.
lgnd (list of strings, optional (default ``None``)): List of
legend string.
lglc (string, optional (default ``None``)): Legend location string.
**kwargs: :class:`matplotlib.lines.Line2D` properties or figure
properties.
Keyword arguments specifying :class:`matplotlib.lines.Line2D`
properties, e.g. `lw=2.0` sets a line width of 2, or
properties of the figure and axes. If not specified, the
defaults for line width (`lw`) and marker size (`ms`) are
1.5 and 6.0 respectively. The valid figure and axes keyword
arguments are listed below:
.. |mplfg| replace:: :class:`matplotlib.figure.Figure` object
.. |mplax| replace:: :class:`matplotlib.axes.Axes` object
.. rst-class:: kwargs
===== ==================== ===================================
kwarg Accepts Description
===== ==================== ===================================
fgsz tuple (width,height) Specify figure dimensions in inches
fgnm integer Figure number of figure
fig |mplfg| Draw in specified figure instead of
creating one
ax |mplax| Plot in specified axes instead of
current axes of figure
===== ==================== ===================================
Returns:
- **fig** (:class:`matplotlib.figure.Figure` object):
Figure object for this figure.
- **ax** (:class:`matplotlib.axes.Axes` object):
Axes object for this plot.
"""
warnings.warn(
"The scico.plot submodule is deprecated; use the corresponding "
"functions in the komplot package",
DeprecationWarning,
stacklevel=2,
)
if not have_komplot:
raise RuntimeError("Package komplot is required for use of this function.")
ptyp_options = {
"plot": (False, False),
"semilogx": (True, False),
"semilogy": (False, True),
"loglog": (True, True),
}
xlog, ylog = ptyp_options[ptyp]
fgsz = kwargs.pop("fgsz", None)
fgnm = kwargs.pop("fgnm", None)
fig = kwargs.pop("fig", None)
ax = kwargs.pop("ax", None)
if x is None:
lplt = kplt.plot(
y,
xlog=xlog,
ylog=ylog,
xlabel=xlbl,
ylabel=ylbl,
title=title,
legend=lgnd,
legend_loc=lglc,
figsize=fgsz,
fignum=fgnm,
ax=ax,
**kwargs,
)
else:
lplt = kplt.plot(
x,
y,
xlog=xlog,
ylog=ylog,
xlabel=xlbl,
ylabel=ylbl,
title=title,
legend=lgnd,
legend_loc=lglc,
figsize=fgsz,
fignum=fgnm,
ax=ax,
**kwargs,
)
return lplt.figure, lplt.axes
[docs]
def surf(
z,
x=None,
y=None,
elev=None,
azim=None,
xlbl=None,
ylbl=None,
zlbl=None,
title=None,
lblpad=8.0,
alpha=1.0,
cntr=None,
cmap=None,
fgsz=None,
fgnm=None,
fig=None,
ax=None,
):
"""Plot a 2D surface in 3D.
Plot a 2D surface in 3D. If a figure object is specified then the
surface is drawn in that figure, and `fig.show()` is not called.
The figure is closed on key entry 'q'.
Args:
z (array_like): 2d array of data to plot.
x (array_like, optional (default ``None``)): Values for x-axis of
the plot.
y (array_like, optional (default ``None``)): Values for y-axis of
the plot.
elev (float): Elevation angle (in degrees) in the z plane.
azim (float): Azimuth angle (in degrees) in the x,y plane.
xlbl (string, optional (default ``None``)): Label for x-axis.
ylbl (string, optional (default ``None``)): Label for y-axis.
zlbl (string, optional (default ``None``)): Label for z-axis.
title (string, optional (default ``None``)): Figure title.
lblpad (float, optional (default 8.0)): Label padding.
alpha (float between 0.0 and 1.0, optional (default 1.0)):
Transparency.
cntr (int or sequence of ints, optional (default ``None``)): If
not ``None``, plot contours of the surface on the lower end
of the z-axis. An int specifies the number of contours to
plot, and a sequence specifies the specific contour levels to
plot.
cmap (:class:`matplotlib.colors.Colormap` object, optional (default ``None``)):
Color map for surface. If none specifed, defaults to `cm.YlOrRd`.
fgsz (tuple (width,height), optional (default ``None``)): Specify
figure dimensions in inches.
fgnm (integer, optional (default ``None``)): Figure number of figure.
fig (:class:`matplotlib.figure.Figure` object, optional (default ``None``)):
Draw in specified figure instead of creating one.
ax (:class:`matplotlib.axes.Axes` object, optional (default ``None``)):
Plot in specified axes instead of creating one.
Returns:
- **fig** (:class:`matplotlib.figure.Figure` object):
Figure object for this figure.
- **ax** (:class:`matplotlib.axes.Axes` object):
Axes object for this plot.
"""
warnings.warn(
"The scico.plot submodule is deprecated; use the corresponding "
"functions in the komplot package",
DeprecationWarning,
stacklevel=2,
)
if not have_komplot:
raise RuntimeError("Package komplot is required for use of this function.")
splt = kplt.surface(
z,
x=x,
y=y,
elev=elev,
azim=azim,
alpha=alpha,
cmap=cmap,
levels=cntr,
xlabel=xlbl,
ylabel=ylbl,
zlabel=zlbl,
labelpad=lblpad,
title=title,
figsize=fgsz,
fignum=fgnm,
ax=ax,
)
return splt.figure, splt.axes
[docs]
def contour(
z,
x=None,
y=None,
v=5,
xlog=False,
ylog=False,
xlbl=None,
ylbl=None,
title=None,
cfmt=None,
cfntsz=10,
lfntsz=None,
alpha=1.0,
cmap=None,
vmin=None,
vmax=None,
fgsz=None,
fgnm=None,
fig=None,
ax=None,
):
"""Contour plot of a 2D surface.
Contour plot of a 2D surface. If a figure object is specified then
the plot is drawn in that figure, and `fig.show()` is not called.
The figure is closed on key entry 'q'.
Args:
z (array_like): 2d array of data to plot.
x (array_like, optional (default ``None``)): Values for x-axis of
the plot.
y (array_like, optional (default ``None``)): Values for y-axis of
the plot.
v (int or sequence of floats, optional (default 5)): An int
specifies the number of contours to plot, and a sequence
specifies the specific contour levels to plot.
xlog (boolean, optional (default ``False``)): Set x-axis to log
scale.
ylog (boolean, optional (default ``False``)): Set y-axis to log
scale.
xlbl (string, optional (default ``None``)): Label for x-axis.
ylbl (string, optional (default ``None``)): Label for y-axis.
title (string, optional (default ``None``)): Figure title.
cfmt (string, optional (default ``None``)): Format string for
contour labels.
cfntsz (int or ``None``, optional (default 10)): Contour label
font size. No contour labels are displayed if set to 0 or
``None``.
lfntsz (int, optional (default ``None``)): Axis label font size.
The default font size is used if set to ``None``.
alpha (float, optional (default 1.0)): Underlying image display
alpha value.
cmap (:class:`matplotlib.colors.Colormap`, optional (default ``None``)):
Color map for surface. If none specifed, defaults to `cm.YlOrRd`.
vmin, vmax (float, optional (default ``None``)): Set upper and
lower bounds for the color map (see the corresponding
parameters of :meth:`matplotlib.axes.Axes.imshow`).
fgsz (tuple (width,height), optional (default ``None``)): Specify
figure dimensions in inches.
fgnm (integer, optional (default ``None``)): Figure number of figure.
fig (:class:`matplotlib.figure.Figure` object, optional (default ``None``)):
Draw in specified figure instead of creating one.
ax (:class:`matplotlib.axes.Axes` object, optional (default ``None``)):
Plot in specified axes instead of current axes of figure.
Returns:
- **fig** (:class:`matplotlib.figure.Figure` object):
Figure object for this figure.
- **ax** (:class:`matplotlib.axes.Axes` object):
Axes object for this plot.
"""
warnings.warn(
"The scico.plot submodule is deprecated; use the corresponding "
"functions in the komplot package",
DeprecationWarning,
stacklevel=2,
)
if not have_komplot:
raise RuntimeError("Package komplot is required for use of this function.")
cplt = kplt.contour(
z,
x=x,
y=y,
xlog=xlog,
ylog=ylog,
levels=v,
clabel_format=cfmt,
clabel_fontsize=cfntsz,
cmap=cmap,
vmin=vmin,
vmax=vmax,
alpha=alpha,
xlabel=xlbl,
ylabel=ylbl,
xylabel_fontsize=lfntsz,
title=title,
figsize=fgsz,
fignum=fgnm,
ax=ax,
)
return cplt.figure, cplt.axes
[docs]
def imview(
img,
title=None,
copy=True,
fltscl=False,
intrp="nearest",
norm=None,
cbar=False,
cmap=None,
fgsz=None,
fgnm=None,
fig=None,
ax=None,
):
"""Display an image.
Display an image. Pixel values are displayed when the pointer is over
valid image data. If a figure object is specified then the image is
drawn in that figure, and `fig.show()` is not called. The figure is
closed on key entry 'q'.
Args:
img (array_like, shape (Nr, Nc) or (Nr, Nc, 3) or (Nr, Nc, 4)):
Image to display.
title (string, optional (default ``None``)): Figure title.
copy (boolean, optional (default ``True``)): If ``True``, create
a copy of input `img` as a reference for displayed pixel
values, ensuring that displayed values do not change when the
array changes in the calling scope. Set this flag to
``False`` if the overhead of an additional copy of the input
image is not acceptable.
fltscl (boolean, optional (default ``False``)): If ``True``,
rescale and shift floating point arrays to [0,1].
intrp (string, optional (default 'nearest')): Specify type of
interpolation used to display image (see `interpolation`
parameter of :meth:`matplotlib.axes.Axes.imshow`).
norm (:class:`matplotlib.colors.Normalize` object, optional (default ``None``)):
Specify the :class:`matplotlib.colors.Normalize` instance used
to scale pixel values for input to the color map.
cbar (boolean, optional (default ``False``)): Flag indicating
whether to display colorbar.
cmap (:class:`matplotlib.colors.Colormap`, optional (default ``None``)):
Color map for image. If none specifed, defaults to
`cm.Greys_r` for monochrome image.
fgsz (tuple (width,height), optional (default ``None``)): Specify
figure dimensions in inches.
fgnm (integer, optional (default ``None``)): Figure number of
figure.
fig (:class:`matplotlib.figure.Figure` object, optional (default ``None``)):
Draw in specified figure instead of creating one.
ax (:class:`matplotlib.axes.Axes` object, optional (default ``None``)):
Plot in specified axes instead of current axes of figure.
Returns:
- **fig** (:class:`matplotlib.figure.Figure` object):
Figure object for this figure.
- **ax** (:class:`matplotlib.axes.Axes` object):
Axes object for this plot.
Raises:
ValueError: If the input array is not of the required shape.
"""
warnings.warn(
"The scico.plot submodule is deprecated; use the corresponding "
"functions in the komplot package",
DeprecationWarning,
stacklevel=2,
)
if not have_komplot:
raise RuntimeError("Package komplot is required for use of this function.")
imv = kplt.imview(
img,
interpolation=intrp,
norm=norm,
show_cbar=cbar,
cmap=cmap,
title=title,
figsize=fgsz,
fignum=fgnm,
ax=ax,
)
return imv.figure, imv.axes
[docs]
def close(fig=None):
"""Close figure(s).
Close figure(s). If a figure object reference or figure number is
provided, close the specified figure, otherwise close all figures.
Args:
fig (:class:`matplotlib.figure.Figure` object or integer (optional (default ``None``)):
Figure object or number of figure to close.
"""
warnings.warn(
"The scico.plot submodule is deprecated; use the corresponding "
"functions in the komplot package",
DeprecationWarning,
stacklevel=2,
)
if not have_matplotlib:
raise RuntimeError("Package matplotlib is required for use of this function.")
if fig is None:
plt.close("all")
else:
plt.close(fig)
def _in_ipython():
"""Determine whether code is running in an ipython shell.
Returns:
bool: ``True`` if running in an ipython shell, ``False``
otherwise.
"""
warnings.warn(
"The scico.plot submodule is deprecated; use the corresponding "
"functions in the komplot package",
DeprecationWarning,
stacklevel=2,
)
try:
# See https://stackoverflow.com/questions/15411967
shell = get_ipython().__class__.__name__
return bool(shell == "TerminalInteractiveShell")
except NameError:
return False
def _in_notebook():
"""Determine whether code is running in a Jupyter Notebook shell.
Returns:
bool: ``True`` if running in a notebook shell, ``False``
otherwise.
"""
warnings.warn(
"The scico.plot submodule is deprecated; use the corresponding "
"functions in the komplot package",
DeprecationWarning,
stacklevel=2,
)
try:
# See https://stackoverflow.com/questions/15411967
shell = get_ipython().__class__.__name__
return bool(shell == "ZMQInteractiveShell")
except NameError:
return False
[docs]
def set_ipython_plot_backend(backend="qt"):
"""Set matplotlib backend within an ipython shell.
Set matplotlib backend within an ipython shell. This function has the
same effect as the line magic `%matplotlib [backend]` but is called
as a function and includes a check to determine whether the code is
running in an ipython shell, so that it can safely be used within a
normal python script since it has no effect when not running in an
ipython shell.
Args:
backend (string, optional (default 'qt')): Name of backend to be
passed to the `%matplotlib` line magic command.
"""
warnings.warn(
"The scico.plot submodule is deprecated; use the corresponding "
"functions in the komplot package",
DeprecationWarning,
stacklevel=2,
)
if not have_matplotlib:
raise RuntimeError("Package matplotlib is required for use of this function.")
if _in_ipython():
# See https://stackoverflow.com/questions/35595766
get_ipython().run_line_magic("matplotlib", backend)
[docs]
def set_notebook_plot_backend(backend="inline"):
"""Set matplotlib backend within a Jupyter Notebook shell.
Set matplotlib backend within a Jupyter Notebook shell. This function
has the same effect as the line magic `%matplotlib [backend]` but
is called as a function and includes a check to determine whether the
code is running in a notebook shell, so that it can safely be used
within a normal python script since it has no effect when not running
in a notebook shell.
Args:
backend (string, optional (default 'inline')): Name of backend to
be passed to the `%matplotlib` line magic command.
"""
warnings.warn(
"The scico.plot submodule is deprecated; use the corresponding "
"functions in the komplot package",
DeprecationWarning,
stacklevel=2,
)
if not have_matplotlib:
raise RuntimeError("Package matplotlib is required for use of this function.")
if _in_notebook():
# See https://stackoverflow.com/questions/35595766
get_ipython().run_line_magic("matplotlib", backend)
[docs]
def config_notebook_plotting():
"""Configure plotting functions for inline plotting.
Configure plotting functions for inline plotting within a Jupyter
Notebook shell. This function has no effect when not within a
notebook shell, and may therefore be used within a normal python
script. If environment variable ``MATPLOTLIB_IPYNB_BACKEND`` is set,
the matplotlib backend is explicitly set to the specified value.
"""
warnings.warn(
"The scico.plot submodule is deprecated; use the corresponding "
"functions in the komplot package",
DeprecationWarning,
stacklevel=2,
)
if not have_komplot:
raise RuntimeError("Package komplot is required for use of this function.")
kplt.config_notebook_plotting()