ユーザ用ツール

サイト用ツール


サイドバー

Menu

Latest

study:software:root:general

General

初めてrootの使い方を勉強する方は猿ROOT等の解説書でひと通り勉強した方がいいと思います。

とりあえず、優先して覚えることは

  1. ヒストグラム(とグラフ)の使い方
    • 画像として表示する方法
    • フィットの仕方
    • rootファイルの保存方法
  2. TTreeの使い方

だと思います。

rootを使う方法

rootはいくつか実行方法がある。ここではそれを4つにわける。

  1. コマンドラインでインタラクティブに使う
  2. マクロを読み込んで使う
  3. ACLiCでマクロをコンパイルして、実行する
  4. rootをライブラリとして利用して、プログラムにする

rootを起動する

きちんとインストールしてあれば、shellでrootとコマンドすると、謎のスプラッシュとともに起動される。

$ root
 *******************************************
  *                                         *
  *        W E L C O M E  to  R O O T       *
  *                                         *
  *   Version   5.34/00       5 June 2012   *
  *                                         *
  *  You are welcome to visit our Web site  *
  *          http://root.cern.ch            *
  *                                         *
  *******************************************

ROOT 5.34/00 (branches/v5-34-00-patches@44555, Jun 05 2012, 16:18:52 on macosx64)

CINT/ROOT C/C++ Interpreter version 5.18.00, July 2, 2010
Type ? for help. Commands must be C++ statements.
Enclose multiple statements between { }.
root [0]

root起動時のオプションを下に示す。

-l スプラッシュを表示しない
-b バッチモードで起動。sshなどで使う場合便利
-n rootの起動終了スクリプトを読み込まない
-q マクロの読み込みが終わったら、rootを終了する
-x exit on exception。例外処理で終了するでok?

rootを終了するときは

root [ ] .q

rootではインタープリターを使わなくても、それらのコマンドを記録したマクロを作って読み込ませることもできる。

$ root macro.cxx

rootファイルを読み込む

rootで作ったデータは拡張子rootのファイルによって、記録することができる。このファイルを開くには

$ root hoge.root

とする。

root [ ] .ls

と打つと、rootファイルの中身を見ることができる。

とりあえず.qと.lsの2つのコマンドは最優先して覚えたほうがいい。

実行ディレクトリを指定する

rootコマンドの第1引数をディレクトリにすると、そのディレクトリをカレントディレクトリにして動作する。

$ root <dir> macro.cxx
$ # これは以下のことをするのと等価
$ # cd <dir>
$ # root macro.cxx
$ # (root終了後に)cd 元々いたディレクトリ

インタープリター

rootは基本的にはインタープリターで、rootのコマンド(rootで予め用意されたクラスのメソッド)を打ち込んで使う。

root [0] TH1F *h1 = new TH1F("h1","histogram",100,0.,200.); //TH1Fはrootのクラスの一種
root [1] h1->Fill(2); //このようにクラスのメソッドを使う形で、物理解析用の機能を利用する
root [2] h1->Fill(1);
root [3] h1->Draw();

TH1Fというのはヒストグラムに対応するクラスの一種。

下のように普通のc++の関数も使える。

root [4] int a = 3;
root [5] cout<<a<<endl; //std::は省略できる
3

下のように{}でくくることで、複数行書くこともできる。

root [6] for(int i=0;i<2;++i){
end with '}', '@':abort > char* b = "Hello";//各行;できちんと終わる必要がある
end with '}', '@':abort > cout<<b<<endl;
end with '}', '@':abort > }
Hello

コマンドラインでは関数は定義できない。クラスは定義できる。つまり構造体だけ定義できるってことか。

rootのコマンドラインはcintというc++用のインタープリターになっており、非常に応用性が高い。

逆にc++の文法に則っているので、コマンドがやや冗長すぎるきらいがある。

一応、tab補完や履歴などshellのような機能が備わっているので駆使すれば多少いらいらが収まる。

