FitしたParameterをvectorに詰める

今回は、ROOTでFitting parameterをvectorに詰めるときにハマったのでメモします。

具体的には、Event by eventでヒストグラムをFitするのですが、そこで得られたParameterを配列として取りたいなぁとなりました。TF1にはDouble_t* GetParameters()という関数があり、複数のParameterをDouble_tの配列として取ってこれます。

root [] TH1D *hist = new TH1D("hist","hist",100,-10,10);
root [] TF1 *func = new TF1("func","gaus",-10,10);
root [] hist->FillRandom("gaus",10000); //カウス分布に従う乱数をヒストグラムに詰める
root [] hist->Fit("func");
root [] Double_t *prm;
root [] prm = func->GetParameters();
root [] prm[0]
(double) 800.72
root [] prm[1]
(double) 0.00567
root [] prm[2]
(double) 0.99295

とこんな感じで。これをstd::vectorに詰めることをしたい。 通常であれば、std::vectorのコンストラクタ

vector(InputIter first, InputIter last, const Allocator& a = Allocator());

(C++リファレンス)を使用して

Double_t [] hoge = {1.,2.,3.};
std::vector<Double_t> hoge_vec(hoge, hoge + sizeof(hoge)/sizeof(Double_t));

と、sizeof(配列オブジェクト)/sizeof(基本型)で配列のサイズを取れます。

しかし、上で定義したprmでこれをやると、サイズは1となります。なぜなら、これはただのポインタのサイズに過ぎないからです。現に、sizeof(prm)とすると、Fitting parameterの数に依らず8バイトを返します。 この戻り値Double_t*は配列を返すものではなく、ただのポインタを返すのです。そして、演算子[]にてポインタ計算をしているだけなのです!そうなもんで、配列要素にないものを叩いてもセグフォルを起こさないです。

では、vectorに詰めるにはどうすれば良いかというと、TF1::GetNPar()を使用します。

std::vector<Double_t> prm_vec(prm, prm + func->GetNPar());

こうすれば、prm+func->GetNPar()は最後のイテレータを示すようになります。

Shoichiro Masuoka

CNS, the Univ. of Tokyo. Dcotoral student

関連項目