具体的に〇〇をやりたいなと思った時にみるメモです. 本編に入らないトリック集です.
- 実行関連
- g++でコンパイル
- ACLiCでコンパイルして実行
- お絵描き
- RGBで色を指定したい
- 範囲を塗りつぶしたい
- ヒストグラム
- ピークサーチがしたい
- TTree
- 人からもらったTTreeをとりあえず見る
- TTreeを処理するマクロを自動生成する
- TTreeのブランチの設定を簡単にやる
- 要らないブランチを読み込まない
- Treeのブランチがstd::vectorの際に, std::vectorの関数を呼ぶ
- 同質のTTreeをまとめて解析する
- TGraph
- std::vectorで入っているデータをプロットしたい
実行関連
g++でコンパイル
ROOTをライブラリとして使って, g++でコンパイルしバイナリを作成する方法です.
root-config というコマンドがよしなに必要なものを準備してくれます.
こういう code.cxx があるとします.
// code.cxx
#include <iostream>
#include <TH1.h>
int main(int argc, char** argv){
auto hist = new TH1D("hist", "hist", 100, -5, 5);
hist->FillRandom("gaus");
std::cout << hist->GetEntries() << std::endl;
return 0;
}この一行で行けます.
g++ code.cxx -o code `root-config --cflags --libs`ACLiCでコンパイルして実行
いつものrootマクロを実行するノリでなんちゃってコンパイルをする方法です.
Shared libraryを作成します.
最後に + をつけるだけです.
root macro.C+この場合, 最初に呼ばれる関数はmain ではなくマクロ名と一致している必要があります. また, マクロとして実行しているときになぜか #include <iostream> せずに呼べているものなどもきちんとincludeする必要があります.
参考
ROOT で使われる色をプレゼンで見やすく変更しよう - 宇宙線実験の覚え書き
ROOT では色の種類を番号で表します。ROOT で default で用意されており、通常よく使われるものは、1:黒 (K)、2:赤 (R)、3:緑 (G)、4:青 (B)、5:黄色 (Y)、6:マゼンタ (M)、7:シアン (C) です。 しかしこれらの色のうち、プレゼン中で使うべきではない色に緑 (G) と黄色 (Y) とシアン (C) があります。背景色が白の場合、線の色が明るすぎて、会場の状況によっては聴衆から識別が困難なためです*1 。ということで、このうち 2 色を少し見やすく変えてやりましょう。それぞれ深緑とオレンジにしちゃいます。シアンは他の良い代替案が思いつかないので、もう 7 色目を使うのは諦めましょう。 例えば以下の ROOT script で、color() と color_mod() を実行します。 ▲ color() の出力結果 ▲ color_mod() の出力結果 この 2 行で、色番号 3 と 5 の TColor への pointer を取り出し、 RGB の割合を再設定してやっています。この 2 行を ~/.rootlogon.C に追記すれば、いつでもこの設定で使用できます。
oxon.hatenablog.com
お絵描き
RGBで色を指定したい
ROOTのカラーを潰さずにやる方法です.
hist->SetLineColor((new TColor(4000, 0.5, 0.2, 0.3))->GetNumber());
// number R G BROOTは色を整数値に対して紐づけているので, ある整数値に色を定義して, その整数値を渡してやる必要があります. ちなみに kBlue とかも整数値が定義された変数です.
1179までの色は定義ずみなため, 適当に大きくて重複しない値をnumberのところには入れる必要があります.
歴史を感じる実装ですね.
範囲を塗りつぶしたい
ヒストグラムをふたつ作って, 下側領域の塗りつぶしを白にして重ねます.
ヒストグラム
ピークサーチがしたい
ROOTのTSpectrumクラスを使ってpeak searchをする
TSpectrum を使うと簡単にpeak searchができた。 の中のサンプルプログラムを動かしたら大体分かる。 ピークの最大数を適当に決めてTSpecrumのインスタンスをつくる。 Int_t maxpeaks = 10; TSpectrum *s = new TSpectrum(maxpeaks); ちなみにこれだとresolutionは1になる。今はピークが探せさえすればいいので気にしない。あとから TSpectum::SetResolutionで変えれる。resolution=1はピーク間の距離は3 sigmaに対応するのだとか。詳しくは TSpectrum::SetResolution を参照。 TSpectrum::Searchを使う。 h1 というTH1Fオブジェクトがあったら、 をするだけでいい。めっちゃ簡単。2つ目の引数はsigma。詳しくはマニュアルって書いてあるのであとで読む。3つ目はオプション。4つ目は省略してるけどthresholdを設定する。ピークサーチが終わると fNPeaks, fPositionXなどの変数に情報が入ってるので、 TSpectrum::GetNPeaks, TSpectrum::GetPositionX とかで取ってくる。 Float_t *xpeaks = s->GetPositionX(); あとはresolutionやthresholdをいじってoptimizeしたり、それはピークじゃないってやつをfitできるかどうかで除けばよいのかな。あとsmoothingしたりも。 コンパイルするときのオプションに、-lSpectrum が必要。これは しても出てこないので自分で Makefile に書いておく必要がある(?)。 に書いてあったけどもっと分かりやすいところに書いて欲しい。
gist.github.com
TTree
人からもらったTTreeをとりあえず見る
root -l tree.root でファイルを開き, .ls コマンドで中身を見ます. TTreeの名前 (ここではtree) がわかったら
tree->Print() // 概要とブランチ確認
tree->Show(0) // 0番目のイベントの中身確認
tree->Scan() // 流してスキャンこのあたりを実行するところから始めます.
TTreeを処理するマクロを自動生成する
tree->MakeClass() で, TTreeの名前を持ったヘッダーとソースが生成されます.
tree.C , tree.h が生成されますが, 特に tree.C を編集する必要があります.
void tree::Loop() 関数の中で, ヒストグラムを作り, ループの中でFillして, 最後にヒストグラムをDrawするなりSaveするなりしてください. 実行の仕方は Loop() 関数の冒頭にコメントで記載されています.
TTreeのブランチの設定を簡単にやる
自動生成ではなく, 自分のマクロに人のtreeの読み込みを組み込みたいことがあります.
auto file = TFile::Open("somefile.root")
auto tree = dynamic_cast<TTree*>(file->Get("tree"))などで読み込めますが, その後にやるブランチ設定が面倒です.
tree->MakeClass() を使うと, tree.h ができます. その中で, // Declaration of leaf types のコメントから始まる変数の定義, // List of branches で始まるbranchの定義, そして, void tree::Init 関数内にある fChain->SetBranchAddress() を全てコピペしてくれば, ブランチ設定は完了です. ただし, fChain の部分は tree とかに変える必要があります. また, 変数の定義がポインタであるものには, コピペした後 =0 としてやらないとエラーが出ます.
要らないブランチを読み込まない
tree->GetEntry(0); // required before SetBranchStatus
tree->SetBranchStatus("*",0); // 全部無効
tree->SetBranchStatus("value1",1); // 必要なものだけ有効にするTreeのブランチがstd::vectorの際に, std::vectorの関数を呼ぶ
tree->Draw("vector_value@.size()")
同質のTTreeをまとめて解析する
同じ構造のTTreeが別のファイルに入っている場合,
hadd コマンドで合成したファイルを作成するか, TChain を使います.
hadd combined_file.root fragment_*.rootTChainを使う場合は,
TChain *chain=new TChain("tree", "tree title");
chain->Add("fragment_1.root");
chain->Add("fragment_2.root");で, chainを1つのtreeのように扱えます. また, chain->Add() ではワイルドカードとして * も使えます.
TGraph
std::vectorで入っているデータをプロットしたい
多少面倒ですが,
auto tg = new TGraph(x_vec.size(), x_vec.data(), y_vec.data())
で愚直に書きます.