# üldised vahendid ja seadistused
import numpy as np
from numpy import zeros, linspace, arange, exp, sin, cos, log, sqrt, pi
from scipy.misc import derivative
from matplotlib import rcParams
rcParams['figure.dpi'] = 100
rcParams['lines.markeredgewidth'] = 0
rcParams['lines.markersize'] = 5
rcParams['font.size'] = 12
from matplotlib.pyplot import *
Kui kasutada %matplotlib inline
(vaikimisi) asemel %matplotlib notebook
, saame interaktiivse graafiku otse Jupyteri keskkonnas. Selline graafik kuvab hiirekursori koordinaate ja sisaldab vahendeid graafiku suumimiseks, liigutamiseks ja salvestamiseks.
Mooduli matplotlib.pyplot
käsud figure
, plot
, text
, jne — nagu ka klasside Figure
, Axes
, jne vastavad meetodid — tagastavad viida loodud objektile, ja selle võib säilitada muutujas. Interaktiivse graafiku puhul saab selle muutuja vahendusel hiljem graafiku sisu muuta:
%matplotlib notebook
f = lambda x: sin(2*pi*x)
x = linspace(0, 1, 200)
x0 = 0.5
tõus = derivative(f, x0, 1e-4)
figure(figsize=(5,3))
plot(x, f(x), 'r-')
punkt, = plot(x0, f(x0), 'bo')
puutuja, = plot(x, f(x0) + (x - x0) * tõus, 'b-')
xlim(0, 1)
ylim(-1.1, 1.1)
grid()
lipik = text(0.75, 0.85, 'tõus=%.2f' % tõus)
tight_layout(pad=0.2)
show()
Nüüd seni kuni see graafik on veel "elav" (st pole vajutatud nupule Stop Interaction), saab järgmise koodi abil muuta graafiku sisu:
x0 = 0.6
tõus = derivative(f, x0, 1e-4)
punkt.set_data(x0, f(x0))
puutuja.set_ydata( f(x0) + (x - x0) * tõus )
lipik.set_text( 'tõus=%.2f' % tõus )
Et parameetreid graafiliselt muuta, tuleb kasutada graafilise kasutajaliidese elemente (widgets) moodulist ipywidgets
. Mugavaim element on liugur (slider), mille tekitab (vastavalt andmetüübile) IntSlider
või FloatSlider
. Aga võimalik on tekitada ka tekstiväli (Text
), rippmenüü (Dropdown
), loend (Select
), lüliti (ToggleButton
või Checkbox
), raadionupud (RadioButtons
), jne (vt täielikku nimekirja). Lihtsamal juhul saab interaktiivse seose arvutusülesande ja sisestuselemendi vahel luua käsuga ipywidgets.interact
.
from ipywidgets import interact, FloatSlider
figure(figsize=(5,3))
plot(x, f(x), 'r-')
punkt, puutuja = plot((), (), 'bo', (), (), 'b-')
xlim(0, 1)
ylim(-1.1, 1.1)
grid()
lipik = text(0.75, 0.85, '')
tight_layout(pad=0.2)
show()
def uuenda(x0):
tõus = derivative(f, x0, 1e-4)
punkt.set_data(x0, f(x0))
puutuja.set_data(x, f(x0) + (x - x0) * tõus)
lipik.set_text( 'tõus=%.2f' % tõus )
slider = FloatSlider(min=0, max=1, step=0.01, value=0.5, description='x0')
interact(uuenda, x0=slider);
Võrreldava tulemuse saab ka staatilise graafikuga (%matplotlib inline
), aga sel juhul tuleb iga kord terve graafik tekitada uuesti.
%matplotlib inline
def graafik(x0):
tõus = derivative(f, x0, 1e-4)
figure(figsize=(5,3))
plot(x, f(x), 'r-')
plot(x0, f(x0), 'bo')
plot(x, f(x0) + (x - x0) * tõus, 'b-')
xlim(0, 1)
ylim(-1.1, 1.1)
grid()
text(0.75, 0.85, 'tõus=%.2f' % tõus)
tight_layout(pad=0.2)
show()
slider = FloatSlider(min=0, max=1, step=0.01, value=0.5, description='x0')
interact(graafik, x0=slider);
Elementide paigutamine üksteise kõrvale või nende kujunduse muutmine nõuab juba rohkem programmeerimist:
%matplotlib notebook
from ipywidgets import interactive_output, HBox
from IPython.display import display
figure(figsize=(6,3))
komp1, = plot((), (), 'g-', linewidth=1)
komp2, = plot((), (), 'r-', linewidth=1)
summa, = plot((), (), 'b-', linewidth=2)
xlim(0, 8)
ylim(-2, 2)
grid()
tight_layout(pad=0.2)
show()
t = linspace(0, 8, 800)
def uuenda(sagedus, faas):
x1 = sin(2*pi*t)
x2 = sin(2*pi*sagedus*t + faas)
komp1.set_data(t, x1)
komp2.set_data(t, x2)
summa.set_data(t, x1+x2)
slider1 = FloatSlider(min=0, max=2, step=0.02, value=1, description='sagedus')
slider2 = FloatSlider(min=0, max=pi, step=0.01*pi, value=0, description='faasinihe')
display(
HBox( (slider1, slider2) ),
interactive_output(uuenda, {'sagedus': slider1, 'faas': slider2})
)
import scipy.signal
from ipywidgets import IntSlider, Layout
t = linspace(0, 2.5, 800)
wt = 2*pi*t
f = scipy.signal.square(wt, 0.5)
fourier = lambda k: 4 * sin((2 * k - 1) * wt) / (pi * (2 * k - 1))
figure(figsize=(6,3))
plot(t, f, 'r-', linewidth=1)
summa, = plot((), (), 'b-', linewidth=2)
xlim(0, 2.5)
ylim(-1.3, 1.3)
grid()
tight_layout(pad=0.2)
show()
def uuenda(n):
x = zeros( len(t) )
for k in range(1, n):
x += fourier(k)
summa.set_data(t, x)
slider = IntSlider(min=2, max=30, value=2,
description='harmooniliste komponentide arv',
style = {'description_width': 'initial'},
layout=Layout(width='90%'))
interact(uuenda, n=slider);
Lihtne liides graafiku animeerimiseks on matplotlib.animation.FuncAnimation
.
from matplotlib.animation import FuncAnimation
graafik = figure(figsize=(6,3))
plot(t, f, 'r-', linewidth=1)
summa, = plot((), (), 'b-', linewidth=2)
xlim(0, 2.5)
ylim(-1.3, 1.3)
grid()
arv = text(0.75, 0.95, '', ha='center', va='top')
tight_layout(pad=0.2)
show()
def uuenda(kaader):
n = kaader + 2
x = zeros( len(t) )
for k in range(1, n):
x += fourier(k)
summa.set_data(t, x)
arv.set_text('n=' + str(n))
return summa, arv
ani = FuncAnimation(graafik, uuenda, frames=20, interval=500, blit=True)
Animatsiooni võib salvestada omaette videofailina. Seda saab teha näiteks järgmisel viisil. Esmalt tuleb käsuga savefig
salvestada iga kaader eraldi (rastergraafika) faili, kus failinimes sisalduks kaadri järjekorranumber (näiteks kaader000.png
, kaader001.png
, jne):
%matplotlib inline
figure(figsize=(8,4), dpi=150)
for kaader in range(20):
n = kaader + 2
x = zeros( len(t) )
for k in range(1, n):
x += fourier(k)
plot(t, f, 'r-', linewidth=0.8)
plot(t, x, 'b-')
xlim(0, 2.5)
ylim(-1.3, 1.3)
grid()
text(0.75, 0.95, 'n=' + str(n), ha='center', va='top')
xlabel('aeg')
ylabel('signaal')
tight_layout(pad=0.2)
savefig('kaadrid/kaader%03d.png' % kaader)
clf() # pärast salvestamist kustutame graafiku
Seejärel tuleb kasutada mõnda programmi, mis võimaldaks kompileerida kõik kaadrid üheks videoks või animeeritud GIF-failiks. Näiteks programm ffmpeg teeb selle töö käsuga:
ffmpeg -r 10 -i kaader%03d.png -b:v 2M animation.mp4
Siin kaadrisagedust (-r
) ja bitikiirust (-b:v
) võib muuta vastavalt vajadusele. Veidi põhjalikum näide, kus täpsustatakse videokoodek ja antakse erinevad kaadrisagedused sisend- ja väljundvoo jaoks:
ffmpeg -r 2 -i kaader%03d.png -c:v libx264 -pix_fmt yuv420p -r 10 animation.mp4
Lihtsaim käsk sama programmiga GIF animatsiooni loomiseks:
ffmpeg -r 2 -i kaader%03d.png animation.gif
GIF animatsioonide tegemiseks leidub ka veebipõhiseid vahendeid.