Matplotlib - Force plot display and then return to main code
Asked Answered
G

4

25

This is a MWE of what I'm after, adapted from this question:

from matplotlib.pyplot import plot, draw, show

def make_plot():
    plot([1,2,3])
    draw()
    print 'continue computation'

print('Do something before plotting.')
# Now display plot in a window
make_plot()

answer = raw_input('Back to main and window visible? ')
if answer == 'y':
    print('Excellent')
else:
    print('Nope')

show()

What I want is: I call the function to make the plot, the plot window appears, and then I get to go back to the prompt so I can input some value (based on that image that just displayed) and carry on with the code (the window can then close or remain there, I don't care).

What I get instead is that the window with the plot only appears after the code is completed, which is no good.


Add 1

I've tried the following with the same results, the plot window appears at the end of the code and not before:

from matplotlib.pyplot import plot, ion, draw

ion() # enables interactive mode
plot([1,2,3]) # result shows immediately (implicit draw())
# at the end call show to ensure window won't close.
draw()

answer = raw_input('Back to main and window visible? ')
if answer == 'y':
    print('Excellent')
else:
    print('Nope')

The same happens if I change draw() for show().


Add 2

I've tried the following approach:

from multiprocessing import Process
from matplotlib.pyplot import plot, show

def plot_graph(*args):
    for data in args:
        plot(data)
    show()

p = Process(target=plot_graph, args=([1, 2, 3],))
p.start()

print 'computation continues...'

print 'Now lets wait for the graph be closed to continue...:'
p.join()

which results in a Python kernel has crashed error in Canopy with the message:

The kernel (user Python environment) has terminated with error code -6. This may be due to a bug in your code or in the kernel itself.

Output captured from the kernel process is shown below.

[IPKernelApp] To connect another client to this kernel, use:
[IPKernelApp] --existing /tmp/tmp9cshhw.json
QGtkStyle could not resolve GTK. Make sure you have installed the proper libraries.
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
python: ../../src/xcb_io.c:274: poll_for_event: La declaración `!xcb_xlib_threads_sequence_lost' no se cumple.

I should mention I'm running Canopy in elementary OS which is based in Ubuntu 12.04.


Add 3

Also tried solution posted in this question:

import numpy
from matplotlib import pyplot as plt

if __name__ == '__main__':
    x = [1, 2, 3]
    plt.ion() # turn on interactive mode
    for loop in range(0,3):
        y = numpy.dot(x, loop)
        plt.figure()
        plt.plot(x,y)
        plt.show()
        _ = raw_input("Press [enter] to continue.")

This displays empty plot windows as the code advances (ie: the user hits [enter]) and only displays the images after the code is finished.

This solution (also in the same question) doesn't even display the plot windows:

import numpy
from matplotlib import pyplot as plt
if __name__ == '__main__':
    x = [1, 2, 3]
    plt.ion() # turn on interactive mode, non-blocking `show`
    for loop in range(0,3):
        y = numpy.dot(x, loop)
        plt.figure()   # create a new figure
        plt.plot(x,y)  # plot the figure
        plt.show()     # show the figure, non-blocking
        _ = raw_input("Press [enter] to continue.") # wait for input from the user
        plt.close()    # close the figure to show the next one.
Godmother answered 17/6, 2013 at 14:10 Comment(0)
E
28

You may use plt.show(block=False), which gets rid of the blocking directly.

For your example, this could read

from matplotlib.pyplot import plot, show

def make_plot():
    plot([1,2,3])
    show(block=False)
    print('continue computation')

print('Do something before plotting.')
# Now display plot in a window
make_plot()

answer = input('Back to main and window visible? ')
if answer == 'y':
    print('Excellent')
else:
    print('Nope')
Election answered 17/6, 2013 at 14:24 Comment(9)
This example doesn't work in my case, the plot window still appears after the code is done and not before I ask for the answer input. Perhaps it has something to do with my IDE (Enthought's Canopy v 1.0.1.1190)?Godmother
Ohh yeah, this feature was only added in recent matplotlib version. It works for me under matplotlib 1.2. Do you have any chance of updating?Election
Matplotlib 1.2 is available in the Canopy package manager. This example works for me in that context on OSX-64. The window is visible though not on top... have to use the OSX "Mission Control" to reveal it, and it is unresponsive.Burrstone
That is indeed inconvenient. Does it perhaps work with a different backend? Such things tend to be backend-specific.Election
So it's a no go with Canopy? Should I try with a different IDE?Godmother
I don't know much about Canopy, but you may just try a different backend by import matplotlib and matplotlib.use('GTKAgg') or any of the other backends to see whether it works. Note that these two lines should go before importing any other plotting related stuff.Election
@DavidZwicker would you mind expanding a bit on what you mean by try a different backend? I'm pretty new to Python, sorry.Godmother
Here is the help from matplotlib itself: matplotlib.org/faq/usage_faq.html#what-is-a-backend Googling matplotlib backend will also point to useful threads like this: #4931024Election
Late answer but sadly none of the backends worked. I'm baffled as to how it can be possible that python doesn't allow to show a plot before ending...Godmother
G
14

None of the presented solutions work for me. I tested them with three different IDEs PyCharm, Spyder and Pyzo, using the (currently) latest Matplotlib 2.1 under Python 3.6.

What works for me, although not optimal, is to use a plt.pause command:

import matplotlib.pyplot as plt

def make_plot():
    plt.plot([1, 2, 3])
#    plt.show(block=False)  # The plot does not appear.
#    plt.draw()             # The plot does not appear.
    plt.pause(0.1)          # The plot properly appears.
    print('continue computation')

print('Do something before plotting.')
# Now display plot in a window
make_plot()

answer = input('Back to main and window visible? ')
if answer == 'y':
    print('Excellent')
else:
    print('Nope')
Gummosis answered 31/10, 2017 at 15:7 Comment(4)
Thank you! I know this is old, but I could not get any other solution to work, except this, and this so simple.Hath
I had to increase the time as I had a lot of lines to display, but this is the only solution I've found yet that works :-)Arundell
I gave up on this problem a long time ago, but just tried your answer and it works, thanks for that.Immoderacy
Doesn't work with pause 0.1 for me. I have to increase to 0.5 which means I have to wait for a long time for the plot to appear... but at least it works.Godewyn
G
1

I couldn't get this to work with Canopy (not yet at least) but I could get the code to run sort of like I wanted to using the Geany IDE. This is the code that works for me, it's a very minor modification to the first block of code in the question where the show() command is moved above from the end of the file to just below the make_plot() command:

from matplotlib.pyplot import plot, draw, show

def make_plot():
    plot([1,2,3])
    draw()
    print 'Plot displayed, waiting for it to be closed.'

print('Do something before plotting.')
# Now display plot in a window
make_plot()
# This line was moved up <----
show()

answer = raw_input('Back to main after plot window closed? ')
if answer == 'y':
    print('Move on')
else:
    print('Nope')

It doesn't do exactly what I want but it's close enough: it shows a plot to the user, waits till that plot window is closed and then moves on with the code. Ideally it shouldn't have to wait until the plot window is closed to move on with the code, but it's better than nothing I guess.

The code in the Add 2 section above also works in the same way and with no modifications needed in Geany, but I prefer this one because it's simpler. I'll update this answer If (when?) I get this to work with Canopy.

Godmother answered 14/7, 2013 at 15:17 Comment(0)
R
0

this works for me, although not optimal. #!/usr/bin/env python3

import matplotlib.pyplot as plt

def make_plot():
    plt.plot([1, 2, 3])
    plt.show(block=False)
    input('Back to main and window visible? ') #Here is the trick
    print('continue computation')

print('Do something before plotting.')
# Now display plot in a window
make_plot()


answer = input('Quit now ?')
if answer == 'y':
    print('Excellent')
else:
    print('Nope')
Royalroyalist answered 18/9, 2023 at 8:23 Comment(2)
Are you trying to ask a new question or provide a solution to the existing question? If you want to ask a new question please create a question.Waxwing
Please create a new question with your concerns, do not post it as an answer to another question!Barns

© 2022 - 2024 — McMap. All rights reserved.