8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

uproot: Python/NumpyベースでROOTファイルを読み書きするライブラリ

Posted at

概要

CERN開発の解析ライブラリROOT(C++ベース)では、データを*.rootファイルで管理・保存します。
uprootはこの*.rootファイルを高速に読み書きするpython/numpyベースのライブラリです。
リリースされて比較的日が浅いこともあり日本語のドキュメントが見当たらないですが、素粒子・原子核・宇宙実験を中心に使用されるROOTとpythonベース機械学習フレームワークをつなぐ上で非常に有用そうなので、まとめてみました。
公式ドキュメント
ROOT ホームページ
logo-uproot.png

背景

作成したROOTファイルを元に機械学習を走らせたい場合、いくつかの方法が考えられます。

  1. ROOTマクロでcsv形式などにして読み出す
  2. pyROOTなどを使用して読み出す

1はcsv形式に変換するROOTマクロとcsvを読み出してnumpy arrayなどに変換するpythonコードの両方を書く必要があり、明らかに面倒です。
一方で、一見straightforwardに見える2は、Google Colabなどのクラウド環境で走らせる場合、pyROOTをしっかり導入するのはかなり大変そうです。(一応可能のようですが...リンク)

そんな中、最近リリースされたuprootは、ROOTファイルをそのまま扱えて、かつ導入コストが高くないuprootは非常に助かる存在になると思います。さらに、膨大なデータ量も高速に読み出せるという機械学習に使用する上で非常に重要な特徴をも備えています。開発チームによれば、大きなサイズのファイルに対しては本家のROOTをも上回る読み出しスピードを達成するそうです。
root-none-muon.png

すでにLHC(Large Hadron Collider)実験や、XENON-nT実験といった(界隈では)メジャーな実験に多くのユーザーがいるようで、今後も継続的に開発が行われそうです。また、LHCで開発されているMLaaSにも使用されています。

uproot_popularity.png

インストール

pipコマンドでインストールできます。

pip install uproot

condaでもインストールすることができます。

conda config --add channels conda-forge  # if you haven't added conda-forge already
conda install uproot

C++ ROOTがインストールされていることはuprootを使用する上で必要ありません。

使い方

本稿では、最も基本的な使い道のみに絞ってご紹介します。uprootでは、ROOTオブジェクトの名前を使って読み込んだり書き込んだりします。

適当なROOTファイルを作る

適当なROOTマクロです。実行はroot -l GenRootFile.cpp.

GenRootFile.cpp

void GenRootFile(){
   TFile* fout = new TFile("sample.root","recreate");
   TTree* tout = new TTree("tout","tout");
   Int_t    event;
   Double_t val;
   tout->Branch("event",&event,"event/I");
   tout->Branch("val"  ,&val  ,"val/D");
   
   TF1* fgaus = new TF1("fgaus","[0]*TMath::Gaus(x,[1],[2])",-10,10);
   fgaus->SetParameters(1,0,2);
   TH1D* hgaus = new TH1D("hgaus","hgaus",20,-10,10);
   Int_t Nevent = 100;
   for (Int_t ievent = 0; ievent < Nevent; ievent++) {
      event = ievent;
      val   = fgaus->GetRandom();
      
      hgaus ->Fill(val);
      tout  ->Fill();
   }
   
   fout ->cd();
   tout ->Write();
   hgaus->Write();
   fout ->Close();
}

例えばこんなヒストグラムが生成されます。

histogram.png

rootファイルのtreeを読み込む

Treeの持っている名前(今回なら"tout")でアクセスします。

import uproot
file = uproot.open("sample.root")
tout = file["tout"] #TName
print(tout)

Treeの要素にアクセスする

TreeのBranchをnumpy arrayとして読み込むことができます。


val  = tout.array("val")

Histogramを読み込む

Histogramも読み込むことができる。

hgaus = file["hgaus"] # TNameで取得
print(hgaus.edges) # ヒストグラムのx軸
print(hgaus.values)  # ヒストグラムのy軸(値)
hgaus.show()

実行結果はこんな感じ。

[-10.  -9.  -8.  -7.  -6.  -5.  -4.  -3.  -2.  -1.   0.   1.   2.   3.
   4.   5.   6.   7.   8.   9.  10.]
[ 0.  0.  0.  0.  0.  0.  5. 13. 17. 24. 20. 14.  2.  3.  1.  0.  1.  0.
  0.  0.]
               0                                                            25.2
               +---------------------------------------------------------------+
[-inf, -10) 0  |                                                               |
[-10, -9)   0  |                                                               |
[-9, -8)    0  |                                                               |
[-8, -7)    0  |                                                               |
[-7, -6)    0  |                                                               |
[-6, -5)    0  |                                                               |
[-5, -4)    0  |                                                               |
[-4, -3)    5  |************                                                   |
[-3, -2)    13 |********************************                               |
[-2, -1)    17 |******************************************                     |
[-1, 0)     24 |************************************************************   |
[0, 1)      20 |**************************************************             |
[1, 2)      14 |***********************************                            |
[2, 3)      2  |*****                                                          |
[3, 4)      3  |*******                                                        |
[4, 5)      1  |**                                                             |
[5, 6)      0  |                                                               |
[6, 7)      1  |**                                                             |
[7, 8)      0  |                                                               |
[8, 9)      0  |                                                               |
[9, 10)     0  |                                                               |
[10, inf]   0  |                                                               |
               +---------------------------------------------------------------+

書き込み

次のように、新しいROOTファイルを作成して、ヒストグラムや新しいTreeを書き込むこともできます。

import numpy as np
t = uproot.newtree({"branch1": int,
                    "branch2": np.int32,
                    "branch3": uproot.newbranch(np.float64, title="This is the title")})
with uproot.recreate("example.root") as f:
    f["hist"] = hgaus #オブジェクトの名前を適当につける
    f["t"] = t

まとめ

uprootを使えばROOTファイルをpython環境で(高速で)読み書きできることがわかりました。python系の機械学習フレームワーク(PyTorch、Tensorflowなど)で大きなファイルを食わせたい場合には特に有用そうです。

8
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?