3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Jupyter でインタラクティブなアニメーション

Posted at

なにがしたいか

JupyterでGUIを書くために、ユーザの入力に応じて出力するようにしなければならない。入力を受け取る方法として、Widgetが使えるということなので調べてみた。

データの生成

描画データとしては、サインカーブを生成する。その際の、周波数と振幅をwidgetで調整できるようにする。nextメソッドを呼ぶと次のデータを返す。

import math
class Oscillator(object):
    def __init__(self):
        self.amp = 1.0
        self.freq = 1.0
        self.angle = 0
    def next(self):
        self.angle += self.freq / 100.0 
        return math.sin(self.angle * 2 * np.pi) * self.amp  

周波数と振幅のコントロール

コントロールにはWidgetのFloatSliderを用いる。スライダをいじったら、その値がOscillatorに反映されるようにするためにコールバック関数を登録する。

import ipywidgets as widgets

class OscillatorController(object):
    def __init__(self, o):
        self.o = o
        self.fw = widgets.FloatSlider(description='Freq:', min=1.0, max=5.0, value=o.freq)
        self.aw = widgets.FloatSlider(description='Ampl:', min=0.0, max=2.5, value=o.amp)
        self.fw.observe(self._assign_freq, names='value')
        self.aw.observe(self._assign_amp, names='value')

    def _assign_freq(self, change):
        self.o.freq = change['new']
        
    def _assign_amp(self, change):
        self.o.amp = change['new']

    def display(self):
        display(self.fw)
        display(self.aw)  

アニメーション

アニメーションはmatplotlib.animationを使う。インターバルごとに指定した関数がよびだされるので、そこからOscillatornextを呼び出して、データを作る。

%matplotlib nbagg
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

class AnimationPlot(object):
    def __init__(self, o):
        self.fig, self.ax = plt.subplots()
        self.ax.set_xlim((0,100))
        self.ax.set_ylim((-2, 2))
        self.x = np.linspace(0, 100, 100)
        self.y = np.zeros(100)
        self.line, = self.ax.plot(self.x, self.y, lw=2)
        self.yl = list(self.y)

    def animate(self, i):
        self.yl.append(o.next())
        self.yl = self.yl[1:]
        y = np.array(self.yl)
        self.line.set_data(self.x, y)
        return (self.line,)

    def display(self):
        self.anim = animation.FuncAnimation(self.fig, self.animate, frames=100, 
                            interval=200, blit=True)

実行

o = Oscillator()
oc = OscillatorController(o)
aplot = AnimationPlot(o)
aplot.display()
oc.display()

こんなかんじになる。

ezgif-6-56efb62c7cb7.gif

所感

まあいいんだけど、CPUの負荷が結構たかくなる。バックエンドでimagemagik使っているっぽいので
そのへんが重いのだろうか。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?