cintそのものは後藤 正治さんが開発したrootとは独自のもの。

簡単なc++のプログラムをテストをするのに便利だし、c++の学習という意味でも優れている

マクロ

複雑な処理をする場合コマンドラインだけで作業をするのはほとんど不可能なので、通常は処理を記述したマクロを読み込ませて使う。

マクロというのは普通のc++のソースコードと同じだけど、コンパイルして使うわけではなくCINTに読み込ませて使用するので、こう呼んでいる(だと思う)。

マクロの読み込ませ方は(細かい話だが)いくつかある。

rootマクロは基本的にc++の文法で書くが、いくつかの点で記述方法が異なる。詳しくは次の項目以降で説明するが、

  • root用のクラスやc++標準ライブラリを使うために、ヘッダーを#includeする必要はない
  • main関数を作らなくていい。ファイル名と同名の関数がmain関数の役割を果たす(後述)
  • その他、CINT独自の拡張によって、文法がいい加減でも実行できる(CINTの項参照)

普通に読み込む、.xを使う

次のようなマクロを例として用意しよう。

//rootのクラスとc++標準関数(一部?)の使用については#includeは不要

int macro()//ファイル名と関数名は同じにする
{
  TH1F *h1 = new TH1F( "h1", "historgram", 100, -10., 10. );
  h1->FillRandom("gaus");
  h1->Draw();
  return 0;
}

ターミナルで

$ root macro.cxx

とコマンドするか、cintで下のようにコマンドすると

root [0]  .x macro.cxx

ヒストグラムが現れるはず。

ここで、メインの関数名はファイル名(拡張子は除く)と同じでなくてはいけない

なぜなら、このときファイル名と同じ名前の関数(この場合macro())を実行するという動作が行われているからである。

.Lを使う

もう一つのマクロの読み込みの方法は.Lを使う方法。

.LはつまりLoad(読み込み)なので、関数が定義されるだけで関数の実行はしない。

root [0]  .L macro.cxx; //.Lでマクロを読み込むと、macro()が定義される
root [1] macro(); //macro()を実行

この場合は当然、関数の名前はファイル名と同じである必要はない。

名前なしのスクリプト

名前なしのスクリプトってのはユーザマニュアルに書いてあった用語。意味がわかりにくい気がする

さきほどの2つはマクロに関数を定義して、それを実行してる点では同じである。

しかし、下のように関数を定義していないファイルを読みこませて使うこともできる。

{
  (なにかコマンド);
  (なにかコマンド);
  (なにかコマンド);
}

これも、下のようにすることで実行できる。

$ root macro.cxx

または

root [0] .x macro.cxx

または

root [0] .L macro.cxx

これは単純に一行一行コマンドを実行しているだけである。


(ここから、余談)

  (なにかコマンド);
  (なにかコマンド);
  (なにかコマンド);

というのも、下のようにすれば読み込ませることができる。

root [0] .L macro.cxx

マクロに引数を渡す

例として下のようなマクロを用意する。

void macro(int i = 3,std::string str = "number")
{
        std::cout << str.Data() << "=" << i << std::endl;
}

普通のcのプログラムの場合はmain関数に許された引数はintとchar**のみだけど、この場合は単に関数を実行するだけなので自由にできる

マクロに引数を渡して実行したい場合は下のようにすればいい。

$ root 'macro.cxx(10,"my number")'
$ root macro.cxx(10,"my number") #これはだめ
$ root 'macro.cxx+(2,"your number")' #ACLiCを使う
$ root 'macro.cxx(1, "'$str'")' #シェル変数を使う場合

つまり、シングルクオートでエスケープして"や(を文字だと判断させる必要がある。

見て分かるようにめちゃくちゃうっとうしい。

下のように、rootのコマンドラインで実行すれば、こんなbash独特の気持ち悪い文法は気にしなくていい。

root [] .x macro.cxx(10,"my number");
root [] .x macro.cxx+(2,"your number");

ACLiC

rootでマクロを実行するにはもうひとつACLiCを使うという方法がある。

