リアルタイム更新したい(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などのタイマーを使って、経過時間ベースで更新するとよいです。

関連メソッド

参考資料