ユーザ用ツール

サイト用ツール


サイドバー

Menu

Latest

study:software:root:main

目次

Main

TH1・一次元ヒストグラム

  • rootのヒストグラム用のクラスはすべてTH1というクラスを継承している
  • 二次元ヒストでもTH1を継承している

ヒストグラムの使い方

TH1F *hist = new TH1F("name","title",binの数,下限,上限);
hist->Fill(n);//Fillはある数値に対応するbinをインクリメントする
hist->Draw();//Draw()で作ったヒストグラムを描くことができる

  • Double_tならTH1D、Int_tならTH1Iを使う。
  • nameはオブジェクトの名前で他のオブジェクトとかぶってはいけない。

TH1FやTH1DのFやDというのは各binの持っている値の型(byte数)を示す(内部的な話をすると各binの値は配列によって記録されている)。

例えばTH1IはInt_tなので、各binには整数型の値しか記憶できない。例えばweight0.5でFillしても縦軸の値はすべて整数になる。

(横軸、つまりbin幅は常にDouble_tの精度で記録されることに注意)。

Fill

hist->Fill(x,w);

  • wで重み付けしてFillする

FillRandom

hist->FillRandom("func",n);

  • TF1で定義した関数の分布に従って、Randomにn回Fillする
  • "func"のところはオブジェクト名をいれる(アドレスじゃない)
  • ntimesのデフォルト値は5000
  • rootの挙動を試すときに、使うことが多い

TH1::Fitと同様にgausやlandauでFillできる。

hist->FillRandom("gaus");


またhistogramの分布にしたがってFillもできる。かつて使ったことがない。

hist->FillRandom(hist2,ntimes);

  • こちらはアドレスをいれる

等幅ではないbin幅のヒストグラム

普通にヒストグラムを作るとbin幅は均等になる。

自由にbin幅を設定する場合は配列を使う。

double xbins[] = {0,4,5,10}
TH1F *hist = new TH1F("hist","",3,xbins);

Drawオプション

hist->Draw("オプション")

"AH":xy軸を表示しない
"E":エラーバーを表示
"C":滑らかな線で結ぶ
"L":折れ線グラフで表示
"P":点をプロットする
"SAME":前に描いていたヒストグラムに重ねて描く
etc...

オプションは大文字と小文字を区別しない

重ね書き

2つ以上のヒストグラムを重ね書きしたい場合は、2つ名以降のヒストグラムに対してsameオプションを使う。

またはTHStack(後述)を使う。

sameオプション、軸の再描画

TCanvas *c1 = new TCanvas("c1","");
h1->Draw();
h2->Draw("same")

しかしFillColorをつけていると、軸の目盛りがヒストグラムと被って消えてしまう。

こんなときはRedrawAxisを使うと軸が復活する。

c1->RedrawAxis()

またはTGaxisを新たに作って再描画という手もあるが面倒すぎるし、綺麗にかけないと思う。

THStack

これはヒストグラムを重ね書きするのではなく、複数のヒストグラムを足し上げて、一つのヒストグラムを作るためのクラス。

多次元ヒストグラムでも使える。

    THStack *hs = new THStack("hs","test stacked histograms");
    TH1F *h1 = new TH1F("h1","h1",100,-5,5);
    h1->SetFillColor(kRed);//あらかじめFillColorをSetしておく
    TH1F *h2 = new TH1F("h2","h2",100,-5,5);
    h2->SetFillColor(kBlue);
    TH1F *h3 = new TH1F("h3","h3",100,-5,5);
    h3->SetFillColor(kGreen);

    //h1,h2,h3を適宜Fillする
    h1->FillRandom("gaus",2000);
    h2->FillRandom("gaus",2000);
    h3->FillRandom("gaus",2000);

    hs->Add(h1);
    hs->Add(h2);
    hs->Add(h3);

    hs->Draw();

オプションでnostackにするとhistを積まずに単に重ね合わせをする。

    hs->Draw("nostack");

