0

I am trying to plot unicode characters in a matplotlib plot in an ipython notebook.

# For example:
plt.title("α")

However, it gives a UnicodeEncodeError. I have tried importing the unicode_literals module as suggested in the matplotlib documentation here: http://matplotlib.org/examples/text_labels_and_annotations/unicode_demo.html. I have also tried using a unicode string with plt.title(u"α"), as suggested here: Unicode in ipython notebook.

Neither approach has affected the error output, (which I've put at the bottom).

How can I get unicode strings to plot in matplotlib in an ipython notebook?

I am not interested in using LaTeX in this case, if that is ok.

---------------------------------------------------------------------------
UnicodeEncodeError                        Traceback (most recent call last)
/usr/local/lib/python3.5/site-packages/IPython/core/formatters.py in __call__(self, obj)
    305                 pass
    306             else:
--> 307                 return printer(obj)
    308             # Finally look for special method names
    309             method = get_real_method(obj, self.print_method)

/usr/local/lib/python3.5/site-packages/IPython/core/pylabtools.py in <lambda>(fig)
    225 
    226     if 'png' in formats:
--> 227         png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
    228     if 'retina' in formats or 'png2x' in formats:
    229         png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))

/usr/local/lib/python3.5/site-packages/IPython/core/pylabtools.py in print_figure(fig, fmt, bbox_inches, **kwargs)
    117 
    118     bytes_io = BytesIO()
--> 119     fig.canvas.print_figure(bytes_io, **kw)
    120     data = bytes_io.getvalue()
    121     if fmt == 'svg':

/usr/local/lib/python3.5/site-packages/matplotlib/backend_bases.py in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, **kwargs)
   2178                     orientation=orientation,
   2179                     dryrun=True,
-> 2180                     **kwargs)
   2181                 renderer = self.figure._cachedRenderer
   2182                 bbox_inches = self.figure.get_tightbbox(renderer)

/usr/local/lib/python3.5/site-packages/matplotlib/backends/backend_agg.py in print_png(self, filename_or_obj, *args, **kwargs)
    525 
    526     def print_png(self, filename_or_obj, *args, **kwargs):
--> 527         FigureCanvasAgg.draw(self)
    528         renderer = self.get_renderer()
    529         original_dpi = renderer.dpi

/usr/local/lib/python3.5/site-packages/matplotlib/backends/backend_agg.py in draw(self)
    472 
    473         try:
--> 474             self.figure.draw(self.renderer)
    475         finally:
    476             RendererAgg.lock.release()

/usr/local/lib/python3.5/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     60     def draw_wrapper(artist, renderer, *args, **kwargs):
     61         before(artist, renderer)
---> 62         draw(artist, renderer, *args, **kwargs)
     63         after(artist, renderer)
     64 

/usr/local/lib/python3.5/site-packages/matplotlib/figure.py in draw(self, renderer)
   1157         dsu.sort(key=itemgetter(0))
   1158         for zorder, a, func, args in dsu:
-> 1159             func(*args)
   1160 
   1161         renderer.close_group('figure')

/usr/local/lib/python3.5/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     60     def draw_wrapper(artist, renderer, *args, **kwargs):
     61         before(artist, renderer)
---> 62         draw(artist, renderer, *args, **kwargs)
     63         after(artist, renderer)
     64 

/usr/local/lib/python3.5/site-packages/matplotlib/axes/_base.py in draw(self, renderer, inframe)
   2317 
   2318         for zorder, a in dsu:
-> 2319             a.draw(renderer)
   2320 
   2321         renderer.close_group('axes')

/usr/local/lib/python3.5/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     60     def draw_wrapper(artist, renderer, *args, **kwargs):
     61         before(artist, renderer)
---> 62         draw(artist, renderer, *args, **kwargs)
     63         after(artist, renderer)
     64 

/usr/local/lib/python3.5/site-packages/matplotlib/text.py in draw(self, renderer)
    747 
    748         with _wrap_text(self) as textobj:
--> 749             bbox, info, descent = textobj._get_layout(renderer)
    750             trans = textobj.get_transform()
    751 

/usr/local/lib/python3.5/site-packages/matplotlib/text.py in _get_layout(self, renderer)
    359                 w, h, d = renderer.get_text_width_height_descent(clean_line,
    360                                                         self._fontproperties,
--> 361                                                         ismath=ismath)
    362             else:
    363                 w, h, d = 0, 0, 0

/usr/local/lib/python3.5/site-packages/matplotlib/backends/backend_agg.py in get_text_width_height_descent(self, s, prop, ismath)
    227             fontsize = prop.get_size_in_points()
    228             w, h, d = texmanager.get_text_width_height_descent(s, fontsize,
--> 229                                                                renderer=self)
    230             return w, h, d
    231 

/usr/local/lib/python3.5/site-packages/matplotlib/texmanager.py in get_text_width_height_descent(self, tex, fontsize, renderer)
    673         else:
    674             # use dviread. It sometimes returns a wrong descent.
--> 675             dvifile = self.make_dvi(tex, fontsize)
    676             dvi = dviread.Dvi(dvifile, 72 * dpi_fraction)
    677             try:

/usr/local/lib/python3.5/site-packages/matplotlib/texmanager.py in make_dvi(self, tex, fontsize)
    397 
    398         if DEBUG or not os.path.exists(dvifile):
--> 399             texfile = self.make_tex(tex, fontsize)
    400             outfile = basefile + '.output'
    401             command = self._get_shell_cmd(

/usr/local/lib/python3.5/site-packages/matplotlib/texmanager.py in make_tex(self, tex, fontsize)
    312             else:
    313                 try:
--> 314                     fh.write(s.encode('ascii'))
    315                 except UnicodeEncodeError as err:
    316                     mpl.verbose.report("You are using unicode and latex, but "

UnicodeEncodeError: 'ascii' codec can't encode character '\xb0' in position 289: ordinal not in range(128)
Community
  • 1
  • 1
  • For me `plt.title("α")` works fine when using `unicode_literals`. Omitting the future import, `plt.title(u"α")` works as well. So I guess you need to provide a [mcve] of the issue. Especially it seems that the traceback goes along some latex rendering in `texmanager.py`, which suggests you *are* actually using Latex. This could of course be a problem together with unicode characters. – ImportanceOfBeingErnest Feb 21 '17 at 08:24

2 Answers2

1

Thanks for the help amoose136. But I managed to figure it out. There were two things.

First, I was using TeX to do the text:

matplotlib.rc('text', usetex=True)

TeX and unicode don't mix.

Omitting this line allowed the matplotlib documentation example to work (in the question info).

Secondly, it then compiled, but I had my (greek) characters showing up as boxes. To fix this, I followed the advice here: Non-ASCII characters in Matplotlib, and used a font that supported my characters, like Arial:

matplotlib.rc('font', family='Arial')

Hope this helps anyone!

Community
  • 1
  • 1
0

Without a full example it's difficult to say for sure what's going on but I can tell you what I did when I had a similar issue and I wanted it to run on both python 2 and python 3 for future proofing.

In the header of the file:

#!/usr/bin/env python
# coding: utf-8
import six,sys
# needed for utf-encoding on python 2:
if six.PY2:
    reload(sys)
    sys.setdefaultencoding('utf8')

Note that for a good reason specified by the pep-0263 standard, the # coding: utf-8 line is actually important and does something. Try that and see if if fixes it. If not, provide a complete example and I will update this answer accordingly.

Alternatively, try changing it to plt.title(u'α').

amoose136
  • 178
  • 1
  • 8