Jupyter의 인터랙티브 애니메이션

13050 단어 파이썬Jupyter

뭐하고 싶니?



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

이런 느낌이 된다.



소감



뭐 괜찮지만, CPU의 부하가 상당히 어려워진다. 백엔드에서 imagemagik을 사용하는 것 같습니다.
그 편이 무거운 것일까.

좋은 웹페이지 즐겨찾기