リアルタイム更新したい(TCanvas::Modified / TCanvas::Update)
1#include <TCanvas.h>
2#include <TGraph.h>
3
4void macro() {
5 TCanvas *c = new TCanvas("c", "Real-time Monitor", 800, 600);
6 TGraph *g = new TGraph();
7
8 for (int i = 0; i < 100; i++) {
9 g->SetPoint(i, i, i * i);
10 if (i % 10 == 0) {
11 g->Draw("AL");
12 c->Modified(); // Mark canvas as changed
13 c->Update(); // Flush to screen
14 }
15 gSystem->ProcessEvents(); // Handle GUI events
16 }
17}
キャンバスをリアルタイムで更新したい場合は、
TCanvas::Modified -> TCanvas::Updateの2ステップが必要です。
TCanvas::Modifiedはキャンバスが変更されたことをマークします。
TCanvas::Updateは変更を画面に反映させます。
gSystem->ProcessEventsは、
マウスやキーボード操作などのGUIイベントを処理するためのメソッドです。
イベントループで毎回呼ぶことで、描画中もウィンドウが応答するようになります。
1from ROOT import TCanvas, TGraph, gSystem
2
3def macro():
4 c = TCanvas("c", "Real-time Monitor", 800, 600)
5 g = TGraph()
6
7 for i in range(100):
8 g.SetPoint(i, i, i * i)
9 if i % 10 == 0:
10 g.Draw("AL")
11 c.Modified() # Mark canvas as changed
12 c.Update() # Flush to screen
13 gSystem.ProcessEvents() # Handle GUI events
グラフを段階的に描画したい
1#include <TCanvas.h>
2#include <TGraph.h>
3#include <TSystem.h>
4#include <TMath.h>
5
6TCanvas *c = new TCanvas("c", "Canvas", 800, 600);
7TGraph *g = new TGraph();
8
9for (int i = 0; i < 100; i++) {
10 g->SetPoint(i, i * 0.1, TMath::Sin(i * 0.1));
11 if (i % 10 == 0) {
12 g->Draw("AL");
13 c->Update();
14 gSystem->Sleep(100); // 100ミリ秒待機
15 }
16}
17g->Draw("AL");
18c->Update();
gSystem->Sleep()と組み合わせることで、グラフが描かれていく様子を確認できます。
ヒストグラムを動的に更新したい
1#include <TCanvas.h>
2#include <TH1D.h>
3#include <TRandom.h>
4
5TCanvas *c = new TCanvas("c", "Canvas", 800, 600);
6TH1D *h = new TH1D("h", "Distribution", 100, -3, 3);
7h->Draw();
8
9for (int i = 0; i < 10000; i++) {
10 h->Fill(gRandom->Gaus(0, 1));
11 if (i % 1000 == 0) c->Update(); // 1000個ごとに更新
12}
13c->Update();
Updateの呼び出しが多すぎると処理が遅くなります。適切な間隔で呼ぶことが大切です。
アニメーションを作りたい
1#include <TCanvas.h>
2#include <TGraph.h>
3#include <TSystem.h>
4#include <TMath.h>
5
6TCanvas *c = new TCanvas("c", "Animation", 800, 600);
7TGraph *g = new TGraph();
8
9for (int frame = 0; frame < 100; frame++) {
10 g->Clear();
11 for (int i = 0; i < 50; i++) {
12 double x = i * 0.1;
13 g->SetPoint(i, x, TMath::Sin(x + frame * 0.1));
14 }
15 g->SetTitle(Form("Frame %d", frame));
16 g->Draw("AL");
17 c->Update();
18 gSystem->Sleep(16); // 約60fps
19}
サンプリング表示したい
1void macro() {
2 // Non-blocking: DAQ keeps running, display updates periodically
3 auto t_last = std::chrono::steady_clock::now();
4
5 while (running) {
6 // Acquire new data and fill histogram
7 // DAQ is never blocked
8 h1->Fill(get_next_sample());
9
10 auto now = std::chrono::steady_clock::now();
11 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - t_last).count();
12
13 if (elapsed >= 500) { // Update every 500 ms
14 h1->Draw();
15 c->Modified();
16 c->Update();
17 gSystem->ProcessEvents(); // Handle GUI events
18 t_last = now;
19 }
20 }
21}
イベントレートが高い場合は、表示する頻度を制限するとよいです。
このときgSystem->Sleepを使うと、データ取得もブロックされてしまうため、
std::chronoなどのタイマーを使って、経過時間ベースで更新するとよいです。
関連メソッド
TCanvas - キャンバスの基本
TCanvas::Divide - キャンバスを分割する
TCanvas::Print - 複数ページのPDFに保存する