Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adjust padding inside matplotlib annotation box

I'm using the annotate method on an Axes object to add an arrow with text to a plot. For example:

ax.annotate('hello world,
            xy=(1, 1),
            xycoords='data',
            textcoords='data',
            fontsize=12,
            backgroundcolor='w',
            arrowprops=dict(arrowstyle="->",
                            connectionstyle="arc3")

This works well but I want to decrease the padding on the inside of the annotation box. Essentially, I want to make the box 'squeeze' tighter around the text. Is there any way to do this via the arrowprops or bbox_props kwargs?

I'm looking for something like borderpad that's available on legends, similar to what's discussed on this answer.

like image 644
durden2.0 Avatar asked Mar 18 '15 10:03

durden2.0


1 Answers

Yes, but you'll need to switch to a slightly different way of specifying the box. The "basic" box doesn't support it, so you need to have annotate make a FancyBboxPatch associated with the text object. (The same syntax for a "fancy" box would work text placed with ax.text as well, for what it's worth.)


Also, before we go much farther, there are a couple of rather thorny bugs that affect this in the current version of matplotlib (1.4.3). (e.g. https://github.com/matplotlib/matplotlib/issues/4139 and https://github.com/matplotlib/matplotlib/issues/4140)

If you're seeing things like this: enter image description here

Instead of this: enter image description here

You might consider downgrading to matplotlib 1.4.2 until the issue is fixed.


Let's take your example as a starting point. I've changed the background color to red and put it in the center of the figure to make it a touch easier to see. I'm also going to leave off the arrow (avoiding the bug above) and just use ax.text instead of annotate.

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
a = ax.text(0.5, 0.5, 'hello world',
            fontsize=12,
            backgroundcolor='red')

plt.show()

enter image description here

To be able to change the padding, you'll need to use the bbox kwarg to text (or annotate). This makes the text use a FancyBboxPatch, which supports padding (along with several other things).

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
a = ax.text(0.5, 0.5, 'hello world', fontsize=12,
            bbox=dict(boxstyle='square', fc='red', ec='none'))

plt.show()

enter image description here

The default padding is pad=0.3. (If I recall correctly, the units are fractions of the height/width of the text's extent.) If you'd like to increase it, use boxstyle='square,pad=<something_larger>':

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
a = ax.text(0.5, 0.5, 'hello world', fontsize=12,
            bbox=dict(boxstyle='square,pad=1', fc='red', ec='none'))

plt.show()

enter image description here

Or you can decrease it by putting in 0 or a negative number to shrink it farther:

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
a = ax.text(0.5, 0.5, 'hello world', fontsize=12,
            bbox=dict(boxstyle='square,pad=-0.3', fc='red', ec='none'))

plt.show()

enter image description here

like image 86
Joe Kington Avatar answered Nov 16 '22 22:11

Joe Kington