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()
は最後のイテレータを示すようになります。