axisにtitleを付けたい場合は、宣言するときにtitleを;で区切る。

THStack *hs = new THStack("hs", "test; x title; y title");

TAxis・軸の設定

ヒストグラムの軸はTAxisというクラスになっている。

軸の設定を変えたいときはほぼすべてTAxisにアクセスすればいい。

もしも、x軸にアクセスしたいなら

hist->GetXaxis()

Y軸なら

hist->GetYaxis()

とすればいい。以下の文章は例として、X,Yのどちらかを書いているがテキトウに読み替えてください。

TGraphでも同様にすればTAxisにアクセス可能だが、TGraphの場合はDraw("ap")をしておかないとTAxisの実体が存在しないのでエラーになる。

それが嫌ならあらかじめTCanvasにDrawFrameをさせるという方法がある。

軸にタイトルをつける

軸にタイトルを付ける場合は下のように、コンストラクタで行うのが楽だと思う。

TH1F *hist = new TH1F("name","title;Xtitle;Ytitle;Ztitle",binの数,下限,上限);

(Z軸がないのであれば、"title;Xtitle;Ytitle"とする)。

また下のようにセットすることもできる。

hist->SetTitle("title;Xtitle;Ytitle;Ztitle");

又は

hist->SetXTitle("Xtitle");
hist->SetYTitle("Ytitle");
hist->SetZTitle("Ztitle");

しばしば一つのマクロでヒストグラムは大量に作るので、いちいちSetTitleで余計な行数を増やすのはあまりおすすめしない。コンストラクタで行うのがいいと思う。

ROOTのオブジェクトはほとんど名前とタイトルというものを持っている。上のようにやる代わりにTAxisにアクセスしてタイトルを変えてもいい。

が、たぶんTH1とそれに付随するTAxisはタイトルを共有している。

つまり、TH1のタイトルを"title;Xtitle"とすれば、x軸のTAxisのタイトルは"Xtitle"になる。なのでどちらのタイトルを変えても結果は同じ、だと思う。

軸のタイトル・目盛りの数字の書式設定

ROOTではタイトルはTitle、目盛りはLabelと呼んでいる。

hist->SetTitleSiZe(0.07,"x");

hist->SetLabelSiZe(0.04,"x");

軸の目盛りに数値ではなくて文字列を使う

まず適当なヒストグラムを作る。今回はbinが4つのヒストグラムを例にする。

TH1F *h = new TH1F("h","",4,0,4); //binの数だけが意味を持つので、下限、上限は適当でいい

次に各binに名前をつける。binの番号は0からではなく1から始まることに注意。

h->GetXaxis()->SetBinLabel(1,"A");
h->GetXaxis()->SetBinLabel(2,"B");
h->GetXaxis()->SetBinLabel(3,"C");
h->GetXaxis()->SetBinLabel(4,"D");

あとは普通にFillすればいい。

h->Fill(1);
...

binにつけた名前でFillすることも出来る。

h->Fill("A",weight); //weightは省略不可。

もしも、binの名前がつけられていない場合、空いているbinのうち一番左側から詰めていくのだと思われる。

軸の範囲を変える

hist->GetXaxis()->SetRange(first bin,last bin);//bin番号を引数にする
hist->GetXaxis()->SetRangeUser(first,last);//user座標を引数にする

y軸を変えたい場合はGetYaxis()をすればいい。


がしかし、ROOTにおいてx軸の範囲を変えるのはなかなか難しい場合が多い(私が言っているx軸の範囲を変えるというのはbinningを変えずに見た目の調整を行うことを意味している。)

例えば、すでにFillしてある、histogramの軸の範囲を上の方法で変えてDrawすると、おそらく意図したものにはならない。

つまり、histogramは配列でbinの値を記録しているので、histogramの軸の設定を書き換えても、binの順番は変わらないため、結局Fillされているbinの位置が変わってしまう。

逆にFillする前に軸の範囲だけを変えてしまうと、binの数は変わっていないので、これもおかしなことになる。

