web-dev-qa-db-fra.com

Matplotlib - Forcer l'affichage du tracé puis revenir au code principal

Ceci est un MWE de ce que je recherche, adapté de cette 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()

Ce que je veux, c'est: j'appelle la fonction pour faire l'intrigue, la fenêtre de l'intrigue apparaît, puis je reviens à l'invite pour pouvoir entrer une valeur (basée sur cette image qui vient d'être affichée) et continuer avec le code (la fenêtre peut alors se fermer ou y rester, je m'en fiche).

Ce que j'obtiens à la place, c'est que la fenêtre avec l'intrigue n'apparaît qu'après le code est terminé, ce qui n'est pas bon.


Ajouter 1

J'ai essayé ce qui suit avec les mêmes résultats, la fenêtre de tracé apparaît à la fin du code et pas avant:

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')

La même chose se produit si je change draw() pour show().


Ajouter 2

J'ai essayé l'approche suivante:

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

ce qui entraîne une erreur Python kernel has crashed dans Canopy avec le 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.

Je dois mentionner que j'exécute Canopy dans elementary OS Qui est basé sur Ubuntu 12.04.


Ajouter 3

Solution également essayée publiée dans cette 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.")

Cela affiche des fenêtres de tracé vides à mesure que le code avance (c'est-à-dire: l'utilisateur frappe [entrée]) et n'affiche les images qu'une fois le code terminé.

Cette solution (également dans la même question) n'affiche même pas les fenêtres de tracé:

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.
18
Gabriel

Vous pouvez utiliser plt.show(block=False), qui supprime directement le blocage.

Pour votre exemple, cela pourrait lire

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')
24
David Zwicker

Aucune des solutions présentées ne fonctionne pour moi. Je les ai testés avec trois IDE différents PyCharm , Spyder et Pyzo , en utilisant le (actuellement) dernier Matplotlib 2.1 sous Python 3.6.

Ce qui fonctionne pour moi, bien que pas optimal, est d'utiliser un plt.pause commande:

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')
8
divenex

Je ne pouvais pas faire fonctionner cela avec Canopy (pas encore au moins), mais je pouvais obtenir que le code s'exécute un peu comme je voulais utiliser l'IDE Geany. C'est le code qui fonctionne pour moi, c'est une modification très mineure du premier bloc de code dans la question où la commande show() est déplacée au-dessus de la fin du fichier vers juste en dessous de la fonction make_plot() commande:

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')

Il ne fait pas exactement ce que je veux mais il est assez proche: il montre un tracé à l'utilisateur, attend que cette fenêtre de tracé soit fermée, puis passe au code. Idéalement, il ne devrait pas avoir à attendre que la fenêtre de traçage soit fermée pour passer au code, mais c'est mieux que rien, je suppose.

Le code dans la section Add 2 ci-dessus fonctionne également de la même manière et sans aucune modification nécessaire dans Geany, mais je préfère celui-ci car il est plus simple. Je mettrai à jour cette réponse Si (quand?) Je fais fonctionner cela avec Canopy.

1
Gabriel