Utility functions for stripes plottingΒΆ

# Shared plotting functions

from matplotlib.lines import Line2D
import numpy as np
import matplotlib.colors as colors
import datetime
from mpl_toolkits.axes_grid1.inset_locator import inset_axes


# Add a line of latitude to an axes
def add_latline(ax, latitude):
    latl = (latitude + 90) / 180
    ax.add_line(
        Line2D(
            ax.get_xlim(),
            [latl, latl],
            linewidth=0.75,
            color=(0.2, 0.2, 0.2, 1),
            zorder=200,
        )
    )


# Add a vertical date line
def add_dateline(ax_main, ax_ticks, year, fontsize=14):
    x = datetime.datetime(year, 1, 1, 0, 0).timestamp()
    ax_main.add_line(
        Line2D([x, x], [0.0, 1.0], linewidth=0.75, color=(0.2, 0.2, 0.2, 1), zorder=200)
    )
    if ax_ticks is not None:
        # Add the year label
        tfp = (x - ax_ticks.get_xlim()[0]) / (
            ax_ticks.get_xlim()[1] - ax_ticks.get_xlim()[0]
        )
        if tfp < 0.02 or tfp > 0.98:
            return
        ax_ticks.text(
            x,
            0.0,
            "%04d" % year,
            horizontalalignment="center",
            verticalalignment="bottom",
            color="black",
            clip_on=True,
            fontsize=fontsize,
            zorder=200,
        )


# Add a colorbar
def add_colorbar(
    ax_cb, img, label="Anomaly(C)", ticks=[-2, -1, -0.5, 0, 0.5, 1, 2], fontsize=12
):
    ax_cb.set_axis_off()
    cbm = ax_cb.get_figure().colorbar(
        img,
        ax=ax_cb,
        location="right",
        orientation="vertical",
        fraction=1.0,
        label=label,
        ticks=ticks,
    )
    cbm.ax.yaxis.label.set_size(fontsize)  # Set label font size
    cbm.ax.tick_params(labelsize=fontsize)  # Set tick label font size


# Add a textured grey background to an axes
def texture_background(ax, s=(2000, 600)):
    nd2 = np.random.rand(s[1], s[0])
    clrs = []
    for shade in np.linspace(0.42 + 0.01, 0.36 + 0.01):
        clrs.append((shade, shade, shade, 1))
    yg = np.linspace(ax.get_ylim()[0], ax.get_ylim()[1], s[1])
    xg = np.linspace(ax.get_xlim()[0], ax.get_xlim()[1], s[0])
    img = ax.pcolormesh(
        xg,
        yg,
        nd2,
        cmap=colors.ListedColormap(clrs),
        alpha=1.0,
        shading="gouraud",
        zorder=10,
    )
    return img


# Plot a set of three datasets
def plot_dataset(
    ax,
    dts,
    ndata,
    cmap,
    norm,
    colorbar=True,
    ticks=False,
    ticks_fontsize=14,
    cm_fontsize=14,
):
    ax.set_axis_off()

    # Sub axes - main, colorbar, maybe xticks
    if ticks:
        ax_main = ax.inset_axes(
            bounds=[0.0, 0.05, 0.95, 0.95],
        )
        ax_cb = ax.inset_axes(bounds=[0.955, 0.05 + 0.15 * 0.95, 0.05, 0.7 * 0.95])
        ax_ticks = ax.inset_axes(
            bounds=[0.0, 0.0, 0.95, 0.05],
        )
    else:
        ax_main = ax.inset_axes(bounds=[0.0, 0.0, 0.95, 1.0])
        ax_cb = ax.inset_axes(bounds=[0.955, 0.15, 0.045, 0.7])
        ax_ticks = None

    ax_main.set_axis_off()
    ax_main.set_xlim(
        (dts[0] + datetime.timedelta(days=1)).timestamp(),
        (dts[-1] - datetime.timedelta(days=1)).timestamp(),
    )
    ax_main.set_ylim((1, 0))
    ax_cb.set_axis_off()
    if ax_ticks is not None:
        ax_ticks.set_axis_off()
        ax_ticks.set_xlim(
            (dts[0] + datetime.timedelta(days=1)).timestamp(),
            (dts[-1] - datetime.timedelta(days=1)).timestamp(),
        )
        ax_ticks.set_ylim((0, 1))

    # Add a textured grey background
    imgt = texture_background(ax_main)

    # Main plot
    s = ndata.shape
    y = 1.0 - np.linspace(0, 1, s[0] + 1)
    x = [(a - datetime.timedelta(days=15)).timestamp() for a in dts]
    x.append((dts[-1] + datetime.timedelta(days=15)).timestamp())
    imgm = ax_main.pcolorfast(x, y, ndata, cmap=cmap, alpha=1.0, norm=norm, zorder=100)

    # Add a latitude grid
    for lat in (-60, -30, 0, 30, 60):
        add_latline(ax_main, lat)

    # Add a date grid

    for year in range((dts[0].year // 10) * 10, dts[-1].year, 10):
        add_dateline(ax_main, ax_ticks, year, ticks_fontsize)

    # add a ColourBar
    if colorbar:
        add_colorbar(ax_cb, imgm, label="Anomaly (C)", fontsize=cm_fontsize)