Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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()?

like image 676
Jan Spurny Avatar asked Jun 22 '16 12:06

Jan Spurny


People also ask

What does show () do in Matplotlib?

If you are using Matplotlib from within a script, the function plt. show() is your friend. plt. show() starts an event loop, looks for all currently active figure objects, and opens one or more interactive windows that display your figure or figures.

What does PLT Tight_layout () do?

tight_layout automatically adjusts subplot params so that the subplot(s) fits in to the figure area. This is an experimental feature and may not work for some cases. It only checks the extents of ticklabels, axis labels, and titles.

How do you apply tight layout?

All tight_layout does is calculate parameters for subplots_adjust , so tight_layout only works with subplots. Use fig, ax = plt. subplots() or ax = fig. add_subplot(1,1,1) instead of specifying the extent of the axes manually and it should work fine.


1 Answers

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, i.e. if you would have called fig.canvas.draw().

like image 170
Thomas Kühn Avatar answered Oct 13 '22 02:10

Thomas Kühn