とりあえず、優先して覚えることは
だと思います。
rootはいくつか実行方法がある。ここではそれを4つにわける。
きちんとインストールしてあれば、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 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のような機能が備わっているので駆使すれば多少いらいらが収まる。
簡単なc++のプログラムをテストをするのに便利だし、c++の学習という意味でも優れている
複雑な処理をする場合コマンドラインだけで作業をするのはほとんど不可能なので、通常は処理を記述したマクロを読み込ませて使う。
マクロというのは普通のc++のソースコードと同じだけど、コンパイルして使うわけではなくCINTに読み込ませて使用するので、こう呼んでいる(だと思う)。
マクロの読み込ませ方は(細かい話だが)いくつかある。
次のようなマクロを例として用意しよう。
//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はつまり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; }
マクロに引数を渡して実行したい場合は下のようにすればいい。
$ 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");
rootでマクロを実行するにはもうひとつACLiCを使うという方法がある。
cintはしょせんインタープリターなので処理速度が遅いし、cintは完全にC++の文法に従うわけじゃないので解釈の違いにより予期せぬバグがおきることがある。
rootで大規模な解析を行うのにインタープリターにマクロを読ませるような手法には限界がある。
ACLiCはAutomatic Compiler of Libraries for CINTのことで、マクロをコンパイルし共有ライブラリを作り、cint上で実行することができる。コンパイラーを名乗っているが、外部コンパイラーを使っているみたい。
これはROOTを使う上では非常に便利な機能で
(CINTと比較して)
(普通にコンパイルするのに比べて)
使い方としては普通に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を使う上での注意点としては
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"); }
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にこだわる理由は皆無なので、普通にgcc等でライブラリを作ればいいと思う。
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
別に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__がdefineされている。
CINTで実行するときはmain関数をマクロの名前にはできないので、
#ifdef __CINT__ int macro(){ #else int main(){ #endif return 0; }
などとすればマクロとしてもソースコードとしても利用できる。
クラスは 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)
http://hep.planet-koo.com/index.php?g=root&sid=rt_g_groot_setstyle
.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();
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とか、メモリの開放とかをやらせると思う。
で見つかった最初のものが読み込まれる。現実的にはUnix.*.Root.MacroPathに追加したディレクトリにこれらのファイルを置くことになると思う。
起動時、終了時にこれらを読み込みたくない場合は-nオプションをつければいい。
$ root -n