Maximize figures before saving

Robyc Source

The question about how to do maximize a window before saving has been asked several times and has several questions (still no one is portable, though), How to maximize a plt.show() window using Python and How do you change the size of figures drawn with matplotlib?

I created a small function to maximize a figure window before saving the plots. It works with QT5Agg backend.

import matplotlib.pyplot as plt
def maximize_figure_window(figures=None, tight=True):
    """
    Maximize all the open figure windows or the ones indicated in figures

    Parameters
    ----------

    figures: (list) figure numbers
    tight  : (bool) if True, applies the tight_layout option

    :return:
    """
    if figures is None:
        figures = plt.get_fignums()
    for fig in figures:
        plt.figure(fig)
        manager = plt.get_current_fig_manager()
        manager.window.showMaximized()
        if tight is True:
            plt.tight_layout()

Problems:

  1. I have to wait for the windows to be actually maximized before using the plt.savefig() command, otherwise it is saved with as not maximized. This is a problem if I simply want to use the above function in a script

(minor problems:)
2. I have to use the above function twice in order to get the tight_layout option working, i.e. the first time tight=True has no effect.

  1. The solution is not portable. Of course I can add all the possible backend I might use, but that's kind of ugly.

Questions:

  1. how to make the script wait for the windows to be maximized? I don't want to use time.sleep(tot_seconds) because tot_seconds would be kind of arbitrary and makes the function even less portable
  2. how to solve problem 2 ? I guess it is related to problem 1.
  3. is there a portable solution to "maximize all the open windows" problem?

-- Edit --

For problem 3. @DavidG suggestion sounds good. I use tkinter to automatically get width and height, convert them to inches, and use them in fig.set_size_inches or directly during the figure creation via fig = plt.figure(figsize=(width, height)).

So a more portable solution is, for example. import tkinter as tk import matplotlib.pyplot as plt

def maximize_figure(figure=None):
    root = tk.Tk()
    width = root.winfo_screenmmwidth() / 25.4
    height = root.winfo_screenmmheight() / 25.4
    if figure is not None:
        plt.figure(figure).set_size_inches(width, height)
    return width, height

where I allow the figure to be None so that I can use the function to just retrieve width and height and use them later.

Problem 1 is still there, though.
I use maximize_figure() in a plot function that I created (let's say my_plot_func()) but still the saved figure doesn't have the right dimensions when saved on file. I also tried with time.sleep(5) in my_plot_func() right after the figure creation. Not working.

It works only if a manually run in the console maximize_figure() and then run my_plot_func(figure=maximized_figure) with the figure already maximized. Which means that dimension calculation and saving parameters are correct. It does not work if I run in the console maximize_figure() and my_plot_func(figure=maximized_figure) altogether, i.e. with one call the the console! I really don't get why.

I also tried with a non-interactive backend like 'Agg', so that the figure doesn't get actually created on screen. Not working (wrong dimensions) no matter if I call the functions altogether or one after the other.

To summarize and clarify (problem 1):
by running these two pieces of code in console, figure gets saved correctly.

plt.close('all')
plt.switch_backend('Qt5Agg')
fig = plt.figure()
w, h = maximize_figure(fig.number)

followed by:
my_plot_func(out_file='filename.eps', figure=fig.number)

by running them together (like it would be in a script) figure is not saved correctly.

 plt.close('all')
 plt.switch_backend('Qt5Agg')
 fig = plt.figure()
 w, h = maximize_figure(fig.number)
 my_plot_func(out_file='filename.eps', figure=fig.number)

Using

plt.switch_backend('Agg') 

instead of

plt.switch_backend('Qt5Agg')

it does not work in both cases.

python-3.xmatplotlib

Answers

comments powered by Disqus