cintはしょせんインタープリターなので処理速度が遅いし、cintは完全にC++の文法に従うわけじゃないので解釈の違いにより予期せぬバグがおきることがある。

rootで大規模な解析を行うのにインタープリターにマクロを読ませるような手法には限界がある。


ACLiCはAutomatic Compiler of Libraries for CINTのことで、マクロをコンパイルし共有ライブラリを作り、cint上で実行することができる。コンパイラーを名乗っているが、外部コンパイラーを使っているみたい。

これはROOTを使う上では非常に便利な機能で

(CINTと比較して)

  • 文法がc++通りで正しい
  • 処理が高速(ただし、コンパイルによるオーバーヘッドはある)

(普通にコンパイルするのに比べて)

  • コンパイルが簡単(マクロを読み込むときに+をつけるだけ。リンクを気にする必要もない)
  • 作成された共有ライブラリはCINTで実行されるので、マクロ実行後シームレスにインタープリターでの操作に移ることが出来る
    • 使用感がCINTにマクロを読みこませるのと大差ない
  • ACLiCがコンパイル時に行うエラー解析はroot用のものなので、普通のコンパイラーよりもわかりやすい(と思う)。


使い方としては普通にmacro.cxxを用意して、下のように実行するだけである。

$ root macro.cxx+ //マクロをコンパイルして実行(マクロが更新されていなければ再コンパイルしない)
$ root macro.cxx++ //マクロを再コンパイルして実行
$ root macro.cxx+g //マクロをデバッグ情報を付加してコンパイルして実行
$ root macro.cxx+o //マクロを最適化してコンパイルして実行

あるいはrootを起動して、下の2つのどちらかをしても同じ意味である。

root [ ] .x macro.cxx+
root [ ] gROOT->macro("macro.cxx+") //.xはgROOT->macro()と同じ。


ACLiCを使う上での注意点としては

  • cint独自の機能を使えない
  • 必要なヘッダをあらかじめ#includeする必要がある(ただしライブラリをリンクする必要はない、というかリンクできない)

ACLiCは使用感はCINTのマクロとあまり変わらないが、実際にはコンパイルと関数の実行を連続にしているだけ。つまり、下のような作業をするのと等価

//コンパイルをして、hoge_cxx.soを作る
root [ ] gSystem->Load("hoge_cxx.so");
root [ ] hoge();

#include <iostream>
#include "TFile.h"
#include "TTree.h"
#include "TCanvas.h"
#include "TH1.h"

void example(){
  cout << "this is example" << endl; 
  //名前空間std::はつけなくてもいい
  //ただし、コンパイルエラー時にはなぜかstdをつけなさいって怒られるから動揺する
  
  TFile *file = new TFile("hoge.root","recreate");
  TTree *tree = new TTree("tree","tree");
  
  int a;
  tree->Branch("a",&a,"a/I");
  a=1; tree->Fill();
  a=2; tree->Fill();
  a=3; tree->Fill();

  TCanvas *canvas = new TCanvas("canvas","canvas");
  TH1F *hist = new TH1F("hist","title",5,0,10);
  tree->Draw("a >> hist");
}

#includeせずとも、なぜか<vector>は使える。

ROOTでの外部ライブラリの利用

CINTでその他の外部ライブラリを利用したい場合は

[ ] .L hoge.so 

gROOT->ProcessLine(".L hoge.so ")
//or
gSystem->Load("hoge.so")

とする。こんな感じで動的にライブラリを利用できるのはc++にはないCINTの特長だと思う。

.Lで読み込むことができるのはRoot.MacroPathで登録したDirectory、gSystem->LoadはRoot.DynamicPathで登録したDirectory(初期設定ファイルと起動終了時マクロに詳しく書かれている)。


ACLiCで外部ライブラリを使いたい場合は基本的にはソースコードではheaderをincludeしておいて

#include "hoge.h"
/*hoge.soで定義されてるクラスや関数を使う*/

