Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can i specify the bottom right corner of a text box in matplotlib?

Is there any way I can specify the bottom right corner coordinates of a text box using matplotlib?

the code for my box is:

plt.text(x_max-2.7e+3, y_min+1e+5, box_text, style='italic',
        bbox={'facecolor':'white', 'alpha':0.5, 'pad':10})

and that produces this for the current plot:

enter image description here

however, those coordinate values were found by trial and error, and the ranges and orders of magnitude for my data will be different for different plots as well.. I would like a way that I can specify the coordinates of the bottom right corner of the text box to be (x_max, y_min) and it would automatically draw the box from there.

Is there any way to do this?

like image 789
guskenny83 Avatar asked Apr 20 '18 03:04

guskenny83


1 Answers

Not surprisingly, the answer is yes. However, there is a much simpler way to do what you want. Let me begin with a bit of background first.

plt.text is just a wrapper that creates a mpl.text.Text object on the current axes. Unfortunately, Text anchors itself based on the text alignment properties, and you can't specify an arbitrary point of the text box to anchor. This is unfortunate because there is a whole tutorial on how to position text using the axis transform (coordinate system) instead of the data.

Fortunately, there are some helper classes in matplotlib.offsetbox that do exactly what you want. These classes are described in the tutorial, and a couple of relevant examples are shown in the sample gallery here and here. The particular class you are looking for is mpl.offsetbox.AnchoredText. You would set up your text box like this:

from matplotlib.offsetbox import AnchoredText

...

text_box = AnchoredText(box_text, frameon=True, loc=4, pad=0.5)
plt.setp(text_box.patch, facecolor='white', alpha=0.5)
plt.gca().add_artist(text_box)

frameon=True makes the Patch behind the text visible. loc=4 lines up the bottom right corner of the box with that of the Axes. pad is now in units of fractions of your font size. plt.setp is a utility function to set multiple properties on an bunch of objects at once. The first argument in this case is just a single patch, but normally you would pass in a list of things to operate on.

Since you have to add an AnchoredText directly to an Axes, I would recommend switching to the Object Oriented API. Your code would look very similar, but you would have more direct access to the underlying objects. You would create your figure and axes using something like plt.subplots. Then you would plot your data using the methods of Axes that correspond to the usual pyplot methods. Your code would look like this:

from matplotlib import pyplot as plt
from matplotlib.offsetbox import AnchoredText

fig, ax = plt.subplots()

ax.plot(...)

text_box = AnchoredText(box_text, frameon=True, loc=4, pad=0.5)
plt.setp(text_box.patch, facecolor='white', alpha=0.5)
ax.add_artist(text_box)
like image 174
Mad Physicist Avatar answered Nov 20 '22 00:11

Mad Physicist