つまり、正しくは、どちらの場合もSetBins(n,xmin,xmax)でbinning自体を変えるべき。なのだが、この場合、(同じヒストグラムにするためには)元のbin幅と一致するように気をつけてbinの数を変更する必要があるので、面倒である。


なので、

canvas->DrawFrame(xmin,ymin,xmax,ymax);
hist->Draw("same");
canvas->RedrawAxis();

とするのが最も簡単。x軸dでもy軸でも使えるし、またTGraphやTF1の場合も利用できるので、知っておいた方がいいテクニックだと思う。

もう一回いうと、この方法が一番簡単。いろいろ調べたので間違いない。

軸の一部を拡大する

GUIでいつもやっているやつ。

hist->GetXaxis()->ZoomOut(Double_t factor, Double_t offset);

例えば、軸が0から100の場合、ZoomOut(0.5,0)とすると、25から75になる。第二引数はなんかよくわからん。

LogScaleにする、細かい目盛りを表示する

なぜかは知らないが、log scaleにするのはTPadのメソッドになっている。いや一応なぜかはわかるんだけど、直感的にはやっぱり不可解。

c1->SetLogy();
c1->SetLogy(false);//元に戻す

LogScaleはデフォルトでは10の指数しか表示しか表示されない。細かい目盛りというか、数字を表示するには、

hist->GetYaxis()->SetMoreLogLabels();
hist->GetYaxis()->SetMoreLogLabels(false);//元に戻す

と、なぜかTAxisにアクセスする必要がある。いや理屈はわかるんだけどさ。

軸の桁数を変える

桁数の許容最大数を指定する。指定された数値を超えると指数関数表示される。

デフォルト値は5。

 ((TGaxis*)hist->GetXaxis())->SetMaxDigits(n);
 ((TGaxis*)hist->GetYaxis())->SetMaxDigits(n);

例えばデフォルトでY軸は5桁まで許されているので、下の絵のようになるが、

 ((TGaxis*)hist->GetYaxis())->SetMaxDigits(4);

とすると最大4桁までなので下の絵のように指数表示される。

指数表示を禁止する

hist->GetYaxis()->SetNoExponent();
hist->GetYaxis()->SetNoExponent(falase);//元に戻す

軸の目盛りの間隔を調整する

hist->GetYaxis()->SetNdivisions(n);

  • n = n1 + 100*n2 + 10000*n3で表す、デフォルト値は510
    • n1は一番大きい仕切りの数、n2はその間に並んだ小さい仕切りの数、n3はその仕切の間の仕切りの数
    • おすすめはn2は5のままでn1だけ変える
  • ただしこの仕切の数は自動的にlabelの数字がキリが良くなるようにに調整される
    • SetNdivisions(n,false)とするとこの調整はせずに強制的に仕切りの数を適用する

統計情報ボックスの設定

Canvasの右上にある統計ボックスはTPaveStatsというクラスでヒストグラムをDrawしたときに自動的に生成される。

SetStats・統計ボックスの表示/非表示

hist->SetStats(1); //表示
hist->SetStats(0); //非表示

各統計情報の表示/非表示

gStyle->SetOptStat(stat);

引数はint又は文字列。デフォルト値は000001111

intを引数にする場合は9桁の10進数で各桁がksiourmenという順番で対応する。

(例えば101010101ならk=1,s=0,o=0,…という感じ)


文字列を引数にする場合は小文字が1、大文字が2に対応する。

(例えば、Kioならk=2,i=1,o=1他は0になる)

k = 1; kurtosis printed
k = 2; kurtosis and kurtosis error printed
s = 1; skewness printed
s = 2; skewness and skewness error printed
i = 1; integral of bins printed
o = 1; number of overflows printed
u = 1; number of underflows printed
r = 1; rms printed
r = 2; rms and rms error printed
m = 1; mean value printed
m = 2; mean and mean error values printed
e = 1; number of entries printed
n = 1; name of histogram is printed

