Skip to content

Instantly share code, notes, and snippets.

@EdwinChan
Created February 16, 2019 23:20
Show Gist options
  • Save EdwinChan/5aa32be477d4efa126746c37ae774ffc to your computer and use it in GitHub Desktop.
Save EdwinChan/5aa32be477d4efa126746c37ae774ffc to your computer and use it in GitHub Desktop.
Matplotlib text bounding boxes
mode = ['png', 'svg', 'pdf', 'pgf'][3]
dpi = 100
poem = '''
Farewell sweet earth and northern sky,
for ever blest, since here did lie,
and here with lissom limbs did run,
beneath the moon, beneath the sun,
L\xfathien Tin\xfaviel
more fair than mortal tongue can tell.
Though all to ruin fell the world,
and were dissolved and backward hurled
unmade into the old abyss,
yet were its making good, for this\u2014
the dawn, the dusk, the earth, the sea\u2014
that L\xfathien on a time should be!
'''.strip('\n').split('\n')
poem[2] += r' $\int dx\,\ln x=\frac{1}{x}+C$'
poem[6] += r' $e=\sum_{n=0}^\infty\frac{1}{n!}$'
poem[10] += r' $\tan x=\frac{\sin x}{\cos x}$'
import itertools
import matplotlib
if mode == 'pgf':
matplotlib.use('pgf')
from matplotlib import pyplot
def hide_frame(axes):
axes.set_frame_on(False)
axes.tick_params(bottom=False, top=False, left=False, right=False,
labelcolor='none')
for tick in itertools.chain(
axes.xaxis.get_major_ticks(),
axes.xaxis.get_minor_ticks(),
axes.yaxis.get_major_ticks(),
axes.yaxis.get_minor_ticks()):
tick.set_visible(False)
pyplot.xlabel('\n'.join(poem[8:12]),
linespacing=1.5, rotation=-10, ha='right', rotation_mode='anchor')
pyplot.ylabel('\n'.join(poem[0:4]),
linespacing=1.5, rotation=30)
pyplot.annotate('\n'.join(poem[4:8]), (0.15, 0.15),
linespacing=1.5)
pyplot.subplots_adjust(left=0.35, bottom=0.35)
hide_frame(pyplot.gca())
def draw_text_boxes(text, format, dpi):
figure = text.figure
canvas = figure.canvas._get_output_canvas(format)
figure.dpi, dpi = dpi, figure.dpi
import io
getattr(canvas, 'print_' + format)(io.BytesIO(), dryrun=True)
renderer = figure._cachedRenderer
from matplotlib.lines import Line2D
from matplotlib.patches import Rectangle
from matplotlib.transforms import Affine2D
tx = text.convert_xunits(text._x)
ty = text.convert_yunits(text._y)
tx, ty = text.get_transform().transform((tx, ty))
_, coords, _ = text._get_layout(renderer)
coords = [(tx+x, ty+y, dx, dy) for _, (dx, dy), x, y in coords]
depths = []
for line in text.get_text().split('\n'):
line, is_math = text.is_math_text(line, text.get_usetex())
if line:
_, _, d = renderer.get_text_width_height_descent(
line, text.get_fontproperties(), is_math)
else:
d = 0
depths.append(d)
rotation = text.get_rotation()
transforms = [
Affine2D().rotate_deg(rotation).translate(x, y)
for x, y, _, _ in coords]
pyplot.gcf().lines += (
Line2D((0, dx), (0, 0), transform=t, zorder=0)
for (_, _, dx, _), t in zip(coords, transforms))
pyplot.gcf().artists += (
Rectangle((0, -d), dx, dy, transform=t, zorder=0, alpha=0.3)
for (_, _, dx, dy), d, t in zip(coords, depths, transforms))
figure.dpi = dpi
draw_text_boxes(pyplot.gca().xaxis.label, mode, dpi)
draw_text_boxes(pyplot.gca().yaxis.label, mode, dpi)
draw_text_boxes(pyplot.gca().texts[0], mode, dpi)
pyplot.savefig('textbbox.' + ('pdf' if mode == 'pgf' else mode), dpi=dpi)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment