機械系エンジニアの備忘録

20代独身社会人。仕事では機械・機構の研究開発を行っているエンジニアが、自分の専門分野ではないpythonを扱って楽しむブログです。

MENU

【python】グラフの変化をアニメーションで(動的に)表示してGIF画像で保存する

tkinterとmatplotlibとPillowを使って、tkinterで作成したウインド上のグラフにアニメーションを付ける。またそのアニメーションをgif画像として保存する。

1. 誰に向けた記事か

pythontkinterを勉強してる人

pythonで変数を変化した時のグラフの変化を、アニメーションで表示させたい人

・上記アニメーションをGIF画像として保存したい方

 

2. はじめに

これまでmatplotlibを使ってグラフを作成する方法を紹介しました。

stjun.hatenablog.com

stjun.hatenablog.com

stjun.hatenablog.com

 

またtkinterと組み合わせて別ウインドでグラフを表示させる方法も紹介しました。

stjun.hatenablog.com

 


今回はこれらmatplotlibとtkinterとpillowを組み合わせて、tkinterのウインド上にグラフの変化をアニメーションで表示し、それをgif画像で保存してみたいと思います。 

また作成するために以下公式HPを参考にしました。

https://matplotlib.org/gallery/animation/simple_anim.html

 

3. コード・実行結果

3.1 コード
import tkinter as tk
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg, NavigationToolbar2Tk)
import numpy as np
import matplotlib.animation as ani
    
root = tk.Tk()#ウインドの作成
root.title("pid soft")#ウインドのタイトル
root.geometry("800x700") #ウインドの大きさ

fig = plt.Figure() #描画の用意
x = np.arange(0, 2*np.pi, 0.01)   #x軸のデータ
ax = fig.add_subplot(111) 
ax.set_ylabel("sin / mm")#y軸のラベル
ax.set_ylim(-1,1)
ax.set_xlim(-1,1)
ax.set_xlabel("x / mm")#x軸のラベル
line, =ax.plot(np.cos(x),np.sin(x))   

def animate(i):
    line.set_ydata(np.sin(x + i/2)) 
    line.set_xdata(np.cos(x + i))
    frame=f"{i:.2f}"
    ax.set_title('frames= '+str(frame))
    return line,

#tkinterのウインド上部にグラフを表示する
canvas = FigureCanvasTkAgg(fig, master=root)
movie= ani.FuncAnimation(fig, animate,interval=10,frames=np.arange(0,2*np.pi,0.1))
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)

#tkinterのウインド下部にツールを追加する
toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)

movie.save("animation_test.gif",writer='pillow')

root.mainloop()

今回は円⇒楕円⇒線⇒楕円⇒円のアニメーションを行います。

 

3.2 実行結果

実行すると以下のアニメーションが表示されます。

f:id:stjun:20200112160331g:plain

このようにtkinterのウインド上にグラフのアニメーションが表示されます。

またgif画像が自動でコードファイルと同じ場所に保存されます。

f:id:stjun:20200112160521p:plain

 

■買って良かった本を紹介

1. はじめての人のための3000円投資生活

はじめての人のための3000円投資生活

はじめての人のための3000円投資生活

  • 作者:横山光昭
  • 出版社/メーカー: アスコム
  • 発売日: 2016/06/24
  • メディア: 単行本(ソフトカバー)
 

最近、株に興味がありますが「投資信託って何?」ってレベルだったので読んでみました。この本を読んで投資信託の概要を理解しました。

 

2. 難しいことはわかりませんが、お金の増やし方を教えてください!

 次に「どうやって始めるか?口座はどこで開設するか?」など具体的なアクションを起こすためにこの本を読み増した。ど素人の著者が口座や銘柄を選ぶ過程が詳しく書いてるので非常に分かりやすかったです。

 

3. ニートの歩き方

ニートの歩き方 ――お金がなくても楽しく暮らすためのインターネット活用法

ニートの歩き方 ――お金がなくても楽しく暮らすためのインターネット活用法

  • 作者:pha
  • 出版社/メーカー: 技術評論社
  • 発売日: 2012/08/03
  • メディア: 単行本(ソフトカバー)
 

仕事でめちゃくちゃメンタルやられてる時に、 テレビでphaさんを知り、その考え方に興味が沸いたので読んでみました。これまで「ニート最高!ニートこそなるべき」みたいな考え方が苦手でしたが、この著者は「お金がないと確かにできないことは多いし諦めなきゃいけないことは多い。けど死にはしないし工夫次第で楽しめるよ」っていうゆるいスタンスなので好きです。仕事に苦しんでる人はぜひ読んでみて下さい。

 

4. すべてはモテるためである

すべてはモテるためである (文庫ぎんが堂)