もしもnameだけ表示をしたいと思って、gStyle->SetOptStat(1);をすると、これはデフォルト値に設定されるため、000000111となる。

かといってgStyle->SetOptStat(000000001);のように先頭が0で始まる場合は八進数で解釈されるので、やはりnameだけにはならない。

このため、余分に1をつけて10桁にして、gStyle->SetOptStat(1000000001);とする必要がある。

なんやねん、この仕様は。

Fit情報の表示

gStyle->SetOptFit(stat);

引数は10進数の4桁の整数で各桁がpcevに対応する。デフォルトは0111。

p = 1 確率の表示
c = 1 χ二乗/ndf
e = 1 エラーの表示(v=1になる)
v = 1 パラメータの名前と値の表示(固定パラメータを除く)
v = 2 固定されているパラメータも含めてすべて表示

統計ボックスの見た目を変える

GUIでも統計ボックスのところを右クリックすると変更できる。

//ボーダーサイズ
gStyle->SetStatBorderSize(Width_t size = 2) //
 //ボックスの背景色
gStyle->SetStatColor(Int_t color = 19)

//よく知らない
gStyle->SetStatFormat(const char* format = "6.4g")
gStyle->SetStatStyle(Style_t style = 1001)

//Font関係
gStyle->SetStatFont(Style_t font = 62)
gStyle->SetStatFontSize(Float_t size = 0)
gStyle->SetStatTextColor(Int_t color = 1)

//ボックスのサイズ?
gStyle->SetStatH(Float_t h = 0.1) //高さ
gStyle->SetStatW(Float_t w = 0.19) //幅

//ボックスの位置
gStyle->SetStatX(Float_t x = 0) //ボックスの右上の点x座標
gStyle->SetStatY(Float_t y = 0) //ボックスの右上の点のy座標

TPaveStatsのポインタを作る

この項目は次の2つ以上の統計ボックスを表示するで使う知識として書いてます

重要なことはヒストグラムをPaintするまでは統計ボックスは存在しないということ。

PaintはDrawしたあとに自動的に行われるので、コマンドラインで下のようにすることは可能。

[ ] hist->Draw();
[ ] TPaveStats *stat = hist->FindObject("stats"); //CINTではキャストは省略可能

しかし、スクリプト中ではPaintはスクリプト実行後行われるので、Paintを強制する必要がある。

hist->Draw();
c1->Update();
TPaveStats *stat = (TPaveStats*)hist->FindObject("stats");


このように、統計ボックスはヒストグラムのメンバ変数ではないので、TAxisのように直接呼び出すメソッドはTH1には存在しない。

しかも、なぜかヒストグラムの関数(fitして得られたTF1)と同じTListに加えられる。

やや隠しキャラ的な存在。

2つ以上の統計ボックスを表示する

例えば、Draw("same")をして2つのヒストグラムを作った場合は2つ目の統計ボックスは表示されない。

Draw("sames")にすると2つ目以降も統計ボックスが表示されるが、この場合一つ目の統計ボックスに重なって見えなくなってしまう。

重なった統計ボックスの位置を変えるには以下の作業を強いられる。

h1->Draw()
h2->Draw("sames")
c1->Update(); //paintする(画面に表示される)
TPaveStats *st = (TPaveStats*)h2->FindObject("stats");
st->SetX1NDC(x1); //x座標の始点、4行あるときの初期位置は0.78?
st->SetX2NDC(x2); //x座標の終点、4行あるときの初期位置は0.98?
st->SetY1NDC(y1); //y座標の始点、4行あるときの初期位置は0.775?
st->SetY2NDC(y2); //y座標の終点、4行あるときの初期位置は0.935?
c1->Modified(); //オブジェクトの設定変更を伝える

見て分かるようにきちんとROOTの仕様をマニアックに理解してないと正しく作ることができない。統計ボックスを2つ作ることを想定していないんだろうなあ。

