0

My question is a kind of follow up of this question. I use the solution proposed in the accepted answer to put some images as tick labels:

import matplotlib.pyplot as plt
import matplotlib.patches as patches
from matplotlib.image import BboxImage,imread
from matplotlib.transforms import Bbox

# define where to put symbols vertically
TICKYPOS = -.6

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(range(10))
plt.xlim((0,10))
plt.ylim((0,10))

# Remove tick labels
ax.get_xaxis().set_ticklabels([])

# Go from data coordinates to display coordinates
lowerCorner = ax.transData.transform((.8,TICKYPOS-.2))
upperCorner = ax.transData.transform((1.2,TICKYPOS+.2))

bbox_image = BboxImage(Bbox([lowerCorner,upperCorner]),
                       norm = None,
                       origin=None,
                       clip_on=False)

bbox_image.set_data(imread('thumb.png'))

ax.add_artist(bbox_image)

where thumb.png is an example of image I want to put as a tick label.

I then save the image with plt.savefig("bbox_large.png") and it works perfectly: Intended result, thumb.png is correctly positioned.

Unfortunately there is a lot of white space remaining around the picture. I tried to remove it using plt.savefig("bbox_tight.png",bbox_inches='tight'). However the positioning gets messed up:

thumb.png is not correctly positioned anymore.


As far as my understanding of matplotlib goes, the problem is that the bbox_inches='tight' option of savefig actually changes the display coordinates system, that is the origin is not in the same place. The figure is somehow correctly displayed but it seems that the coordinates of the artists added to the axes are not automatically updated.

I tried to take the extra artists into account using:

plt.savefig("bbox_tight_extra.png",bbox_extra_artists=[bbox_image],bbox_inches='tight')

but it gives the same result.

I also tried to use the event manager to manually update the display coordinates:

import matplotlib.pyplot as plt
import matplotlib.patches as patches
from matplotlib.image import BboxImage,imread
from matplotlib.transforms import Bbox

def ondraw(event):
    # Go from data coordinates to display coordinates
    lowerCorner = ax.transData.transform((.8,TICKYPOS-.2))
    upperCorner = ax.transData.transform((1.2,TICKYPOS+.2))

    bbox_image = BboxImage(Bbox([lowerCorner,upperCorner]),
                           norm = None,
                           origin=None,
                           clip_on=False)

    bbox_image.set_data(imread('thumb.png'))
    ax.add_artist(bbox_image)

# define where to put symbols vertically
TICKYPOS = -.6

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(range(10))
plt.xlim((0,10))
plt.ylim((0,10))

# Remove tick labels
ax.get_xaxis().set_ticklabels([])

fig.canvas.mpl_connect('draw_event', ondraw)

but it also gives the same result. I assume that it is because I do not explicitly use the event variable and hence I do not use the updated display coordinate system, that is the transData that I use is not the correct one.


How can I avoid having the position of the images getting messed up with bbox_inches='tight'?

M. P.
  • 101
  • 2
  • i'm pretty sure i've seen this problem before here on StackOverflow, let me try to find a relevant answer – Yuca Sep 20 '18 at 12:34
  • have you seen this? https://stackoverflow.com/questions/9622163/save-plot-to-image-file-instead-of-displaying-it-using-matplotlib/9890599#9890599 – Yuca Sep 20 '18 at 12:35
  • Thanks for the link. I tried to use the `pylab.savefig` function instead of `plt.savefig` but unfortunately it does not solve the problem. I also tried to save as a pdf instead of a png but the result is even worse and the original image is not correct anymore. Did I miss something? – M. P. Sep 20 '18 at 13:07
  • 2
    I guess it makes sense to answer this on the original question. See the [newly provided answer](https://stackoverflow.com/a/52426377/4124317). I will hence close this as duplicate such that the solutions are all in one place. – ImportanceOfBeingErnest Sep 20 '18 at 13:36
  • Sure! Thank you for the answer, it works perfectly. – M. P. Sep 20 '18 at 13:57

0 Answers0