概要
通常グラフのアニメーションはアニメーションgifが一般的であるが、長いアニメーションはファイルサイズの大きくなり、gifファイルを作成するのも少し時間を要する。通常のアプリケーションのようにGUI上で簡単にアニメーションができたら良いなと思っていた。
CERN ROOTでは描画の間にSleepを入れるだけで簡単にアニメーションになる。CERN ROOTを本格的に覚えようと思った動機でもある。
実行環境
sw_vers
ProductName: macOS
ProductVersion: 14.6.1
BuildVersion: 23G93
root --version
ROOT Version: 6.32.06
Built for macosxarm64 on Sep 21 2024, 18:21:53
From tags/6-32-06@6-32-06
sinの進行波のアニメーション
sinの進行波は次の式で表される
$$
A\sin(kx-\omega t)
$$
$k$:波数 $\omega$: 角振動数
void sin_wave() {
constexpr double timer = 100;
constexpr double y_max = 1.5;
auto canvas = new TCanvas("canvas");
canvas->SetGrid();
auto gr = new TF1("wave", "TMath::Sin([0]*x - [1]*[2])", 0,10);
double t = 0;
double k = 2;
double w = 1;
gr->SetParameters(k, w, t);
gr->SetTitle("sin (kx - #omega t)");
gr->SetMaximum(y_max); //y軸の最大値
gr->SetMinimum(-y_max); //y軸の最小値
gr->Draw();
canvas->ModifiedUpdate();
for(int i = 0; i < 100 && !gSystem->ProcessEvents(); i++) {
gSystem->Sleep(timer);
t += 0.2;
gr->SetParameter(2,t);
canvas->ModifiedUpdate();
}
}
TF1
の第2引数が進行波の計算式で、[0]が波数、[1]が角振動数、[2]が時間でgr->SetParameters(k,w,t)
で具体的な値をセットしています。
forループ内のgr->SetParameter(2,t)
は時間だけが変化するので計算式の[2]だけを変更します。
gSystem->Sleep
はミリ秒です。gSystem->ProcessEvents
は無くても問題なく動作します。
実行するが、これはGUI上のアニメーションなのでアニメーションをここで表示することはできない。なので、終了時の画面のスクショを添付する。
root [0] .x sin_wave.C
root [1]
途中で止めたいときはROOT上でCTRL+C
を打鍵します。
PyROOTバージョン
import ROOT as RT
timer = 100
y_max = 1.5
canvas = RT.TCanvas("canvas")
canvas.SetGrid()
gr = RT.TF1("wave", "TMath::Sin([0]*x - [1]*[2])", 0,10)
t = 0.0
k = 3.0
w = 1.0
gr.SetParameters(k, w, t)
gr.SetTitle("sin (#kappa x - #omega t)")
gr.SetMaximum(y_max)
gr.SetMinimum(-y_max)
gr.Draw()
canvas.ModifiedUpdate()
for i in range(100):
if RT.gSystem.ProcessEvents():
break
RT.gSystem.Sleep(timer)
t += 0.2
gr.SetParameter(2,t)
canvas.ModifiedUpdate()
実行する
source thisroot.sh
python3 -i sin_wave.py
>>>
-i
オプションは実行終了後Pythonが終了してしまうと、実行終了時が画面も消えてしまうので、-i
オプションでPythonを終わらせないようにします。 スクショは同じなので省略します。
sin,cosの重ねグラフを徐々に描画するアニメーション
CERN ROOT (C++) グラフ作成 (1) sin,cosのグラフの重ね表示で描画したsin,cosの重ねグラフの描画を1マーカ毎に描画するアニメーション。
void sincos_anime() {
auto canvas = new TCanvas("canvas");
auto gr = new TGraph();
auto gr2 = new TGraph();
gr->SetMarkerStyle(20);
gr->SetMarkerColor(2);
gr->SetMinimum(-1.1); //y軸の最小値
gr->SetMaximum(1.1); //y軸の最大値
gr->GetXaxis()->SetLimits(0,4); //x軸の範囲
gr->AddPoint(0, TMath::Sin(0));
gr->Draw("apc");
gr2->SetMarkerColor(4);
gr2->SetMarkerStyle(40);
gr2->AddPoint(0, TMath::Cos(0));
gr2->Draw("pc");
canvas->ModifiedUpdate();
for(int i = 1; i < 100 && !gSystem->ProcessEvents(); i++) {
gSystem->Sleep(100);
float x = 0.04 * i;
float ys = TMath::Sin(x * 4);
float yc = TMath::Cos(x * 4);
gr->AddPoint(x, ys);
gr2->AddPoint(x, yc);
gr->SetMinimum(-1.1);
gr->SetMaximum(1.1);
gr->GetXaxis()->SetLimits(0,4);
canvas->ModifiedUpdate();
}
}
CERN ROOT (C++) グラフ作成 (1) sin,cosのグラフの重ね表示のときとは異なり、プロットする点をAddPoint
を使っています。
実際に実行すると赤い点などが1個ずつ描画されるアニメーションなっています。
PyROOTバージョン
PyROOTでは以下のようなコードになります。スクショは省略します。
import ROOT as RT
canvas = RT.TCanvas("canvas")
gr = RT.TGraph()
gr2 = RT.TGraph()
gr.SetMarkerStyle(20)
gr.SetMarkerColor(2)
gr.SetMinimum(-1.1)
gr.SetMaximum(1.1)
gr.GetXaxis().SetLimits(0,4)
gr.AddPoint(0, RT.TMath.Sin(0))
gr.Draw("apc")
gr2.SetMarkerColor(4)
gr2.SetMarkerStyle(40)
gr2.AddPoint(0, RT.TMath.Cos(0))
gr2.Draw("pc")
canvas.ModifiedUpdate()
for i in range(1,100):
if RT.gSystem.ProcessEvents():
break
RT.gSystem.Sleep(100)
x = 0.04 * i
ys = RT.TMath.Sin(x * 4)
yc = RT.TMath.Cos(x * 4)
gr.AddPoint(x, ys)
gr2.AddPoint(x, yc)
gr.SetMinimum(-1.1)
gr.SetMaximum(1.1)
gr.GetXaxis().SetLimits(0,4)
canvas.ModifiedUpdate()
関連
- CERN ROOT (C++) グラフ作成 (2) yをxの計算式として与え、x-yグラフを描画 (class TF1 )
- CERN ROOT (C++) グラフ作成 (1) sin,cosのグラフの重ね表示
終わりに
ここでは実際のアニメーションを見せられないのが残念ですが、興味にある方はぜひCERN ROOTで実行してみてください。 次回は簡単な物理シミュレーションのアニメーションを予定しています。