あるいはDraw("sames")する前にgStyleで設定書き換えればもっと単純にできるのか。その方がいいかなあ。

GUIなら統計ボックスの位置をドラッグするだけでいいので、これに関してはGUIで操作のほうが楽だと思う。

macro.cxx:
void macro(){
 
    TH1F *h1 = new TH1F("h1","",100,-3,3);
    h1->SetLineColor(kRed);
    h1->FillRandom("gaus",6000);
    TH1F *h2 = new TH1F("h2","",100,-3,3);
    h2->SetLineColor(kBlue);
    h2->FillRandom("gaus",3000);
    h1->Draw();
    h2->Draw("sames");
    c1->Update();
    TPaveStats *st1 = (TPaveStats*)h1->FindObject("stats");
    st1->SetTextColor(kRed);
    TPaveStats *st2 = (TPaveStats*)h2->FindObject("stats");
    st2->SetTextColor(kBlue);
    st2->SetX1NDC(0.18);
    st2->SetX2NDC(0.38);
    c1->Modified();
 
}

ヒストグラムの演算

ヒストグラム同士の演算

猿でも番外編のここに書かれている方法は使えなかったのだが、古いrootならできるのだろうか。

hist->Add(hist1,x);//各binの値=現在の値+x*hist1の値
hist->Add(hist1,hist2,x,y);//各binの値=x*hist1の値+y*hist2の値

hist->Divide(hist1,x);//各binの値=現在の値/(x*hist1の値)
hist->Divide(hist1,hist2,x,y);//各binの値=(x*hist1の値)/(y*hist2の値)

hist->Multiply(hist1,x);//各binの値=現在の値*x*hist1の値
hist->Multiply(hist1,hist2,x,y);//各binの値=x*hist1の値*y*hist2の値

  • 定数x,yは省略すると1になる

hist->Scale(x);//各binの値=x*現在の値

bin幅などが揃っていないと演算はできない

複数ファイルの同一設定のhistogramを足したい場合はhaddを使う

Merge・複数のhistをmergeする

上で紹介しているhistの演算はbinの最大値や最小値が同じでないと足せないが、Mergeなら可能。細かい仕様はしらない。

TList *l = new TList;
l->Add(h1);
l->Add(h2);
l->Add(h3);

まず、上のようにTListを作って、mergeしたいヒストグラムをいれておく。

TH1F *h = new TH1F("h","title",100,-100,100);
h->Merge(l);
h->Draw();

上のようにMergeの引数としてTListをいれる。

Integral・ヒストグラムを積分する

hist->Integral(); //全Entry数を返す
hist->Integral(binx1,binx2); //ビン番号をいれる
hist->Integral(binx1,binx2,"width"); //ビンの中身×ビン幅で重み付けして積分する

TLegend・凡例の表示

ヒストグラムやグラフに凡例をいれるクラス。なぜTH1の下位項目なのかというツッコミをいれないでください。

TH1F *h = /**/;
TGraph *g = /**/;
TF1 *f = /**/;

//TLegend(x1,y1,x2,y2,"title")、位置はNDCで指定する(0−1の間の値)
//最後の引数の"title"はlegendに表示にされるタイトル、邪魔な場合はいれなくてもいい
TLegend *leg = new TLegend(0.1,0.7,0.48,0.9);


//第一引数はポインタ、第二引数は項目名、第三引数で表示したいattributeを指定
leg->AddEntry(h,"histogram","f");
leg->AddEntry(gr,"graph","lep");
leg->AddEntry(f,"function","l");
leg->Draw()

AddEntryの3つ目の引数は凡例を表示したいクラスに合わせて、下のように変える。

f TAttFill、主にヒストグラム
l TAttLine、グラフや関数などの線
p TAttMarker、グラフのマーカー
e error bar、グラフやヒストグラムのエラーバー

テキストを挿入するには

leg->AddEntry((TObject*)0, "Some text", "");

