简体   繁体   中英

Show multiple Matplotlib figures by calling a function multiple times?

The following code does not do what I want: it shows a figure, waits for the user to close the window, then shows a second figure.

def my_plot(arr_x, arr_y):
    import matplotlib.pyplot as plt
    plt.plot(arr_x, arr_y)
    plt.show()

if __name__ == '__main__':
    my_plot((1, 2, 3), (10, 20, 90))
    my_plot((101, 102, 103), (1, 5, 4))

I would like to have the two figures displayed simultaneously, so I could visually compare them, then eg choose one and close the other. My requirement is to store all Matplotlib calls in just one user-defined function such as my_plot .

I have read that show has to be called after all plots have been defined, which does not fit the above requirement.

Actually I am almost losing hope that Matplotlib can do that by itself, perhaps the only solution is something like using a new thread for each call of my_plot ?


EDIT:
Problem solved. I hereunder share a function I wrote thanks to Nieznany's answer, that does exactly what I want. Of course it's improvable, but for most of my use cases it works and I can happily forget about Matplotlib.

#!/usr/bin/env python
import matplotlib.pyplot as plt
from os.path import splitext

def plot_XY(arr_x, arr_y, graph_file_name=None, graph_title="", x_label="", y_label=""):
    """Plot a series of (x, y) points.

    If graph_file_name is not provided, the graph is
    plotted in a temporary window; else, the file
    format is deduced from the extension contained
    in graph_file_name.
    """

    def create_figure():
        plt.figure()
        plt.plot(arr_x, arr_y)
        plt.title(graph_title)
        plt.xlabel(x_label)
        plt.ylabel(y_label)

    if graph_file_name is None:
        def my_show():
            create_figure()
            plt.show()
        from multiprocessing import Process
        Process(target=my_show, args=[]).start()
    else:
        extension = splitext(graph_file_name)[1][1:] # Get extension, without dot
        if extension not in ("eps", "pdf", "pgf", "png", "ps", "raw", "rgba", "svg", "svgz"):
            print(f"\"{extension}\" is not a file extension recognized by savefig. Assuming png.")
            extension = "png"
            graph_file_name += "." + extension
        create_figure()
        plt.savefig(graph_file_name, format=extension)
        plt.close()

if __name__ == '__main__':
    # Test: calling the function multiple times:
    x = (1, 2, 3)
    plot_XY(x, (1, 4, 2), graph_title="Example")
    plot_XY(x, (2, 3, 1), graph_file_name="output.abc")
    plot_XY(x, (1, 4, 9), x_label="x", y_label="x^2")

You can use individual process to plot a window and show it without blocking main process.
Example solution:

def my_plot(arr_x, arr_y):
    import matplotlib.pyplot as plt
    from multiprocessing import Process
    def _my_plot(arr_x, arr_y):

        plt.figure()
        plt.plot(arr_x, arr_y)
        plt.show()

    Process(target=_my_plot, args=[arr_x,arr_y]).start()

if __name__ == '__main__':
    my_plot((1, 2, 3), (10, 20, 90))
    my_plot((101, 102, 103), (1, 5, 4))

Resources

Call plt.show() once you've created all figures.

import matplotlib.pyplot as plt

def my_plot(arr_x, arr_y):
    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1)
    ax.plot(arr_x, arr_y)
    return fig

if __name__ == '__main__':
    f1 = my_plot((1, 2, 3), (10, 20, 90))
    f2 = my_plot((101, 102, 103), (1, 5, 4))
    plt.show()

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