すべてはモテるためである (文庫ぎんが堂)

 

 この本は人におすすめされて読みました。非常に面白かったです。

題目だけ見るとモテるためのhow to本のように見えますが実際は全然違いました。「なぜモテる必要があるのか」「それが人生の幸せなのか」というような広い視点から論じている本です。若いころはあまりピンとこなかったですが、社会人になって、結婚を考えていた恋人と別れて読み返したときにすごく考えさせられました。

 

5. アイデアの作り方

アイデアのつくり方

アイデアのつくり方

 

古い本で中古しかありませんが私が大事に持ち続けている本の1つです。私は仕事で研究職をしていますが、アイデアが生まれるときはまさにこの本に書かれたプロセスと同じです。この本を読むとアイデアを作るプロセスは今も昔も変わらないんだなと思います。情報を集め、自分の中で考えて考えて腹落ちさせ、そこまですると帰宅時やお風呂でふと閃くというプロセスです。とても良い本なのでぜひ読んでみて下さい。

 

6. 伝わるデザインの基本

 この本は言わずと知れた名著です。おそらく理系に進んだ人の多くは、学会や卒論・修論発表等でどうやって資料を作れば良いか悩んだ末にこの本を手に取ったと思います。私もパワポ作成が苦手でしたがこの本を読み解決しました。

 

 

4.  説明

4.1 必要なモジュールのimportとウインドとグラフの用意
import tkinter as tk
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg, NavigationToolbar2Tk)
import numpy as np
import matplotlib.animation as ani
    
root = tk.Tk()#ウインドの作成
root.title("pid soft")#ウインドのタイトル
root.geometry("800x700") #ウインドの大きさ

fig = plt.Figure() #描画の用意
x = np.arange(0, 2*np.pi, 0.01)   #x軸のデータ
ax = fig.add_subplot(111) 
ax.set_ylabel("sin / mm")#y軸のラベル
ax.set_ylim(-1,1)
ax.set_xlim(-1,1)
ax.set_xlabel("x / mm")#x軸のラベル
line, =ax.plot(np.cos(x),np.sin(x)) 

上記コード部分はウインドの用意とグラフの用意になります。

円なのでx軸をcos(x)、y軸をsin(x)としてlineという名前で定義しています。

 

4.2 アニメーション部分
def animate(i):
    line.set_ydata(np.sin(x + i/2)) 
    line.set_xdata(np.cos(x + i))
    frame=f"{i:.2f}"
    ax.set_title('frames= '+str(frame))
    return line,

#tkinterのウインド上部にグラフを表示する
canvas = FigureCanvasTkAgg(fig, master=root)
movie= ani.FuncAnimation(fig, animate,interval=10,frames=np.arange(0,2*np.pi,0.1))
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)

まずanimate関数の中ですが

まず1~2行目は、先ほど定義したlineのx軸をiだけ、y軸をi / 2ずつ更新しています。

(※どちらもiずつ更新するとずっと円のままで楕円にならになので、y軸の値だけi/2として遅らせています。)

 

次の3~4行目は、グラフのタイトルに何フレーム目かを表示する際に見やすくするために、浮動小数点iを小数点第二位まで表示するようにして、タイトルを更新しているだけです。この行は無くても問題ありません。

frame=f"{i:.2f}"
ax.set_title('frames= '+str(frame))

最後の5行目、

return line,

で結果を返します。

 

次にアニメーション部分になります。

movie= ani.FuncAnimation(fig, animate,interval=10,frames=np.arange(0,2*np.pi,0.1))

まずカッコ内を先頭から順番に説明します。

1. fig:どのグラフを更新するか

2. animate:どういう風に更新するか(※処理の内容を関数化しておく)

3.interval:どのくらいの間隔で更新するか

3 frame:関数animateの引数iをどのように変化させるか、今回はnp.arrange(0,2*np.pi,0.1)なので0, 0.1, 0.2,.....,6.2と0から6.2まで0.1ずつ変化させていることになります。

  

4.3 GIF画像として保存
movie.save("animation_test.gif",writer='pillow')

 

gif 画像としての保存は簡単です。

カッコ内の前が保存名、後ろがpillowというモジュールを使って保存するという意味になります。なおpillowのインストールができていない人は、例えばAnacondaを使用しているなら、お使いのPCのスタートメニューから以下Anaconda promptを起動し、「pip install pillow」と打てばpillowがインストールできます。

f:id:stjun:20200112163457p:plain

 

 

■おわりに

いかがだったでしょうか。

グラフをアニメーションで表示できると、例えば機械学習で学習率がどのように変化しているかを表示させたり、モデルの変数を変化させるとグラフがどう変わるのかをアニメーションで見せることが出来るので非常に便利だと思います。