Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

matplotlib savefig - text chopped off [duplicate]

Say I create a plot:

import matplotlib.pyplot as plt
plt.clf()
import numpy as np
props = np.random.randint(0,100,(200,))
x=np.arange(1,201,1)
plt.plot(x,props,c='k')
plt.xlabel('blah blah blah blah blah blah\n blah blah blah blah blah')
plt.ylabel('blah blah blah blah blah blah blah blah blah')
fig=plt.gcf()
fig.set_size_inches(3.75,3.75)#14, 23)
plt.savefig('testfig.png',dpi=300)

When using Ipython (via Spyder), the plot presents ok. However when I looked at the saved image, it presents thus:

enter image description here

As you can see, the text is cut off. What is recommended practice for dealing with this?

I have got round it by increasing the figure size, and re-sizing afterwards. However, my aim is to produce a set of images with a consistent text size (figure size varies); so this approach is not ideal.

Note. Whilst a similar question exists, this question is distinct in that it:

  • deals with both xlabel and ylabel.
  • combines with set_size_inchesfunction
  • seeks to ensure consistent text size with differing figure sizes.
  • seeks to find out why Ipython output differs from savefig
like image 416
atomh33ls Avatar asked Jul 21 '17 13:07

atomh33ls


3 Answers

The Ipython console in Spyder uses the inline backend, which saves the figure as png and displays the output image. When saving, it uses the option bbox_inches = "tight".

So in order to obtain the same figure as shown in the console, you may decide to use this option as well - it basically extends or shrinks the bounding box such that all objects in the canvas are displayed.

plt.savefig('testfig.png',dpi=300, bbox_inches = "tight")

Alternatively, you can make sure that all objects are already inside the figure boundaries before saving or showing the figure. This can either be accomplished using

plt.tight_layout()

which tries to do that automatically, or you can use

plt.subplots_adjust(left=0.3, right=0.9, bottom=0.3, top=0.9)

where the parameters denote the margins on each side in units of fractions of figure size (30% space on the left, 10% space on the right, etc.).

like image 65
ImportanceOfBeingErnest Avatar answered Nov 14 '22 16:11

ImportanceOfBeingErnest


matplotlib has a function called tight_layout , which automatically adjusts subplot params so that the subplot(s) fits in to the figure area.

As stated in the docs, it's flagged as experimental, but is commonly used.

In my experience it should be called as late as possible (e.g. before using savefig) and probably after calls which change the geometry (like fig.set_size_inches).

In the plt.show() gui-window, one of the buttons is doing exactly this call too.

(converted to answer from earlier comment)

like image 44
sascha Avatar answered Nov 14 '22 17:11

sascha


I think the answer is given elsewhere on stackoverflow. Briefly, you should chane the fontsize of your label-text:

plt.ylabel('Example', fontsize=40)
plt.xlabel('Example', fontsize=40)

Of course, change the number 40 (trial and error) to a more suitable value.

I don't know if this is a fix or a work-around. And neither do I know if this helps.

like image 1
Ramon van der Werf Avatar answered Nov 14 '22 16:11

Ramon van der Werf