10

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

2
  • 2
    I'd like to know as well. Commented Sep 13, 2017 at 22:18
  • 1
    @user1350191 Thomas's answer below worked for me... Commented Dec 16, 2017 at 14:12

2 Answers 2

10

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

Sign up to request clarification or add additional context in comments.

Comments

-1

`layout` parameter of `plt.figure` can be used for this purpose.

for instance, following example dynamically adjusts the layout to stay tight after window is resized.

import matplotlib.pyplot as plt

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

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

plt.show()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.