35

I'd like to have a colored buffer around annotation text within a matplotlib. This screenshot taken in QGIS shows how it looks like (in red):

buffered text in GIS

What I tried

My naive approaches involved plotting 'Some text' twice, with different font size and font weight. The result looks not convincing both times. The bbox solution "works", but does not have the same aesthetics as the buffered text.

%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt

# font size
plt.annotate(
    'Some text', xy=(.5, .75), color=(.7, .7, .7), 
    ha='center', va='center', fontsize='20')
plt.annotate(
    'Some text', xy=(.5, .75), color=(.2, .3, .8), 
    ha='center', va='center', fontsize='16')

# font weight
plt.annotate(
    'Some text', xy=(.5, .5), color=(.7, .7, .7), 
    ha='center', va='center', fontsize='16', weight='bold')
plt.annotate(
    'Some text', xy=(.5, .5), color=(.2, .3, .8), 
    ha='center', va='center', fontsize='16')

# bbox
plt.annotate(
    'Some text', xy=(.5, .25), color=(.2, .3, .8), 
    ha='center', va='center', fontsize='16', 
    bbox=dict(fc=(.7, .7, .7), lw=0, pad=5))

Result

matplotlib exercises to recreate buffered text

So my question is

(How) is it possible (with reasonable effort) to recreate buffered text in matplotlib?

4
  • (I'm posting this as a comment as I don't know for sure and hopefully for you someone could prove me wrong :) ) but I am pretty sure this isn't possible. Commented Aug 21, 2014 at 12:55
  • @Ffisegydd: I hope you are wrong :-) My experience with SO/SE so far has been that there are code ninjas who craft solutions for every problem, often shorter and more elegant than I expected them to be, especially when huge package/framework ecosystems are concerned. Probably there is some obscure technique/hack/undocumented switch/... Unfortunately, my matplotlib-foo is not strong enough yet to find them on my own. Commented Aug 21, 2014 at 12:59
  • I have found that as well :) The only reference to "edgecolor" in matplotlib.text is talking about the edgecolor of the bbox which unfortunately is not what you want. The problem with trying to use a larger font is that you don't really want a larger font, you want the same size font but you want the actual font curves to be "thicker". Still, hopefully someone will come up with some matplotlib-based wizardry :) Commented Aug 21, 2014 at 13:13
  • One thing you might want to look into is matplotlib.font_manager which will allow you to add your own. If you can find the font you want (with the bordering) in your system (or on the internet) then you could add it yourself and not have to worry about the matplotlib wizardry. Commented Aug 21, 2014 at 13:15

1 Answer 1

71

There's a detailed demo over here of using path effects to outline a variety of graphical objects. Here is a minimal example focusing on the text element.

import matplotlib.pyplot as plt
import matplotlib.patheffects as pe

fig, ax = plt.subplots()
txt = ax.text(0.5, 0.5, "test",
              size=20,
              color='white',
              path_effects=[pe.withStroke(linewidth=4, foreground="red")])

Example output showing white text outlined in red

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.