Using matplotlib scatter markers in text of legend together with Latex

1.7k Views Asked by At

I have a plot with an inset. The latter has a legend, in whose text I would like to use matplotlib scatter markers. I also want to be able to use LaTeX at the same time for all the labels and legends. The reason I am mentioning this is because I had a look at this thread and the solutions there don't work for me. I will explain why bellow.

Here is an example code (sorry for the functions I am plotting, couldn't think of anything)

# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid.inset_locator import (inset_axes, InsetPosition, mark_inset)
from matplotlib import rc
rc('text', usetex=True)

N = 50
x = np.random.rand(N)
y = np.random.rand(N)

fig, ax1 = plt.subplots()

ax1.scatter(x, np.cos(x), color = 'blue', marker = "D", s=47.5, label = r'$\cos$')
ax1.scatter(y, np.sin(y), color = 'cyan', marker = "*", alpha = 0.85, label = r'$\sin$')
ax1box = ax1.get_position()
x_value = -0.13
y_value = 0.675
legend=ax1.legend(loc = (ax1box.x0 + x_value, ax1box.y0 + y_value), handletextpad=0.1, prop={'size':8})
frame = legend.get_frame()
frame.set_alpha(0)
frame.set_linewidth(0)

ax2 = plt.axes([0.5,0.5,0.5,0.5])
ip = InsetPosition(ax1, [0.55,0,0.45,0.40])
ax2.set_axes_locator(ip)
ax2.scatter(x, np.tan(x), color = 'gray', marker = "v", s=15, label = r'Insert blue square marker here')
ax2.scatter(y, np.log(y)+1, color = 'brown', marker = "4", s=15, label = r'Insert cyan star marker here')
ax2.xaxis.tick_top()
ax2.xaxis.set_label_position('top')
ax2.yaxis.tick_right()
legend2=ax2.legend(loc = 'lower right', handletextpad=0.1, prop={'size':7})
frame2 = legend2.get_frame()
frame2.set_alpha(0)
frame2.set_linewidth(0)

plt.show()

If I am to go with the advice in here about LaTeX and try with

ax2.scatter(x, np.tan(x), color = 'gray', marker = "v", s=15, label = r'$\square$')

the plot shows with no legend in the inset.

If, instead, I decide to implement the unicode solution

ax2.scatter(x, np.tan(x), color = 'gray', marker = "v", s=15, label = '●')

I get the following error

Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python3.5/tkinter/__init__.py", line 1562, in __call__
    return self.func(*args)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/backends/backend_tkagg.py", line 280, in resize
    self.show()
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/backends/backend_tkagg.py", line 351, in draw
    FigureCanvasAgg.draw(self)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/backends/backend_agg.py", line 464, in draw
    self.figure.draw(self.renderer)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/artist.py", line 63, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/figure.py", line 1144, in draw
    renderer, self, dsu, self.suppressComposite)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/image.py", line 139, in _draw_list_compositing_images
    a.draw(renderer)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/artist.py", line 63, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/axes/_base.py", line 2426, in draw
    mimage._draw_list_compositing_images(renderer, self, dsu)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/image.py", line 139, in _draw_list_compositing_images
    a.draw(renderer)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/artist.py", line 63, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/legend.py", line 471, in draw
    bbox = self._legend_box.get_window_extent(renderer)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/offsetbox.py", line 269, in get_window_extent
    w, h, xd, yd, offsets = self.get_extent_offsets(renderer)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/offsetbox.py", line 391, in get_extent_offsets
    for c in self.get_visible_children()]
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/offsetbox.py", line 391, in <listcomp>
    for c in self.get_visible_children()]
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/offsetbox.py", line 262, in get_extent
    w, h, xd, yd, offsets = self.get_extent_offsets(renderer)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/offsetbox.py", line 462, in get_extent_offsets
    for c in self.get_visible_children()]
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/offsetbox.py", line 462, in <listcomp>
    for c in self.get_visible_children()]
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/offsetbox.py", line 262, in get_extent
    w, h, xd, yd, offsets = self.get_extent_offsets(renderer)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/offsetbox.py", line 391, in get_extent_offsets
    for c in self.get_visible_children()]
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/offsetbox.py", line 391, in <listcomp>
    for c in self.get_visible_children()]
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/offsetbox.py", line 262, in get_extent
    w, h, xd, yd, offsets = self.get_extent_offsets(renderer)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/offsetbox.py", line 462, in get_extent_offsets
    for c in self.get_visible_children()]
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/offsetbox.py", line 462, in <listcomp>
    for c in self.get_visible_children()]
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/offsetbox.py", line 835, in get_extent
    bbox, info, d = self._text._get_layout(renderer)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/text.py", line 362, in _get_layout
    ismath=ismath)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/backends/backend_agg.py", line 230, in get_text_width_height_descent
    renderer=self)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/texmanager.py", line 676, in get_text_width_height_descent
    dvifile = self.make_dvi(tex, fontsize)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/texmanager.py", line 399, in make_dvi
    texfile = self.make_tex(tex, fontsize)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/texmanager.py", line 314, in make_tex
    fh.write(s.encode('ascii'))
UnicodeEncodeError: 'ascii' codec can't encode character '\u25cf' in position 226: ordinal not in range(128) 

Which seems to come from the fact that I am using LaTeX, as If I comment out

# from matplotlib import rc
# rc('text', usetex=True)

Then I get everything working, but without LaTeX. (Well the circle I get is black, I haven't looked into whether it is possible to change its colour yet). I do want LaTeX, though, so this is not good for me.

1

There are 1 best solutions below

5
Andrey Sobolev On BEST ANSWER

As The Great, Big List of LaTeX Symbols tells us, \square is an AMS symbol. So, in order to use it you have to put \usepackage{amssymb} in your preamble, which can be done with

rc('text', usetex=True)
rc('text.latex', preamble=r'\usepackage{amssymb}')