下のようにCINT上で実行するという方法をとる。

[ ] .L hoge.so
[ ] .x macro.cxx+

ACLiCで生成するライブラリに外部ライブラリをリンクする方法もあるとは思うが、私は知らない。

別にACLiCにこだわる理由は皆無なので、普通にgcc等でライブラリを作ればいいと思う。

rootをコンパイルして使用する

rootは必要なライブラリをリンクすることで、普通のプログラムのようにコンパイルして実行することもできる。

このメリットは

  • root以外のライブラリをリンクできる
  • コンパイルするので高速

デメリットは

  • コンパイルするのが面倒くさい

コンパイル方法

ライブラリのリンク

rootは実に親切で必要なライブラリを出力するコマンドを作ってくれている。

$ root-config --cflags --libs
-pthread -m64 -I/usr/local/hep/root/include -L/usr/local/hep/root/lib -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lpthread -Wl,-rpath,/usr/local/hep/root/lib -lm -ldl

なので、基本的には上の引数で得られるオプションを追加すればコンパイルできる。

g++ `root-config --cflags --libs` macro.cxx -o macro

もしもライブラリが足りなくてコンパイルできない場合はhttp://root.cern.ch/root/htmlの 各クラスのページの右上にライブラリが表示されているので、足りないライブラリをリンクする

root-configは$ROOTSYS/binに置いてあるシェルスクリプト

Makefile

別にMakefileを作らなくてもコンパイルはできるが、なんだかんだいって一度Makefileを作っておくと流用できるので楽。

例えば、単純にmacro.ccをコンパイルしてrootのアプリケーションにするMakefile。

TARGET = macro

SRCS = $(TARGET).cc
OBJS = $(TARGET).o

ROOTCFLAGS = $(shell root-config --cflags)
ROOTLIBS   = $(shell root-config --libs)
ROOTGLIBS = $(shell root-config --glibs)

CXXFLAGS   = $(ROOTCFLAGS) -Wall -fPIC
CXXLIBS    = $(ROOTLIBS)
CC = g++ 

$(TARGET): $(OBJS)
    $(CC) $(CXXLIBS) $(OBJS) -o $@

# suffix rule
.cc.o:
    $(CC) $(CXXFLAGS) -c $<

# clean
clean:
    rm -f $(TARGET) $(OBJS)

この場合、一つのソースファイルをコンパイルするだけなので、Makefileを作るほどのことでもない気もする。

※インデントが入力の関係でスペースになっているけど、タブにしてください。

イベントループ

ディスプレイ出力をしたい

TCanvasにDrawして画面出力がしたい場合は、GUIイベントループを発生させる必要がある。

下のようにTApplicationのインスタンスを作って、Runさせればいいらしい。

#include <TApplication.h>
#include <TH1.h>

int main( int argc, char **argv )
{
    TApplication app( "app", &argc, argv );/

    TH1F *h = new TH1F( "h", "", 100, -5, 5 );
    h->FillRandom("gaus");
    h->Draw();

    app.Run();

    return 0;
}  

インタープリターの起動

C++のコードからインタープリターを起動させることができる。

上のコードのTApplicationをTRintに変えるだけでいい(TRintはTApplicationを継承している)。

#include <TRint.h>
#include <TH1.h>

int main( int argc, char **argv )
{
    TRint app( "app", &argc, argv );/

    TH1F *h = new TH1F( "h", "", 100, -5, 5 );
    h->FillRandom("gaus");
    h->Draw();

    app.Run();

    return 0;
}  

CINTとコンパイラー両方で動くマクロを作る

CINTで実行されるときには__CINT__がdefineされている。

CINTで実行するときはmain関数をマクロの名前にはできないので、

