ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/JetFitAnalyzer/src/jetfit.cpp
Revision: 1.14
Committed: Fri Nov 13 04:01:17 2009 UTC (15 years, 5 months ago) by dnisson
Branch: MAIN
CVS Tags: HEAD
Changes since 1.13: +0 -0 lines
State: FILE REMOVED
Log Message:
Removed now-obsolete jetfit.cpp and jetfit.h files

File Contents

# User Rev Content
1 dnisson 1.1 /* jetfit.cpp - Package to fit multi-Gaussian distributions to histograms
2     * Author: David Nisson
3     */
4    
5     #include <cstdlib>
6     #include <cmath>
7     #include <ctime>
8     #include <cstdio>
9     #include <cstring>
10     #include <cctype>
11     #include <iostream>
12     #include <fstream>
13     #include <sstream>
14     #include <string>
15     #include <vector>
16     #include <set>
17     #include <map>
18     #include <limits>
19     #include <exception>
20    
21     #include <TMinuit.h>
22     #include <TH1.h>
23     #include <TH2.h>
24     #include <TF2.h>
25     #include <TRandom3.h>
26     #include <Rtypes.h>
27     #include <TFormula.h>
28     #include <TSystem.h>
29 dnisson 1.12 #include <TMath.h>
30 dnisson 1.1
31     #include "UserCode/JetFitAnalyzer/interface/jetfit.h"
32    
33     #define PI 3.141592653
34    
35     #define MAX_GAUSS 3
36    
37     using namespace std;
38    
39     namespace jetfit {
40     // configurable options
41     bool ignorezero = false; // ignore zero bins when fitting
42    
43     model_def *mdef;
44    
45     model_def& curr_model_def() {
46     return *mdef;
47     }
48    
49     void set_model_def(model_def *_mdef) {
50     mdef = _mdef;
51     }
52    
53 dnisson 1.10 int model_def::get_ngauss() {
54 dnisson 1.1 return ngauss;
55     }
56    
57 dnisson 1.10 void model_def::set_ngauss(int _ngauss) {
58 dnisson 1.1 ngauss = _ngauss;
59     }
60    
61     // fit function
62 dnisson 1.10 double model_def::fit_fcn(double x, double y, double *xval) {
63     int npar_indiv = get_formula()->GetNpar();
64 dnisson 1.1 double val = 0.0;
65     for (int i = 0; i < ngauss; i++) {
66 dnisson 1.10 get_formula()->SetParameters(xval + i*npar_indiv);
67 dnisson 1.1 val += mdef->get_formula()->Eval(x, y);
68     }
69     return val;
70     }
71    
72     // TF2-compatible fit function
73     double fit_fcn_TF2(double *x, double *pval) {
74 dnisson 1.10 double val = mdef->fit_fcn(x[0], x[1], pval);
75 dnisson 1.1 return val;
76     }
77    
78 dnisson 1.9 // Integral of (model formula)^2 / chisquare sigma
79 dnisson 1.10 double model_def::formula_int(double xlo, double xhi, double ylo, double yhi,
80 dnisson 1.1 double *pval, double XbinSize, double YbinSize,
81     double *xval) {
82     double xstep = (xhi - xlo) / static_cast<double>(20);
83     double ystep = (yhi - ylo) / static_cast<double>(20);
84    
85     double fsum = 0.0;
86     double pval_old[256];
87 dnisson 1.10 int npar = get_formula()->GetNpar();
88 dnisson 1.1 if (npar > 256) {
89     cerr << "Parameter overload" << endl;
90     return 0.0;
91     }
92 dnisson 1.10 get_formula()->GetParameters(pval_old);
93     get_formula()->SetParameters(pval);
94 dnisson 1.1
95     for (int i = 0; i < 20; i++) {
96     for (int j = 0; j < 20; j++) {
97     double x = (static_cast<double>(i) + 0.5)*xstep + xlo;
98     double y = (static_cast<double>(j) + 0.5)*ystep + ylo;
99     double sig_cut = 1.0e-5;
100     double nu = XbinSize * YbinSize * fit_fcn(x, y, xval);
101 dnisson 1.10 double sigma = fabs(chisquare_error(0.0)) < sig_cut
102     ? sig_cut : chisquare_error(0.0);
103 dnisson 1.1
104 dnisson 1.10 fsum += pow(xstep * ystep * get_formula()->Eval(x, y), 2.0)
105 dnisson 1.1 / sigma / sigma;
106     }
107     }
108    
109 dnisson 1.10 get_formula()->SetParameters(pval_old);
110 dnisson 1.1 return fsum;
111     }
112    
113     // MINUIT objective function
114     void fcn(int &npar, double *grad, double &fcnval, double *xval, int iflag)
115     {
116     double chisquare = 0.0;
117     double XbinSize = (energy.Xhi - energy.Xlo)
118     / static_cast<double>(energy.bins.size());
119     double YbinSize = (energy.Yhi - energy.Ylo)
120     / static_cast<double>(energy.bins.at(0).size());
121     try {
122     // add errors in data points in histogram
123     for (int i = 0; i < energy.bins.size(); i++) {
124     for (int j = 0; j < energy.bins.at(i).size(); j++) {
125 dnisson 1.4 double x = (static_cast<double>(i) + 0.5) * (energy.Xhi - energy.Xlo)
126 dnisson 1.1 / static_cast<double>(energy.bins.size()) + energy.Xlo;
127     double y = (static_cast<double>(j) + 0.5) * (energy.Yhi - energy.Ylo)
128     / static_cast<double>(energy.bins.at(i).size()) + energy.Ylo;
129 dnisson 1.10 double nu = mdef->fit_fcn(x, y, xval) * XbinSize * YbinSize;
130 dnisson 1.1 double sig_cut = 1.0e-5;
131 dnisson 1.7 if (fabs(mdef->chisquare_error(energy.bins.at(i).at(j))) > sig_cut || !ignorezero) {
132 dnisson 1.1 chisquare += pow(energy.bins.at(i).at(j) - nu, 2.0)
133 dnisson 1.7 / pow(mdef->chisquare_error(energy.bins.at(i).at(j)), 2.0);
134 dnisson 1.3 }
135     else {
136 dnisson 1.1 chisquare += pow(energy.bins.at(i).at(j) - nu, 2.0)
137     / pow(sig_cut, 2.0);
138 dnisson 1.3 }
139 dnisson 1.1 }
140     }
141 dnisson 1.7
142 dnisson 1.1 // add errors due to Gaussians outside histogram
143 dnisson 1.6 double eps = 0.01; // accuracy set for this function
144 dnisson 1.10 for (int i = 0; i < mdef->get_ngauss(); i++) {
145 dnisson 1.3 double *pval = xval+i*(mdef->get_formula()->GetNpar());
146 dnisson 1.1 double par_x = pval[mdef->get_indiv_max_x()];
147     double par_y = pval[mdef->get_indiv_max_y()];
148     double par_sig = pval[3];
149 dnisson 1.7 double cutoff_rad = sqrt(-log(eps * 2.0 * PI * par_sig * par_sig
150     / pval[0]) * 2.0 * par_sig * par_sig);
151 dnisson 1.1
152     bool left = par_x < energy.Xlo + cutoff_rad;
153     bool right = par_x > energy.Xhi - cutoff_rad;
154     bool top = par_y > energy.Yhi - cutoff_rad;
155 dnisson 1.2 bool bottom = par_y < energy.Ylo + cutoff_rad;
156 dnisson 1.1
157     if (left) {
158     double xlo = par_x - cutoff_rad;
159     double xhi = energy.Xlo;
160     double ylo = energy.Ylo;
161     double yhi = energy.Yhi;
162 dnisson 1.10 chisquare += 2.0*mdef->formula_int(xlo, xhi, ylo, yhi, pval,
163 dnisson 1.1 XbinSize, YbinSize, xval);
164     }
165     if (right) {
166     double xlo = energy.Xhi;
167     double xhi = par_x + cutoff_rad;
168     double ylo = energy.Ylo;
169     double yhi = energy.Yhi;
170 dnisson 1.10 chisquare += 2.0*mdef->formula_int(xlo, xhi, ylo, yhi, pval,
171 dnisson 1.1 XbinSize, YbinSize, xval);
172     }
173     if (top) {
174     double xlo = left ? par_x - cutoff_rad : energy.Xlo;
175     double xhi = right ? par_x + cutoff_rad : energy.Xhi;
176     double ylo = energy.Yhi;
177     double yhi = par_y + cutoff_rad;
178 dnisson 1.10 chisquare += 2.0*mdef->formula_int(xlo, xhi, ylo, yhi, pval,
179 dnisson 1.1 XbinSize, YbinSize, xval);
180     }
181     if (bottom) {
182     double xlo = left ? par_x - cutoff_rad : energy.Xlo;
183     double xhi = right ? par_x + cutoff_rad : energy.Xhi;
184     double ylo = par_y - cutoff_rad;
185     double yhi = energy.Ylo;
186 dnisson 1.10 chisquare += 2.0*mdef->formula_int(xlo, xhi, ylo, yhi, pval,
187 dnisson 1.1 XbinSize, YbinSize, xval);
188     }
189     }
190 dnisson 1.7
191 dnisson 1.1 fcnval = chisquare;
192     }
193     catch (exception ex) {
194     cerr << "Exception in jetfit::fcn" << endl;
195     }
196     }
197    
198     bool get_ignorezero() {
199     return ignorezero;
200     }
201    
202     void set_ignorezero(bool _iz) {
203     ignorezero = _iz;
204     }
205    
206     TFormula * model_def::get_formula() {
207     return indiv_formula;
208     }
209    
210     void model_def::set_formula(TFormula *new_formula) {
211     indiv_formula = new_formula;
212     }
213    
214     void model_def::get_indiv_par(int i, string &name, double &start, double &step,
215     double &lo, double &hi) {
216     try {
217     name = indiv_par_names.at(i);
218     start = indiv_par_starts.at(i);
219     step = indiv_par_start_steps.at(i);
220     lo = indiv_par_lo.at(i);
221     hi = indiv_par_hi.at(i);
222     } catch (exception ex) {
223     cerr << "exception in jetfit::model_def::get_indiv_par" << endl;
224     }
225     }
226    
227     void model_def::set_indiv_par(int i, string name, double start, double step,
228     double lo, double hi) {
229     if (indiv_par_names.size() < i+1) {
230     indiv_par_names.resize(i+1);
231     indiv_par_starts.resize(i+1);
232     indiv_par_start_steps.resize(i+1);
233     indiv_par_lo.resize(i+1);
234     indiv_par_hi.resize(i+1);
235     }
236     try {
237     indiv_par_names.at(i) = name;
238     indiv_par_starts.at(i) = start;
239     indiv_par_start_steps.at(i) = step;
240     indiv_par_lo.at(i) = lo;
241     indiv_par_hi.at(i) = hi;
242     }
243     catch (exception ex) {
244     cerr << "exception in jetfit::model_def::set_indiv_par" << endl;
245     }
246     }
247    
248     int model_def::get_indiv_max_E() {
249     return indiv_max_E;
250     }
251    
252     void model_def::set_indiv_max_E(int _new_max_E) {
253     indiv_max_E = _new_max_E;
254     }
255    
256     int model_def::get_indiv_max_x() {
257     return indiv_max_x;
258     }
259    
260     void model_def::set_indiv_max_x(int new_max_x) {
261     indiv_max_x = new_max_x;
262     }
263    
264     int model_def::get_indiv_max_y() {
265     return indiv_max_y;
266     }
267    
268     void model_def::set_indiv_max_y(int new_max_y) {
269     indiv_max_y = new_max_y;
270     }
271    
272     unsigned model_def::get_n_special_par_sets() {
273     return special_par_starts.size();
274     }
275    
276     void model_def::get_special_par(int g, int i, double &pstart,
277     double &perr, double &plo, double &phi) {
278     try {
279     pstart = special_par_starts.at(g).at(i);
280     perr = special_par_start_steps.at(g).at(i);
281     plo = special_par_lo.at(g).at(i);
282     phi = special_par_hi.at(g).at(i);
283     } catch (exception ex) {
284     cerr << "Exception in model_def::get_special_par" << endl;
285     }
286     }
287    
288     void model_def::set_special_par(int g, int i, double pstart,
289     double perr, double plo, double phi) {
290     if (g+1 > special_par_starts.size()) {
291     special_par_starts.resize(g+1);
292     special_par_start_steps.resize(g+1);
293     special_par_lo.resize(g+1);
294     special_par_hi.resize(g+1);
295     }
296    
297     try {
298     if (i+1 > special_par_starts.at(g).size()) {
299     special_par_starts.at(g).resize(i+1);
300     special_par_start_steps.at(g).resize(i+1);
301     special_par_lo.at(g).resize(i+1);
302     special_par_hi.at(g).resize(i+1);
303     }
304    
305     special_par_starts.at(g).at(i) = pstart;
306     special_par_start_steps.at(g).at(i) = perr;
307     special_par_lo.at(g).at(i) = plo;
308     special_par_hi.at(g).at(i) = phi;
309     }
310     catch (exception ex) {
311     cerr << "exception in jetfit::model_def::set_special_par" << endl;
312     }
313     }
314    
315 dnisson 1.5 void fill_histo_with_vec(TH2 *hist, vector< vector<double> > &vec) {
316     for (int i = 0; i < vec.size(); i++) {
317     for (int j = 0; j < vec[i].size(); j++) {
318 dnisson 1.6 hist->SetBinContent(i+1, j+1, vec[i][j]);
319 dnisson 1.5 }
320     }
321     }
322    
323 dnisson 1.10 void model_def::par_init(TH2 *hist, TMinuit *gMinuit, vector<TString> &pars,
324 dnisson 1.1 double *pval, double *perr, double *plo, double *phi,
325 dnisson 1.13 int npar, FitResults r) {
326 dnisson 1.10 int npar1 = npar - get_formula()->GetNpar();
327 dnisson 1.1 bool init_spec_pars = false;
328 dnisson 1.10 if (ngauss <= get_n_special_par_sets()) {
329 dnisson 1.1 init_spec_pars = true;
330     for (int k = 0; k < ngauss; k++) {
331 dnisson 1.10 int ipar0 = k*get_formula()->GetNpar(); // index of indiv par 0
332     for (int l = 0; l < get_formula()->GetNpar(); l++) {
333 dnisson 1.1 int ipar = ipar0 + l;
334     if (ipar < npar)
335 dnisson 1.10 get_special_par(k, l, pval[ipar], perr[ipar], plo[ipar],
336 dnisson 1.1 phi[ipar]);
337     else
338     cerr << "WARNING: Attempt to set parameter out of index range!"
339     << endl;
340     }
341     }
342     }
343     else {
344     double XbinSize = (energy.Xhi - energy.Xlo)
345     / static_cast<double>(energy.bins.size());
346     double YbinSize = (energy.Xhi - energy.Xlo)
347     / static_cast<double>(energy.bins.at(0).size());
348     vector< vector<double> > sub_energy(energy.bins.size());
349     double max_sub, max_x = 0.0, max_y = 0.0;
350     double pval_other[256];
351 dnisson 1.3 max_sub = -(numeric_limits<double>::max());
352 dnisson 1.1 for (int i = 0; i < energy.bins.size(); i++) {
353     sub_energy[i].resize(energy.bins[i].size());
354     for (int j = 0; j < energy.bins[i].size(); j++) {
355     double x = static_cast<double>(i)*(energy.Xhi - energy.Xlo)
356     / static_cast<double>(energy.bins.size()) + energy.Xlo;
357     double y = static_cast<double>(j)*(energy.Yhi - energy.Ylo)
358     / static_cast<double>(energy.bins[i].size()) + energy.Ylo;
359     if (ngauss > 1) {
360 dnisson 1.6 // subtract integral of fit function
361 dnisson 1.1 try {
362     int npval_other = r.pval.at(r.pval.size()-1).size();
363     if (npval_other > 256) {
364     cerr << "Parameter overload" << endl;
365     return;
366     }
367     for (int k = 0; k < npval_other; k++) {
368     pval_other[k] = r.pval[r.pval.size()-1][k];
369     }
370     ngauss--;
371     double nu = fit_fcn(x, y, pval_other) * XbinSize * YbinSize;
372     ngauss++;
373 dnisson 1.6 sub_energy[i][j] = energy.bins[i][j] - nu;
374 dnisson 1.1 }
375     catch (exception ex) {
376     cerr << "Exception in par_init" << endl;
377     }
378     }
379     else {
380     sub_energy[i][j] = energy.bins[i][j];
381     }
382     }
383     }
384 dnisson 1.5 TH2D *hist_sub = new TH2D("hist_sub", "Subtracted histo",
385     sub_energy.size(), energy.Xlo,
386     energy.Xhi,
387     sub_energy[0].size(), energy.Ylo,
388     energy.Yhi);
389     fill_histo_with_vec(hist_sub, sub_energy);
390 dnisson 1.8 max_sub = 0.0;
391 dnisson 1.9 max_x = 0.0;
392     max_y = 0.0;
393 dnisson 1.8 for (int i = 1; i <= hist_sub->GetXaxis()->GetNbins(); i++) {
394     for (int j = 1; j <= hist_sub->GetYaxis()->GetNbins(); j++) {
395 dnisson 1.9 double nu = energy.bins[i-1][j-1] - sub_energy[i-1][j-1];
396     if (hist_sub->GetBinContent(i, j)
397 dnisson 1.10 - 3.0*pow(chisquare_error(nu), 2.0) > max_sub) {
398 dnisson 1.8 max_sub = hist_sub->GetBinContent(i, j);
399 dnisson 1.9 max_x = static_cast<double>(i-1)*XbinSize
400     + hist_sub->GetXaxis()->GetXmin();
401     max_y = static_cast<double>(j-1)*YbinSize
402     + hist_sub->GetYaxis()->GetXmin();
403 dnisson 1.8 }
404     }
405 dnisson 1.9 }
406 dnisson 1.1
407     for (int i = npar1; i < npar; i++) {
408 dnisson 1.10 if (get_indiv_max_E() == i - npar1) {
409 dnisson 1.9 pval[i] = max_sub / XbinSize / YbinSize;
410 dnisson 1.4 perr[i] = mdef->chisquare_error(pval[i])*0.5;
411 dnisson 1.1 plo[i] = 0.0;
412     phi[i] = 1.0e6;
413     }
414 dnisson 1.10 else if (get_indiv_max_x() == i - npar1) {
415 dnisson 1.1 pval[i] = max_x;
416     perr[i] = (energy.Xhi - energy.Xlo) / static_cast<double>(hist->GetXaxis()->GetNbins());
417     plo[i] = 0.0;
418     phi[i] = 0.0;
419     }
420 dnisson 1.10 else if (get_indiv_max_y() == i - npar1) {
421 dnisson 1.1 pval[i] = max_y;
422     perr[i] = (energy.Yhi - energy.Ylo) / static_cast<double>(hist->GetYaxis()->GetNbins());
423     plo[i] = 0.0;
424     phi[i] = 0.0;
425     }
426     else {
427     string dummy;
428 dnisson 1.10 get_indiv_par(i-npar1, dummy, pval[i], perr[i], plo[i], phi[i]);
429 dnisson 1.1 }
430     }
431     }
432 dnisson 1.10 int n_pars_to_set = init_spec_pars ? ngauss*get_formula()->GetNpar()
433 dnisson 1.1 : npar - npar1;
434     int init_par_to_set = init_spec_pars ? 0 : npar1;
435     for (int i = 0; i < n_pars_to_set; i++) {
436     double dummy;
437     string s;
438     int ipar = i + init_par_to_set;
439 dnisson 1.10 get_indiv_par(i % get_formula()->GetNpar(), s,
440 dnisson 1.1 dummy, dummy, dummy, dummy);
441     ostringstream par_oss;
442 dnisson 1.10 par_oss << s << ipar / (get_formula()->GetNpar()) << flush;
443 dnisson 1.1 try {
444     pars.at(ipar) = TString(par_oss.str());
445     }
446     catch (exception ex) {
447     cerr << "exception 2 in par_init" << endl;
448     }
449     int error_flag;
450     try {
451     gMinuit->mnparm(ipar, pars.at(ipar),
452     pval[ipar], perr[ipar], plo[ipar], phi[ipar], error_flag);
453     } catch (exception ex) {
454     cerr << "exception 3 in par_init" << endl;
455     }
456     }
457     }
458    
459 dnisson 1.13 FitResults fit_histo(TH2 *hist, vector<trouble> &t_vec,
460 dnisson 1.10 void (*cc_minuit)(TMinuit *, TH2 *, int),
461     int start_ngauss,
462     int rebinX, int rebinY,
463     double P_cutoff_val) {
464 dnisson 1.1 TMinuit *gMinuit = new TMinuit();
465     int npar_indiv = mdef->get_formula()->GetNpar();
466     int istat, erflg;
467 dnisson 1.13 FitResults r;
468 dnisson 1.1
469     gMinuit->SetFCN(fcn);
470     gMinuit->mninit(5, 6, 7);
471    
472     // set error def and machine accuracy
473     double cs_err_def = 1.0;
474     double fcn_eps = 0.2;
475     gMinuit->mnexcm("SET ERR", &cs_err_def, 1, erflg);
476     gMinuit->mnexcm("SET EPS", &fcn_eps, 1, erflg);
477    
478     // rebin histogram
479     TH2 *hist_rebinned;
480     if (rebinX > 1 && rebinY > 1)
481     hist_rebinned = hist->Rebin2D(rebinX, rebinY);
482     else
483     hist_rebinned = hist;
484    
485     r.hist_rebinned = hist_rebinned;
486     // load histogram into energies vector
487     energy.bins.resize(hist_rebinned->GetXaxis()->GetNbins());
488     for (int i = 0; i < energy.bins.size(); i++) {
489     energy.bins[i].resize(hist_rebinned->GetYaxis()->GetNbins());
490     for (int j = 0; j < energy.bins[i].size(); j++) {
491     energy.bins[i][j] = hist_rebinned->GetBinContent(i+1, j+1);
492     }
493     }
494    
495     energy.Xlo = hist->GetXaxis()->GetXmin();
496     energy.Xhi = hist->GetXaxis()->GetXmax();
497     energy.Ylo = hist->GetYaxis()->GetXmin();
498     energy.Yhi = hist->GetYaxis()->GetXmax();
499    
500     if (start_ngauss < 1) {
501     start_ngauss = 1;
502     }
503    
504 dnisson 1.11 for (mdef->set_ngauss(start_ngauss);
505     mdef->get_ngauss() <=
506     (MAX_GAUSS > start_ngauss ? MAX_GAUSS : start_ngauss);
507     mdef->set_ngauss(mdef->get_ngauss()+1)) {
508    
509     int ngauss = mdef->get_ngauss();
510 dnisson 1.1 t_vec.resize(t_vec.size() + 1);
511 dnisson 1.11 int npar = npar_indiv*mdef->get_ngauss();
512 dnisson 1.1 double pval[256], perr[256], plo[256], phi[256];
513     if (npar > 256) {
514     cerr << "Parameter overload" << endl;
515     return r;
516     }
517     vector<TString> pars(npar);
518    
519     // initialize parameters
520 dnisson 1.11 mdef->par_init(hist, gMinuit, pars, pval, perr, plo, phi, npar, r);
521 dnisson 1.5
522 dnisson 1.1 // minimize
523     double chisquare, edm, errdef;
524     int nvpar, nparx;
525     trouble t;
526     t.occ = T_NULL;
527     t.istat = 3;
528 dnisson 1.4 // fix sigmas of the Gaussians
529 dnisson 1.1 for (int i = 0; i < ngauss; i++) {
530     double parno[2];
531 dnisson 1.4 parno[0] = i*npar_indiv + 4;
532     gMinuit->mnexcm("FIX", parno, 1, erflg);
533 dnisson 1.1 }
534     gMinuit->mnexcm("SIMPLEX", 0, 0, erflg);
535     gMinuit->mnexcm("MIGRAD", 0, 0, erflg);
536     gMinuit->mnstat(chisquare, edm, errdef, nvpar, nparx, istat);
537     if (istat == 3) {
538     /* we're not concerned about MINOS errors right now
539     gMinuit->mnexcm("MINOS", 0, 0, erflg);
540     gMinuit->mnstat(chisquare, edm, errdef, nvpar, nparx, istat);
541     if (istat != 3) {
542     t.occ = T_MINOS;
543     t.istat = istat;
544     }
545     */
546     }
547     else {
548     t.occ = T_MIGRAD;
549     t.istat = istat;
550     }
551    
552     try {
553     if (t_vec.size() < ngauss) {
554     t_vec.resize(ngauss);
555     }
556     t_vec.at(ngauss-1) = t;
557     }
558     catch (exception ex) {
559     cerr << "exception in fit_histo" << endl;
560     }
561    
562     // put parameters in map
563     for (int i = 0; i < npar && i < 256; i++) {
564     int iuint; // internal parameter number
565     gMinuit->mnpout(i, pars[i], pval[i], perr[i], plo[i], phi[i], iuint);
566     }
567     vector<double> pval_copy(npar);
568     vector<double> perr_copy(npar);
569     vector<double> plo_copy(npar);
570     vector<double> phi_copy(npar);
571     for (int i = 0; i < npar && i < 256; i++) {
572     pval_copy[i] = pval[i];
573     perr_copy[i] = perr[i];
574     plo_copy[i] = plo[i];
575     phi_copy[i] = phi[i];
576     }
577     r.pars.push_back(pars);
578     r.pval.push_back(pval_copy);
579     r.perr.push_back(perr_copy);
580     r.plo.push_back(plo_copy);
581     r.phi.push_back(phi_copy);
582    
583     // execute user minuit code
584     if (cc_minuit != 0)
585     (*cc_minuit)(gMinuit, hist_rebinned, ngauss);
586    
587     int ndof = 0;
588     if (!ignorezero)
589     ndof = energy.bins.size() * energy.bins[0].size();
590     else {
591     for (int i = 0; i < energy.bins.size(); i++) {
592     for (int j = 0; j < energy.bins[i].size(); j++) {
593     if (energy.bins[i][j] > 1.0e-30)
594     ndof++;
595     }
596     }
597     }
598     ndof -= npar;
599    
600 dnisson 1.2 r.chisquare.push_back(chisquare);
601 dnisson 1.12 double P = TMath::Prob(chisquare, ndof);
602 dnisson 1.1 if (P > P_cutoff_val) {
603     break;
604     }
605     }
606    
607     delete gMinuit;
608     return r;
609     }
610     }