Legendの影や背景色は邪魔だと思う。以下のようにすると消せる

leg->SetBorderSize(0); //影をなくす
leg->SetFillStyle(0); //背景を透明にする

又は

gStyle->SetLegendBorderSize(0); //影をなくす

※Styleの変更はオブジェクトを生成する前に行うこと

BuildLegend

TPadに描かれているObjectのLegendを自動的につくる一見便利そうなメソッド。

TCanvas *c1 = new TCanvas("c1","c1");
h1->Draw();
h2->Draw();
c1->BuildLegend();

動作としてはTLegendを生成して、順番にTPadに描かれているObjectをAddEntryする。

Objectのtitleを項目名に、Objectが継承しているTAtt系のクラスをすべて凡例に表示する(例えばTAttLineを継承していれば、オプション"l"を追加という具合)。

がしかし、例えば、TGraphなら凡例にMarkerだけを出したい場合やLineだけを出したい場合もあるので、いまいち痒いところに手が届かない。

単純なメソッドなので、もっと便利なように自分で作ったほうがいい気がする。

Bin関係

FindBin・数値のビン番号を調べる

TH1のメソッドはビン番号を引数にすることが多いので、このメソッドはよく使う。

h1->FindBin(数値);
h1->FindFixBin(数値);

ビン番号は1から始まる。0ではないことに注意。

GetBinContent・あるビンのEntry数を調べる

h1->GetBinContent(ビン番号);

SetBinContent・ビンに直接値を代入する

h1->SetBinContent(binのnum,代入したいvol);

bin番号がわからければ使えないわけだが、多次元ヒストになってくるとbin番号を調べるのはかなり面倒。

Fill(x,w)で重み付けしてFillしたほうが簡単な気がする。

Rebin・binを区切り直す

ヒストグラムのbinをいくつかまとめて、binを区切り直すことができる。

ただ、例えば{0,1,2,3,4}を{0,2,4}と切り直すことはできるが、逆はできない。もはや情報が失われている。

TH1F h_rebin* = hist->Rebin(n);
TH1F h_rebin* = hist->Rebin(n,"h_rebin");//第二引数は新しく作るhistoの名前

double x[n] = {};
TH1F h_rebin* = hist->Rebin(n,"h_rebin",xbins);

TH2・二次元ヒストグラム

使い方

TH2F *h = new TH2F("name","title; X; Y", nbinsx, xlow, xup, nbinsy, ylow, yup);
h->Fill(x,y);

とりあえず使えばわかると思う。

Drawオプション

h->Draw("colz");

これが一番よく使う。zはカラーパレットを表示するオプションでcol以外でも使える。


h->Draw("arr");


legoは色なし、lego1はFillColorの色、lego2は値に応じて色を変える。

後ろ側が見えないので、画像にするときはあまり使わない。

h->FillColor(kYellow)
h->Draw("lego1");

h->Draw("lego2z");


等高線を表示する。

h->Draw("cont1z");

h->Draw("cont2");


boxの面積又は体積はデータに比例する。

h->Draw("box");


各binに数値をtextで表示。textの大きさはmarkerのsizeに比例。色はmarkerの色。

h->Draw("text");

これは他のオプションと組み合わせても有効。textの右に書かれている数値は角度を表す。

h->Draw("text45 colz");


散布図を描画。パッと見るとbin幅より細かい情報を持つように見えるが、たぶんbinの中でrandomにplotしているだけ。

h->Draw("scat");

MarkerのStyleはTAttMarkerのメソッドでスタイルを変えることができる。

gr->SetMarkerColor(3);
gr->SetMarkerSize(2);
gr->SetMarkerStyle(3);


h->Draw("surf1z");

h->Draw("surf3z");

Profile・プロファイルをする

二次元ヒストのx軸の各bin毎の、y値の平均とエラーを計算してグラフにするメソッド。rootの動きとしてはTH2からTProfileを生成している。

TProfile *pf = h2->ProfileX();
pf->Draw();

