私はここ数日でNumpyとmatplotlibで遊んでいます。 matplotlibで実行をブロックせずに関数をプロットしようとすると問題が発生します。 SOには同様の質問をするスレッドがすでにたくさんあります。私はかなりグーグルで検索しましたが、うまくいかないことがあります。
一部の人が示唆するように、show(block = False)を使用しようとしましたが、表示されるのはフリーズウィンドウだけです。単純にshow()を呼び出すと、結果は適切にプロットされますが、ウィンドウが閉じるまで実行はブロックされます。私が読んだ他のスレッドから、show(block = False)が機能するかどうかはバックエンドに依存しているのではないかと考えています。これは正しいです?私のバックエンドはQt4Aggです。私のコードを見て、何かおかしいと思ったら教えてください。これが私のコードです。助けてくれてありがとう。
from math import *
from matplotlib import pyplot as plt
print plt.get_backend()
def main():
x = range(-50, 51, 1)
for pow in range(1,5): # plot x^1, x^2, ..., x^4
y = [Xi**pow for Xi in x]
print y
plt.plot(x, y)
plt.draw()
#plt.show() #this plots correctly, but blocks execution.
plt.show(block=False) #this creates an empty frozen window.
_ = raw_input("Press [enter] to continue.")
if __== '__main__':
main()
PS。新しいウィンドウを作成するのではなく、何かをプロットするたびに既存のウィンドウを更新したいということを忘れていました。
私は解決策を探すのに長い時間を費やし、 この答え を見つけました。
あなた(そして私)が望むものを得るためには、plt.ion()
、plt.show()
(blocking=False
ではなく、非推奨です)、そして最も重要なこととしてplt.pause(.001)
(またはあなたが望む時間)の組み合わせが必要です。 pause は、描画を含むメインコードがスリープしている間にGUIイベントが発生するために必要です。これは、スリープ状態のスレッドから時間を取得することで実装される可能性があるため、IDEがそれを混乱させる可能性があります。
python 3.5で動作する実装を次に示します。
import numpy as np
from matplotlib import pyplot as plt
def main():
plt.axis([-50,50,0,10000])
plt.ion()
plt.show()
x = np.arange(-50, 51)
for pow in range(1,5): # plot x^1, x^2, ..., x^4
y = [Xi**pow for Xi in x]
plt.plot(x, y)
plt.draw()
plt.pause(0.001)
input("Press [enter] to continue.")
if __== '__main__':
main()
私のために働く簡単なトリックは次のとおりです:
例:
import matplotlib.pyplot as plt
plt.imshow(add_something)
plt.xlabel("x")
plt.ylabel("y")
plt.show(block=False)
#more code here (e.g. do calculations and use print to see them on the screen
plt.show()
注:plt.show()
は、スクリプトの最終行です。
プロットを配列に書き込み、別のスレッドで配列を表示することにより、実行のブロックを回避できます。 pyformulas 0.2.8 のpf.screenを使用して、プロットを同時に生成および表示する例を次に示します。
import pyformulas as pf
import matplotlib.pyplot as plt
import numpy as np
import time
fig = plt.figure()
canvas = np.zeros((480,640))
screen = pf.screen(canvas, 'Sinusoid')
start = time.time()
while True:
now = time.time() - start
x = np.linspace(now-2, now, 100)
y = np.sin(2*np.pi*x) + np.sin(3*np.pi*x)
plt.xlim(now-2,now+1)
plt.ylim(-3,3)
plt.plot(x, y, c='black')
# If we haven't already shown or saved the plot, then we need to draw the figure first...
fig.canvas.draw()
image = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='')
image = image.reshape(fig.canvas.get_width_height()[::-1] + (3,))
screen.update(image)
#screen.close()
結果:
免責事項:私はpyformulasのメンテナーです。
リファレンス: Matplotlib:プロットをnumpy配列に保存
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2 * np.pi, 100)
# plt.axis([x[0], x[-1], -1, 1]) # disable autoscaling
for point in x:
plt.plot(point, np.sin(2 * point), '.', color='b')
plt.draw()
plt.pause(0.01)
# plt.clf() # clear the current figure
データ量が多すぎる場合は、単純なカウンターで更新レートを下げることができます
cnt += 1
if (cnt == 10): # update plot each 10 points
plt.draw()
plt.pause(0.01)
cnt = 0
これは満足のいく答えを見つけることができなかった私の実際の問題でした。スクリプトが終了した後(MATLABのように)閉じないプロットを望んでいました。
考えてみると、スクリプトが終了した後、プログラムは終了し、このようにプロットを保持する論理的な方法がないため、2つのオプションがあります。
これは私にとって満足のいくものではなかったので、箱の外で別の解決策を見つけました
このため、保存と表示は高速で、視聴者はファイルをロックせず、コンテンツを自動的に更新する必要があります
ベクトルベースのフォーマットは小さくて高速です
PDFには、いくつかの適切なオプションがあります
Windowsでは SumatraPDF を使用します。これは無料、高速、軽量です(私の場合は1.8MB RAMのみを使用します)
プロットをファイルに出力するためのサンプルコード
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2 * np.pi, 100)
y = np.sin(2 * x)
plt.plot(x, y)
plt.savefig("fig.pdf")
最初に実行した後、上記のいずれかのビューアで出力ファイルを開いて楽しんでください。
これはSumatraPDFと一緒のVSCodeのスクリーンショットです。また、プロセスはセミライブ更新レートを取得するのに十分高速です(間隔でtime.sleep()
を使用するだけでセットアップで10Hzに近づくことができます)
Iggyの答え は私にとって最も簡単でしたが、その後subplot
を実行していたときに存在しなかったshow
コマンドを実行すると、次のエラーが発生しました。
MatplotlibDeprecationWarning:以前の軸と同じ引数を使用して軸を追加すると、現在、以前のインスタンスが再利用されます。将来のバージョンでは、新しいインスタンスが常に作成されて返されます。一方、各軸インスタンスに一意のラベルを渡すことにより、この警告を抑制し、将来の動作を保証できます。
このエラーを回避するには、ユーザーがEnterキーを押した後にプロットを閉じる(または clear )と役立ちます。
私のために働いたコードは次のとおりです:
def plt_show():
'''Text-blocking version of plt.show()
Use this instead of plt.show()'''
plt.draw()
plt.pause(0.001)
input("Press enter to continue...")
plt.close()
これらの答えの多くは非常に膨らんでおり、私が見つけることができるものから、答えはそれほど難しくありません。
必要に応じてplt.ion()
を使用できますが、plt.draw()
を使用しても効果的であることがわかりました
私の特定のプロジェクトでは、画像をプロットしていますが、plot()
の代わりにscatter()
やfigimage()
などを使用できますが、それは問題ではありません。
plt.figimage(image_to_show)
plt.draw()
plt.pause(0.001)
または
fig = plt.figure()
...
fig.figimage(image_to_show)
fig.canvas.draw()
plt.pause(0.001)
実際の図を使用している場合。
@ krs013と@Default Pictureの回答を使用してこれを把握しました
これにより、誰かが個別のスレッドですべての図を起動したり、これを理解するためだけにこれらの小説を読む必要がなくなります。
Pythonパッケージdrawnowを使用すると、非ブロッキング方式でリアルタイムにプロットを更新できます。
また、ウェブカメラやOpenCVと連携して、たとえば各フレームの測定値をプロットします。
元の投稿 を参照してください。