HistogramのFitを行うときにFunctionのDrawをしなくする

今回はTH1::FitをLoop内で用いるときに使用すると良いと思ったOptionを紹介します。 TH1::Fit関数は第二引数にオプションを入れることができます。Defaultでは、ヒストグラムをFitすると自動的にTF1のObjectを生成し、そのObjectのDrawを行います。

TH1D *hist = new TH1D("hist","hist",100,-10,10);
for (Int_t iData = 0, Int_t nData = 1e3; iData != nData; ++iData) {
	hist->Fill(gRandom->Gaus(0,1));
	}
hist->Fit("gaus","",-10,10);  // FitされたFunctionとHistogramも自動でDrawされる

Drawは基本的にTime Costがかかるので、Loopの中でDrawさせるのはあまりよろしくないかと思います。そのときに使える2つのオプション"N"と"0"のご紹介です!*1

*1: 実は、これを発見した理由は別にあります。Event displayを実装したコード中にてDrawしないで走らせたときにだけバグるという現象にハマり、Fitしたときの自動Drawが動いているのにCanvasオブジェクトがないことで止まってしまっていたことに気づいたのでした。そこで、自動DrawをDisableするオプションがないかと思い調べて知りました。

TH1::FitのReferenceによると、“N"はFitしたあとのFunctionオブジェクトを保持せず、“0"はDrawのみ行わない、とあります。これの違いは実際に使って確かめてみれば分かります。

root [] hist->Fit("gaus","n",-10,10);
root [] TF1 *func1 = hist->GetFunction("gaus"); 
root [] func1  //これはNULL Pointerになる
root [] (class TF1*) 0x0

root [] hist->Fit("gaus","0",-10,10);
root [] TF1 *func2 = hist->GetFunction("gaus");
root [] func2 //これはPointerを持っている
root [] (class TF1*) 0x1111111

“N"オプションを使っても、オブジェクトを持っていなければ煮るなり焼くなり出来ないじゃん…と思っても、大丈夫です。自分でTF1のオブジェクトを持っていればちゃんとそれに詰まります!

root [] TF1 *gausfunc = new TF1("gausfunc","gaus",-10,10);
root [] hist->Fit("gausfunc","n",-10,10); //これで*gausfunc にはFitしたParameter等が詰まっています
root [] Double_t *prm = gausfunc->GetParameters(); //gausfuncはNULLではないので、ちゃんとFitting parameterが取得できます

実際にLoopを回すときには合わせて"q"オプションもつけます(Fitしたあとに数値の画面Outputがなくなります)

参考までに、Fit Optionを変えてそれぞれ"ガウス分布に従う乱数を1000回発生させたヒストグラムを1000個作り、それをFitする"という操作の時間をTStopwatchにて計測し、その10000回の平均を取ったので、載せておきます。

Option Time cost (s)
”” 2.106
"q” 2.050
"q”,“goff” 2.052
"q0” 2.033
"qn” 2.011

"q","goff""q0" は内部的に違う挙動なのね。3番めの引数はGraphical Optionとしているし、確かに "goff" は表示させないだけでDrawはしていますからね。というところまでは納得なのですが、"goff"を付けたほうがDrawするより遅いとは!!! Errorの範囲でもないし…

Shoichiro Masuoka

CNS, the Univ. of Tokyo. Dcotoral student

関連項目