x値の平均とエラーが知りたい場合はProfileYを使う。

Projection・二次元histを一次元histに射影する

あるビンからビンまでの範囲での射影を作るメソッド。

TH1D *pj = h2->ProjectionX("object name",first,last);
pj->Draw();

X軸にスライスして、Y軸に射影するときはProjectionYを使う。

ポイントとしてはProjectionはたとえTH2Fだったとしても、生成されのはTH1Dであること。

FitSlice

TGraph/TGraphErrors

  • 各点にプロットしていく場合に使う
  • TGraphは生成された状態ではファイルに属さない(.lsしても表示できない)
  • TH1をメンバ変数に持っている
  • TH1はTArrayをメンバ変数に持っていたが、TGraphは普通の配列をメンバ変数に持っている
  • 衝撃的に使いにくい仕様な気がする

使い方

事前に配列を用意してグラフを作る

一番ノーマルな使い方。プロットしたいx,y座標をいれた配列をそれぞれ用意して、そのアドレスをTGraphに渡せばいい。

const Int_t n = 20;
Double_t x[n] = {0}, y[n] = {0};

for (Int_t i=0;i<n;++i) {
     x[i] = i*0.1;
     y[i] = 10*sin(x[i]+0.2);
}

TGraph *gr = new TGraph(n,x,y);
gr->Draw("AP");

  • nは配列の要素数
  • DrawオプションAはフレームを描く、Pは各点にマーカーを描く

error barをつけたい場合は、TGraphErrorsを使う

TGraphErrors *gr = new TGraphErrors(n,x,y,xerror,yerror);

SetPoint・点を追加してグラフを作る

SetPointを使うと、TGraphを作った後に各点の位置を変更したり追加することが出来る。

const Int_t n = 20;
TGraph *gr = new TGraph(n); //各点が(0,0)で初期化される

for (Int_t i=0;i<n;++i) {
     gr->SetPoint(i , i*0.1 , 10*sin(x[i]+0.2)); //SetPoint(点番号,x座標,y座標)
}

gr->Draw("AP");

SetPointを使うときに、最初に用意した点の数より大きな点番号を引数にした場合は自動的に配列を拡張して、点を追加することができる。

といっても、当然配列を拡張するのでコストは高い作業なので、最初から丁度いい大きさの配列を用意するほうが望ましい。

データファイルを読み込ませてグラフを作る

ifstreamで作らずに、データファイルからコンストラクタで一発でTGraphを作る方法。

0 0
1 10
2 20

のようなファイルを用意して

TGraph *gr = new TGraph("ex.dat","%lg %lg");

とする。

0 1 0
1 1 10
2 1 20

のようなファイルで1行目と3行目をデータとして使いたい場合は

TGraph *gr = new TGraph("ex.dat","%lg %*lg %lg");

又は

TGraph *gr = new TGraph("ex.dat","%lg %*s %lg");

とする。ただしsはchar*型として受け取る(が、スキップするだけなので、この場合どちらでも同じ)。

csvファイルの区切り文字(delimiter)を変えたい場合は

TGraph *gr = new TGraph("ex.dat","%lg %lg",",");

などとすればいい。

関数を使ってグラフを作る

TF1を使って初期化することも出来る。どういう場合に役立つかはよくわからない。

TGraph *g = new TGraph(f); //関数の形にプロット
TGraph *g = new TGraph(f,"d"); //導関数の形にプロット
TGraph *g = new TGraph(f,"i"); //関数の積分の形にプロット
TGraph *g = new TGraph(f,"I"); //正規化した積分の形にプロット

重ね書き

複数のグラフを重ね書きする場合は2つ目以降はAを除く。

gr1->Draw("AP");
gr2->Draw("P");
gr3->Draw("P");

Aオプションはフレームを描画するオプションである。

ソースは確認してないけど、おそらくオプションAをつけた場合はTGraphのメンバー変数のTH1にいったんDrawさせているんだと思う。だから2つ目以降のTGraphにAをつけてしまうと上書きされて消えてしまう。

