Source code for huracanpy.plot._fancyline

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
from matplotlib.patheffects import Stroke
from cartopy.crs import Geodetic
from cartopy.mpl.geoaxes import GeoAxes


def _map_values(values, vmin, vmax, vrange, clip):
    # Allow a single value to be set for all the line segments
    if np.size(values) == 1:
        return values

    if vmin is None:
        vmin = values.min()
    if vmax is None:
        vmax = values.max()

    norm = plt.Normalize(vmin, vmax, clip)
    return vrange[0] + norm(values) * (vrange[1] - vrange[0])


[docs] def fancyline( x, y, colors=None, vmin=None, vmax=None, cmap=None, clip_colors=False, linewidths=None, wmin=None, wmax=None, wrange=(1, 5), clip_linewidths=True, alphas=None, amin=None, amax=None, arange=(0, 1), clip_alphas=True, linestyles=None, ax=None, transform=None, autoscale=True, ): """ A line plot of x vs y that can show extra information by having a variable color, linewidth, alpha, linestyle, or any combination of the four. For variable color set a vmin, vmax, and cmap (similar to pcolormesh/contourf) >>> fancyline(x, y, colors=z, vmin=0, vmax=10, cmap="viridis") For variable linewidth, set a wmin, wmax, and wrange. Like with vmin/vmax, wmin/wmax specify the data values for the smallest and largest linewidth with variables outside that range being clipping to wmin/wmax. The wrange specifies the range of linewidths that you actually want to display >>> fancyline(x, y, linewidths=z, wmin=0, wmax=10, wrange=(1, 5)) For a variable alpha, set an amin, amax, and arange >>> fancyline(x, y, alphas=z, amin=0, amax=10, arange=(0, 1)) For a variable linestyle, pass an array of linestyles specified as strings. e.g. to show whether z is above a threshold >>> linestyles = ["--" if value < 5 else "-" for value in z] >>> fancyline(x, y, linestyles=linestyles) https://matplotlib.org/stable/gallery/lines_bars_and_markers/multicolored_line Parameters ---------- x, y : array_like The points to plot colors : array_like or str, optional The data used to set the colors along the line or a string of the color to set the line to a uniform color vmin, vmax : scalar, optional The bounding values of the colors array for the colormap. If not set, will use the min and max of the colors array cmap : str, optional Specify the colormap. Will default to the matplotlib default (viridis) clip_colors : bool, default=False Clips values outside vmin/vmax to vmin/vmax. The default of False is the standard behaviour for matplotlib and sets the colours to the outside colors from the colormap linewidths : array_like or scalar, optional The data used to set the width along the line or a single value for the whole line wmin, wmax : scalar, optional The bounding values for the linewidths. If not set, will use the min and max of the linewidths array wrange : tuple, default=(1, 5) The range of linewidths to map the data to clip_linewidths : bool, default=True Clips values outside wmin/wmax to wmin/wmax. Unlike clip_colors, this is set to True by default because negative linewidths are interpreted as positive and to avoid very large linewidths on the figure. alphas : array_like or scalar, optional The data used to set the alpha along the line or a single value for the whole line amin, amax : float, optional The bounding values for the alphas. If not set, will use the min and max of the alphas array arange : tuple, default=(0, 1) The range of alphas to map the data to clip_alphas : bool, default=True Clips values outside amin/amax to amin/amax. Unlike clip_colors, this is set to True by default because alphas outside the range 0-1 will raise an error linestyles : array_like or str, optional The linestyle for each section of line. Same length as x/y ax : matplotlib.axes.Axes or cartopy.mpl.geoaxes.GeoAxes, optional The axes to add the line to. If not given, it will be added to the most recent axes transform : cartopy.crs.Projection, optional If the axes being drawn on are :class:`cartopy.mpl.geoaxes.GeoAxes` then the data will be converted from the data coordinates, given by the transform, to the projection coordinates. If a transform is not given, then :class:`cartopy.crs.Geodetic` will be used with default arguments autoscale : bool, default=True Determines whether to call :obj:`matplotlib.axes.Axes.autoscale` after adding the lines to the plot because the x/y limits are not automatically adjusted otherwise. If you are overlaying the line on an existing plot you may want to avoid doing this by setting to False. Returns ------- matplotlib.collections.LineCollection: The plotted LineCollection. Required as argument to :func:`matplotlib.pyplot.colorbar` """ if ax is None: ax = plt.gca() # Deal with cartopy transforms if isinstance(ax, GeoAxes): if transform is None: transform = Geodetic() xyz = ax.projection.transform_points(transform, x, y) x = xyz[:, 0] y = xyz[:, 1] # Break the xy points up in to line segments points = np.asarray([x, y]).T.reshape(-1, 1, 2) segments = np.concatenate([points[:-1], points[1:]], axis=1) # Collect the line segments lc = LineCollection(segments, path_effects=[Stroke(capstyle="round")]) if colors is not None: if np.size(colors) == 1: lc.set_colors(colors) else: lc.set_array(colors) if vmin is None: vmin = colors.min() if vmax is None: vmax = colors.max() lc.set_norm(plt.Normalize(vmin, vmax, clip_colors)) lc.set_cmap(cmap) if linewidths is not None: lc.set_linewidth(_map_values(linewidths, wmin, wmax, wrange, clip_linewidths)) if alphas is not None: lc.set_alpha(_map_values(alphas, amin, amax, arange, clip_alphas)) if linestyles is not None: lc.set_linestyle(linestyles) # Add the colored line to the existing plot ax.add_collection(lc) if autoscale: ax.autoscale() return lc