#ifdef __CINT__
int macro(){
#else
int main(){
#endif


  return 0;
}

などとすればマクロとしてもソースコードとしても利用できる。

rootについての基本知識

コーディング規約

クラスは T で始まる: TLine, TTree
クラス以外の型は _t で終わる: Int_t
データメンバは f で始まる: fTree
メンバ関数は大文字で始まる: Loop()
定数はk で始まる: kInitialSize,kRed
グローバル変数は g で始まる: gEnv
静的データメンバは fg で始まる: fgTokenClient
列挙型は E で始まる: EColorLevel
ローカル変数とパラメータは小文字で始まる: nbytes
何かを取得・設定するものはGetとSetで始まる: SetLast(), GetFirst()

ついでに言うと基本的にすべてCamelCase。

処理系非依存型

普通c++ではdoble型やint型といった変数を使うが、これらは処理系によってサイズが違うことがあるらしい。

なので、違うpcでプログラムを走らせるとバグの原因になる。

そこで、rootでは処理系に依存しない変数型が用意されている。Int_tやDouble_tといった感じで、頭文字が大文字で後ろに_tをつけた名前になっている。

Char_t Char型 (符号付き:1バイト)
UChar_t Char型 (符号なし:1バイト)
Short_t Short型(符号付き整数:2バイト)
UShort_t Short型(符号なし整数:2バイト)
Int_t Int型 (符号付き整数:4バイト)
UInt_t Int型 (符号なし整数:4バイト)
Long64_t Long型 (移植可能:符号付き整数:8バイト)
ULong64_t Long型 (移植可能:符号なし整数:8バイト)
Float_t Float型 :4バイト
Double_t Float型 :8バイト
Double32_t Double型 :メモリでは8バイト、書き込みは4バイトのFloat
Bool_t Boolean型 (0=false, 1=true)

これらの変数型は$ROOTSYS/core/base/inc/Rtypes.hで定義されている。

初期設定ファイルと起動終了時マクロ

.rootrc

http://hep.planet-koo.com/index.php?g=root&sid=rt_g_groot_setstyle

.rootrcはライブラリのパスや一部のデフォルト値などが書かれているファイルである。

  1. $ROOTSYS/etc/root/system.rootrc
  2. $HOME/.rootrc
  3. ./.rootrc

で最初に見つかったものが優先されて読み込まれる。

設定を変えたい場合はsystem.rootrcを$HOMEにコピーして、これを書き換えるのが普通だと思う。

$ cp $ROOTSYS/etc/root/system.rootrc $HOME/.rootrc

といってもそれほど書き換えたいものはないと思う。私は以下のようにしている。

Unix.*.Root.DynamicPath:    .:$(ROOTSYS)/lib:$(HOME)/.root/lib
Unix.*.Root.MacroPath:      .:$(ROOTSYS)/macros:$(HOME)/.root/macros


.rootrcで設定された現在値は以下のようにして知ることが出来る。

root [] gEnv->Print();

Unix.*.Root.MacroPathが通っているディレクトリにあるマクロは.Lで読み込める。またUnix.*.Root.DynamicPathが通っているディレクトリにある共有ライブラリはgSystem->Load()で読み込める

.rootlogon.C,rootlogoff.C,.rootalias.C

http://hep.planet-koo.com/index.php?g=root&sid=rt_g_genv

rootlogon.C,rootlogoff.Cは起動時、終了時のそれぞれに読み込まれるマクロ、rootalias.Cはインタラクティブにrootを起動させた場合のみに読み込まれるマクロ。

普通は毎回行うstyleの設定や自分で定義した関数などをここに書いておく。rootlogoff.Cの方はたぶんfileのcloseとか、メモリの開放とかをやらせると思う。

rootlogon.Cなどのファイルの名前は.rootrcによって変えることも出来る

  1. カレントディレクトリ
  2. マクロパスのディレクトリ

で見つかった最初のものが読み込まれる。現実的にはUnix.*.Root.MacroPathに追加したディレクトリにこれらのファイルを置くことになると思う。

起動時、終了時にこれらを読み込みたくない場合は-nオプションをつければいい。

$ root -n

study/software/root/general.txt · 最終更新: 2015/08/13 13:04 by kamo

ページ用ツール