なので、Aは2つ目以降はつけない。

あまり意識はしないと思うが、TH1はsameオプション無しでDrawすると、前に描かれていたオブジェクトをすべて消す性質を持つが、その他のオブジェクトはどんどん上書きしていく(常にsameオプションと思えばいい)。

TMultiGraph

複数のグラフをまとめてDrawするクラス。私は使わないと思うから書かないけど、3D表示とかも出来る。

{

    gStyle->SetMarkerStyle(20);
    gStyle->SetMarkerSize(0.7);

    TF1 *f1 = new TF1("f1","x^3+x^2+2",-5,5);
    TF1 *f2 = new TF1("f2","10*x^2+x - 50",-5,5);
    TF1 *f3 = new TF1("f3","-x -8",-5,5);

    TGraph *g1 = new TGraph(f1);
    g1->SetMarkerColor(kRed);
    TGraph *g2 = new TGraph(f2);
    g2->SetMarkerColor(kBlue);
    TGraph *g3 = new TGraph(f3);
    g2->SetMarkerColor(kOrange);

    TMultiGraph *mg = new TMultiGraph();

//    Axisにtitleを付けたい場合は
//    TMultiGraph *mg = new TMultiGraph("name","title; xtitle; ytitle");
//    又は
//    mg->SetTitle("title; xtitle; ytitle");

    mg->Add(g1);
    mg->Add(g2);
    mg->Add(g3);

    mg->Draw("ap");

}

TMultiGraphの何が便利かというと、普通にTGraphのDrawでグラフを複数同じキャンバスに描こうとすると、座標はaオプションを使用したグラフのものになるので、他のグラフをきちんと表示しようとするためには、座標軸を自分で調整する必要がある。

TMultiGraphはすべてのグラフが範囲に収まるように調整してくれる。逆に言うとそれぐらいしかいいところがないと思う。

Drawオプション

詳しくはここを見ましょう→http://root.cern.ch/root/html/TGraphPainter.html

"L" すべての点を単純に折れ線で結ぶ
"F" フィル領域を描く
"F1" "F"と同じだがX=0またはY=0の近くのフィル領域の描画には適さない
"F2" フィル領域にビンの中心を結ぶ折れ線を引く
"A" グラフを座標軸で囲む
"C" 滑らかな曲線を描く
"*" 各点に星印をつける
"P" 各点にグラフの現在のマーカーをつける
"B" 各点に棒グラフを描く
"[]" 誤差棒の端の縦/横の線だけを描く。このオプションはTGraphAsymmErrorsだけに使える。
"1" ylow = rwymin

軸のタイトルをつける

 
gr->SetTitle("title;Xtitle;Ytitle")

軸の範囲を変える

TH1の方で書いた軸の変え方を利用した方がいいと思う

下でY軸については設定できる。

gr->SetMaximum(x);
gr->SetMinimum(x);

X軸は下で成功した。

gr->GetXaxis()->SetLimits(min,max);

ちなみにLogScaleの時に、SetLimitsで軸の最小値を0にした場合は(最大値についても)無視される?みたい。

下のようにしても、理由は知らないが、軸に影響はない。

gr->GetXaxis()->SetRangeUser(min,max);

ちょっと違うけど、下でもできる。

gr->GetHistogram()->SetBins(てきとう,min,max);

ただし、これはヒストグラムのbinningを変えている荒業。

ファイルに保存する

普通にgr→Write()するだけなんだけど、少しだけ注意事項。

TGraphはデフォルトでオブジェクト名とタイトルがGraphになるようにしている。

TFile**		hoge.root	
 TFile*		hoge.root	
  KEY: TGraph	Graph;1	Graph

なので区別したいなら、したのように予め名前とtitleをつけたほうがいいと思う。

gr->SetName("name");
gr->SetTilte("title");
gr->Write();

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

ページ用ツール