R でアニメーションするグラフを描く

まずは、非線形モデル y = mesor + a cos(2pi*(t-acrophase)/P) にN(0,0.5)のガウシアンノイズを加えたデータを用意し、これを測定されたデータと考える。そのデータに対して非線形回帰するために、Nelder-Mead法で目的関数sum( (y-yhat)^2 )を最大化する。いわゆる cosinor analysis ですね。その計算過程を各ステップごとにプロットし、animation libraryを使ってアニメ化する。

アニメーションの動きが激しくなるように、わざと初期値をおおげざにはずしてある。青が測定データで、緑が予測した回帰曲線。緑のほうの線が動いてみえるはず。収束間近ではあまり動かないのでしばらくみつめていると、ループしてまた初期値から計算しなおす。

コードは以下の通り。

library(animation)
t <- seq(0,48,1)
mesor <- 0
a <- 3
acrophase <- 12
P <- 24
y <- mesor + a * cos(2*pi*(t-acrophase)/P)
y.noise <- mesor + a * cos(2*pi*(t-acrophase)/P) + rnorm(length(t), mean=0, sd=1)

resid <- function(par) {
mesor <- par[1]
a <- par[2]
acrophase <- par[3]
P <- par[4]
yhat <- mesor + a * cos(2*pi*(t-acrophase)/P)

matplot(t,
matrix(c(y.noise, yhat), ncol=2),
col=c("#1E5692", "#3E9A3B"),
type="l", lty=1, pch=21, lwd=5, cex=2,
ylim=c(-5,5))
sum( (y-yhat)^2 )
}
saveMovie(optim(c(5,10,2,18), resid), interval = 0.01, movietype = "gif", outdir = getwd())

ようするにユーザはプロットを何枚か出力するような関数を用意するだけ。それをsaveMovie()関数に渡せば、内部でImageMagickやらSWF Toolsががんばってくれてアニメになる、という仕組みになっている。ImageMagickを MacPortsあたりで入れておく必要がある。

Flash で出力する

SWF Toolsをインストール

sudo port install swftools

lameやらcmakeやらPythonやらがインストールされる。 前回のソース

saveMovie(optim(c(5,10,2,18), resid), interval = 0.01, movietype = "gif", outdir = getwd())

saveSWF( optim(c(5,10,2,18), resid), interval = 0.01, dev="png", outdir = getwd())

アニメーションのコントロールボタンを付ける

ソースコードの最後、

saveMovie(optim(c(5,10,2,18), resid), interval = 0.01, movietype = "gif", outdir = getwd())

ani.options(nmax=200, interval=0.1, title="Cosinor Analysis", outdir = getwd())
ani.start()
optim(c(5,10,2,18), resid)
ani.stop()

に置きかえるだけでHTMLとアニメ用の画像、再生のコントロールボタンを制御するJavaScriptが自動生成される。