🐾

QtでCERNのROOTを使用する

2022/07/15に公開

概要

 CERNで開発されているROOTというデータ解析フレームワークをQtに組み込んで使用するための設定です。
 主に宇宙物理学(素粒子など)で使用されているようです。グラフ表示や基本設定などは奥村 曉さんの(PDF)高エネルギー宇宙物理学のための ROOT 入門を一読されるとわかると思います。
 本記事では、QtにROOTを組み込んで表示する部分にフォーカスして説明します。

環境

Windows 10 (64bit)
Qt6

準備

1. ROOT

 以下のリンクからROOTをダウンロード&インストールします。基本的にLatestで問題ないと思います。
 古いバージョンが必要な場合は、Windows環境だと64bit版が提供されていないので、ソースからビルドする必要がありますが、そんなに難しくないので問題なくビルドできると思います。

ROOT Releases

2. Qt

 以下のリンクからQtをダウンロード&インストールします。Windows版だとメンテナンスツール経由のインストールになります。(macOSだとbrewでインストールできます。)

Qtを取得する

手順

1. C++での設定

 QtのMainWindowの設定として、ROOTのCanvasの場所を指定しています。設定した座標(XY)と縦横の大きさで表示されます。
 描画はQtのSlotを使って描画するタイミングでdraw()を呼び出すとROOTのAPIで呼び出したグラフが表示できます。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow)
{
    my_canvas = new MyCanvas(this);
    my_canvas->setGeometry(<x>, <y>, <width>, <height>);
}

 Canvasは別クラスにして、MyCanvasとして実装しました。

#include <TVirtualX.h>
#include <TCanvas.h>

MyCanvas::MyCanvas(QWidget *parent)
    : QWidget{parent}
{
    setAttribute(Qt::WA_PaintOnScreen, false);
    setAttribute(Qt::WA_OpaquePaintEvent, true);
    setAttribute(Qt::WA_NativeWindow, true);
    setUpdatesEnabled(false);
    setMouseTracking(false);

    int w = 300;
    int h = 300;
    int wid = gVirtualX->AddWindow((ULong_t)winId(), w, h);
    canvas = new TCanvas("", w, h, wid);
}

 以下のリンクのROOT公式のグラフの例から、好きなグラフのコードを記述します。グラフ描画後にResize()とUpdate()を呼びます。

THistPainter Class Reference

void MyCanvas::draw() {
    // draw a graph here.
    canvas->Resize();
    canvas->Update();
}

2. CMakeLists.txtの設定

find_package(ROOT REQUIRED)
include(${ROOT_USE_FILE})
include_directories(${ROOT_INCLUDE_DIRS})
target_link_libraries(<bin_name> PRIVATE Qt${QT_VERSION_MAJOR}::Widgets ${ROOT_LIBRARIES})

3. 描画例

 ROOTの公式サンプルを参考にグラフを表示するとこのようになります。座標(100, 50)、縦横(300,300)で描画したグラフは以下のようになります。
 MainWindowの上にオーバーレイする形で表示されているのがわかります。

最後に

 ROOTのLicenseを読むと、MathMore関連はLGPLじゃないので、商用などでROOTを使用したい場合は、気をつける必要があります。依存している部分は一部なので除外するという手段で回避できると思います。
 今回はWindows上での動作確認を行っていますが、Linuxでも問題なく動作すると思います。注意が必要なのはmacOSで、現状だとmacOSではgVirtualXによるwidの取得がうまく動作せず、正常に動作しないハズです。少なくとも、動作確認をとることができませんでした。Cocoaの問題なのかとおもい、X11でROOTをビルドしてみたのですが、そちらも動作しませんでした。macOSでもQt上でCanvasを表示できたという方がいれば、教えて頂きたいです。Canvasは表示されるけど、真っ黒な画像となってしまって、正しい画像が表示できませんでした。以下のような画面表示になって、エラーもでるはずです。これはROOTのForumでも報告されていているので、認知はされているかと思いますが、開発リソースが不足しているようですし、macOS+Qtでの描画は優先順位が低いのかもしれません。

RootCanvas[16903:290415] This window not found among allocated/deleted drawables
RootCanvas[16903:290415] Fatal error: requested drawable 18446744073709551615 is not found among currently valid drawables.
RootCanvas[16903:290415] Fatal error: requested drawable 0 is not found among currently valid drawables.
RootCanvas[16903:290415] Fatal error: requested drawable 18446744073709551615 is not found among currently valid drawables.
RootCanvas[16903:290415] Fatal error: requested non-existing drawable 18446744073709551615

Discussion