Rhinoceros: 4th and 5th Left panelΒΆ

../../_images/p4L_5L.webp

The 4th and 5th left panel uses a streamplot, polygon patches, vlines, and imshow.

# function to plot the contents of the row 4 and 5 Left panel

import sys
from matplotlib.patches import Polygon
from utils import smoothLine, colours, viridis
import numpy as np
import matplotlib


def p4L_5L(fig, gspec):
    ax_4L_5L = fig.add_subplot(
        gspec,
        frameon=True,
        xlim=[0, 100],
        xticks=[0, 20, 40, 60, 80, 100],
        ylim=[0, 1],
        yticks=[0.1, 0.3, 0.5, 0.7, 0.9],
    )
    ax_4L_5L.set_facecolor(colours["ax_bg"])
    ax_4L_5L.spines["right"].set_visible(False)
    ax_4L_5L.spines["top"].set_visible(False)

    # Bottom of the hip plate
    hipl = smoothLine(
        np.array(
            [
                [20, 1.0],
                [30, 0.8],
                [50, 0.65],
                [70, 0.55],
                [80, 0.65],
                [90, 0.72],
                [100, 1.0],
            ]
        ),
        horizontal=True,
        k=3,
    )
    hip_patch = matplotlib.patches.Polygon(
        hipl, facecolor=colours["ax_bg"], edgecolor="none", zorder=200
    )
    ax_4L_5L.add_patch(hip_patch)

    # Fill the hip patch with a streamplot
    # make a stream function:
    X, Y = np.meshgrid(np.linspace(0, 100, 200), np.linspace(0, 1, 200))
    Z = ((X - 60) / 10) ** 3 + (100 * (Y - 0.7)) ** 2
    # make U and V out of the streamfunction:
    V = np.diff(Z[1:, :], axis=1)
    U = -np.diff(Z[:, 1:], axis=0)
    sps = ax_4L_5L.streamplot(
        X[1:, 1:],
        Y[1:, 1:],
        U,
        V,
        arrowsize=0,  # Arrows can't be clipped - they will be drawn outside the hip patch
        density=2,
        linewidth=3,
        color=colours["purple"],
        zorder=250,
    )
    sps.lines.set_clip_path(hip_patch)

    # Rear right leg
    legr_l = smoothLine(  # Left side
        np.array(
            [
                [30, 0.85],
                [18, 0.65],
                [23, 0.3],
                [20, 0.22],
                [28, 0.1],
            ]
        ),
        horizontal=False,
    )
    legr_b = smoothLine(  # Bottom
        np.array(
            [
                [28, 0.1],
                [40, 0.06],
                [60, 0.05],
                [78, 0.08],
            ]
        ),
        horizontal=True,
        k=2,
    )
    legr_r = smoothLine(  # Right side
        np.array(
            [
                [78, 0.08],
                [70, 0.25],
                [60, 0.3],
                [55, 0.35],
                [60, 0.5],
                [65, 0.6],
            ]
        ),
        horizontal=False,
        k=2,
    )
    legr = np.append(legr_l, legr_b, axis=0)
    legr = np.append(legr, legr_r, axis=0)
    legr_patch = matplotlib.patches.Polygon(
        legr,
        facecolor=colours["ax_bg"],
        edgecolor=colours["green"],
        hatch="X",
        linewidth=3,
        zorder=100,
    )
    ax_4L_5L.add_patch(legr_patch)

    # Rear left leg
    legl = smoothLine(
        np.array(
            [
                [100, 0.25],
                [95, 0.4],
                [90, 0.45],
                [80, 0.65],
                [70, 0.8],
                [85, 0.9],
                [100, 1.0],
            ]
        ),
        horizontal=False,
        k=2,
    )
    legl_patch = matplotlib.patches.Polygon(
        legl,
        facecolor=colours["ax_bg"],
        edgecolor=colours["blue"],
        hatch="//",
        linewidth=3,
        zorder=20,
    )
    ax_4L_5L.add_patch(legl_patch)

    # Ground shading with a clipped gradient
    phi = 0.5 * np.pi / 2
    v = np.array([np.cos(phi), np.sin(phi)])
    X = np.array([[v @ [1, 0], v @ [1, 1]], [v @ [0, 0], v @ [0, 1]]])
    a, b = (0, 1)
    X = a + (b - a) / X.max() * X
    im = ax_4L_5L.imshow(
        X,
        interpolation="bicubic",
        clim=(0, 1),
        aspect="auto",
        extent=(100, 0, 0, 1),
        cmap="gray_r",
        alpha=0.3,
        zorder=5,
    )
    im.set_clip_path(
        Polygon([[0, 0], [0, 0.4], [100, 0.6], [100, 0]], transform=ax_4L_5L.transData)
    )

    # bottom part of tail
    yt = np.linspace(10, 15, 8)
    lengths = 0.07  # + np.random.rand(yt.shape[0]) * 0.1
    ax_4L_5L.vlines(
        yt,
        ymin=1.0 - lengths,
        ymax=1.0,
        colors=colours["blue"],
        linewidths=1,
        zorder=10,
    )
    yt = np.linspace(8, 10, 3)
    lengths = np.random.rand(yt.shape[0]) * 0.05 + 0.05
    ax_4L_5L.vlines(
        yt,
        ymin=0.95 - lengths,
        ymax=0.95,
        colors=colours["blue"],
        linewidths=1,
        zorder=10,
    )
    yt = np.linspace(15, 17, 3)
    lengths = np.random.rand(yt.shape[0]) * 0.05 + 0.05
    ax_4L_5L.vlines(
        yt,
        ymin=0.95 - lengths,
        ymax=0.95,
        colors=colours["blue"],
        linewidths=1,
        zorder=10,
    )

    return ax_4L_5L