79822386

Date: 2025-11-17 14:06:43
Score: 0.5
Natty:
Report link

I wrote a function for anyone who wants curly braces:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import transforms


def partial_circle(x_center, y_center, radius_x, radius_y, start_deg, end_deg, n=100):
    t = np.linspace(start_deg/180*np.pi, end_deg/180*np.pi, n)
    return x_center + radius_x * np.cos(t), y_center + radius_y * np.sin(t)


def underbrace(ax,
               x_start, x_end,       # horizontal position in data coords
               y=-0.15,              # vertical position in axes coords (0 = bottom, 1 = top)
               label=None,
               radius_y=0.02,        # vertical radius in axes coords
               radius_x=0.1,         # horizontal radius in data coords
               lw=1.0,
               color="black",
               text_offset=-0.04,    # extra offset for the label in axes coords
               **text_kwargs):

    # x in data coords, y in axes coords
    trans = transforms.blended_transform_factory(ax.transData, ax.transAxes)

    x_mid = 0.5 * (x_start + x_end)

    y_top = y + radius_y
    y_mid = y
    y_bottom = y - radius_y

    # left brace
    X_circ_left, Y_circ_left = partial_circle(x_start + radius_x, y_top, radius_x, radius_y, 180, 270)
    X_line_left = np.linspace(x_start + radius_x, x_mid - radius_x)
    Y_line_left = np.full_like(X_line_left, y_mid)
    # middle kink
    X_circ_mid_left,  Y_circ_mid_left  = partial_circle(x_mid - radius_x, y_bottom, radius_x, radius_y, 90, 0)
    X_circ_mid_right, Y_circ_mid_right = partial_circle(x_mid + radius_x, y_bottom, radius_x, radius_y, 180, 90)
    # right brace
    X_line_right = np.linspace(x_mid + radius_x, x_end - radius_x)
    Y_line_right = np.full_like(X_line_right, y_mid)
    X_circ_right, Y_circ_right = partial_circle(x_end - radius_x, y_top, radius_x, radius_y, 270, 360)

    Xs = np.concatenate([X_circ_left, X_line_left,
                         X_circ_mid_left, X_circ_mid_right,
                         X_line_right, X_circ_right])
    Ys = np.concatenate([Y_circ_left, Y_line_left,
                         Y_circ_mid_left, Y_circ_mid_right,
                         Y_line_right, Y_circ_right])

    ax.plot(Xs, Ys, color=color, lw=lw, transform=trans, clip_on=False)

    if label is not None:
        ax.text(x_mid, y + text_offset, label,
                ha="center", va="top",
                transform=trans, color=color, **text_kwargs)


# Array of values
values = np.array([[1,2,3], [1,2,3]])

# Line plot
fig, ax = plt.subplots()
plt.plot(values[0,:], values[1,:], 'bo-',label='$P_{1}$')

# make room for braces + labels
plt.subplots_adjust(bottom=0.25)

# add braces
underbrace(ax, 1.0, 2.0, label="s", color="red")
underbrace(ax, 2.0, 3.0, label="t - s", color="green")

plt.legend()
plt.show()

Output image: Graph with curly underbraces

Reasons:
  • Probably link only (1):
  • Long answer (-1):
  • Has code block (-0.5):
  • Low reputation (1):
Posted by: karla