简体   繁体   中英

How to set tight_layout for matplotlib graphs after show()

My setup:

Debian Linux 8.3 amd64, XMonad WM, python2.7, matplotlib 1.5.1

Problem:

I'm making a plot, for example:

import matplotlib.pyplot as plt

x = xrange(10)
y1 = [i ** 2 for i in x]
y2 = [1.0 / (i + 1) for i in x]

fig = plt.figure()
ax1 = plt.subplot(1, 2, 1)
ax1.plot(x, y1)
ax2 = plt.subplot(1, 2, 2)
ax2.plot(x, y2)

plt.show()

and since I'm using tiling window manager, the matplotlib's window gets stretched to a tile. Unfortunately this makes the graphs small and layout somewhat loose.

If I want to "tighten" it a litte bit, clicking "Configure subplots->Tight Layout" does the job. But this means I have to click on the icon and then on the button every time and since I use this plot to display testing data and run it very often, it's quite annoying. So I tried a few things to make this easier:

What have I tried:

  • calling plt.tight_layout() before show() :

     ... ax2.plot(x, y2) plt.tight_layout() plt.show() 
  • adding keypress handler (so I would just press "t"):

     ... ax2.plot(x, y2) def kbd_handler(event): if event.key == 't': plt.tight_layout() plt.gcf().canvas.mpl_connect('key_press_event', kbd_handler) plt.show() 
  • calling tight_layout on figure:

     ax2.plot(x, y2) fig.tight_layout() plt.show() 

It all changed nothing or at least it looked the same for 2 subplots in one row, however for more than one row, it made the layout even more loose and all subplots extremely small.

What I suspect:

I believe the problem is related to resize which probably happens after the window is created, so the tighten_layout works with original window dimensions. When the Window Manager resizes the window, the layout keeps the subplot sizes and I have a "loose" layout with miniature graphs..

The question

Is there a way to automaticaly (or very easily - like using a key_press_event) tighten the layout even when the window gets resized immediately after calling plt.show() ?

You can achieve what you want with the help of Matplotlib event handling . Just write a small function that calls tight_layout and updates the figure every time the figure is resized:

from matplotlib import pyplot as plt
import numpy as np

x = np.linspace(0,np.pi,100)
y1 = np.sin(x)
y2 = np.cos(x)
fig, (ax1,ax2) = plt.subplots(nrows=1, ncols=2)
fig.tight_layout()
ax1.plot(x,y1)
ax2.plot(x,y2)

def on_resize(event):
    fig.tight_layout()
    fig.canvas.draw()

cid = fig.canvas.mpl_connect('resize_event', on_resize)

plt.show()

There is of course a small chance that this is system or version dependent. I verified the above example on MacOS Sierra with Python 3.5.4 (Matplotlib 2.0.2) and with Python 2.7.14 (Matplotlib 2.1.0). Hope this helps.

EDIT :

In fact, I think your keypress handler would have worked if you would have updated the figure after tight_layout , ie if you would have called fig.canvas.draw() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM