ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/JetFitAnalyzer/src/jetfit.cpp~
Revision: 1.2
Committed: Fri Sep 4 20:09:16 2009 UTC (15 years, 7 months ago) by dnisson
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +0 -0 lines
State: FILE REMOVED
Error occurred while calculating annotation data.
Log Message:
Deleting ~ clutter.

File Contents

# Content
1 /* jetfit.cpp - Package to fit multi-Gaussian distributions to histograms
2 * rewrite after accidental deletion 07-24-09
3 * Author: David Nisson
4 */
5
6 #include <cstdlib>
7 #include <cmath>
8 #include <ctime>
9 #include <cstdio>
10 #include <cstring>
11 #include <cctype>
12 #include <iostream>
13 #include <fstream>
14 #include <sstream>
15 #include <string>
16 #include <vector>
17 #include <set>
18 #include <map>
19 #include <limits>
20 #include <exception>
21
22 #include <TMinuit.h>
23 #include <TH1.h>
24 #include <TH2.h>
25 #include <TF2.h>
26 #include <TRandom3.h>
27 #include <Rtypes.h>
28 #include <TFormula.h>
29 #include <TSystem.h>
30
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 int ngauss; // number of Gaussians in current model
44
45 struct histo {
46 vector< vector<double> > bins;
47 double Xlo, Xhi, Ylo, Yhi;
48 } energy;
49
50
51 model_def *mdef;
52
53 model_def& curr_model_def() {
54 return *mdef;
55 }
56
57 void set_model_def(model_def *_mdef) {
58 mdef = _mdef;
59 }
60
61 int get_ngauss() {
62 return ngauss;
63 }
64
65 void set_ngauss(int _ngauss) {
66 ngauss = _ngauss;
67 }
68
69 // fit function
70 double fit_fcn(double x, double y, double *xval) {
71 int npar_indiv = mdef->get_formula()->GetNpar();
72 double val = 0.0;
73 for (int i = 0; i < ngauss; i++) {
74 mdef->get_formula()->SetParameters(xval + i*npar_indiv);
75 val += mdef->get_formula()->Eval(x, y);
76 }
77 return val;
78 }
79
80 // TF2-compatible fit function
81 double fit_fcn_TF2(double *x, double *pval) {
82 double val = fit_fcn(x[0], x[1], pval);
83 return val;
84 }
85
86 // Integral of model formula / chisquare sigma
87 double formula_int(double xlo, double xhi, double ylo, double yhi,
88 double *pval, double XbinSize, double YbinSize,
89 double *xval) {
90 double xstep = (xhi - xlo) / static_cast<double>(20);
91 double ystep = (yhi - ylo) / static_cast<double>(20);
92
93 double fsum = 0.0;
94 double pval_old[256];
95 int npar = mdef->get_formula()->GetNpar();
96 if (npar > 256) {
97 cerr << "Parameter overload" << endl;
98 return 0.0;
99 }
100 mdef->get_formula()->GetParameters(pval_old);
101 mdef->get_formula()->SetParameters(pval);
102
103 for (int i = 0; i < 20; i++) {
104 for (int j = 0; j < 20; j++) {
105 double x = (static_cast<double>(i) + 0.5)*xstep + xlo;
106 double y = (static_cast<double>(j) + 0.5)*ystep + ylo;
107 double sig_cut = 1.0e-5;
108 double nu = XbinSize * YbinSize * fit_fcn(x, y, xval);
109 double sigma = mdef->chisquare_error(nu) < sig_cut
110 ? sig_cut : mdef->chisquare_error(nu);
111
112 fsum += xstep * ystep * mdef->get_formula()->Eval(x, y)
113 / sigma / sigma;
114 }
115 }
116
117 mdef->get_formula()->SetParameters(pval_old);
118 return fsum;
119 }
120
121 // MINUIT objective function
122 void fcn(int &npar, double *grad, double &fcnval, double *xval, int iflag)
123 {
124 double chisquare = 0.0;
125 double XbinSize = (energy.Xhi - energy.Xlo)
126 / static_cast<double>(energy.bins.size());
127 double YbinSize = (energy.Yhi - energy.Ylo)
128 / static_cast<double>(energy.bins.at(0).size());
129 try {
130 // add errors in data points in histogram
131 for (int i = 0; i < energy.bins.size(); i++) {
132 for (int j = 0; j < energy.bins.at(i).size(); j++) {
133 double x = (static_cast<double>(i) + 0.5) * (energy.Xhi - energy.Xlo)
134 / static_cast<double>(energy.bins.size()) + energy.Xlo;
135 double y = (static_cast<double>(j) + 0.5) * (energy.Yhi - energy.Ylo)
136 / static_cast<double>(energy.bins.at(i).size()) + energy.Ylo;
137 double nu = fit_fcn(x, y, xval) * XbinSize * YbinSize;
138 double sig_cut = 1.0e-5;
139 if (mdef->chisquare_error(nu) > sig_cut || !ignorezero)
140 chisquare += pow(energy.bins.at(i).at(j) - nu, 2.0)
141 / pow(mdef->chisquare_error(nu), 2.0);
142 else
143 chisquare += pow(energy.bins.at(i).at(j) - nu, 2.0)
144 / pow(sig_cut, 2.0);
145 }
146 }
147
148 // add errors due to Gaussians outside histogram
149 double eps = 0.1; // accuracy set for this function
150 for (int i = 0; i < ngauss; i++) {
151 double *pval = xval+i*mdef->get_formula()->GetNpar();
152 double par_x = pval[mdef->get_indiv_max_x()];
153 double par_y = pval[mdef->get_indiv_max_y()];
154 double par_sig = pval[3];
155 double cutoff_rad = -log(eps * 2.0 * PI * par_sig * par_sig
156 / pval[0]);
157
158 bool left = par_x < energy.Xlo + cutoff_rad;
159 bool right = par_x > energy.Xhi - cutoff_rad;
160 bool top = par_y > energy.Yhi - cutoff_rad;
161 bool bottom = par_y > energy.Ylo + cutoff_rad;
162
163 if (left) {
164 double xlo = par_x - cutoff_rad;
165 double xhi = energy.Xlo;
166 double ylo = energy.Ylo;
167 double yhi = energy.Yhi;
168 chisquare += formula_int(xlo, xhi, ylo, yhi, pval,
169 XbinSize, YbinSize, xval);
170 }
171 if (right) {
172 double xlo = energy.Xhi;
173 double xhi = par_x + cutoff_rad;
174 double ylo = energy.Ylo;
175 double yhi = energy.Yhi;
176 chisquare += formula_int(xlo, xhi, ylo, yhi, pval,
177 XbinSize, YbinSize, xval);
178 }
179 if (top) {
180 double xlo = left ? par_x - cutoff_rad : energy.Xlo;
181 double xhi = right ? par_x + cutoff_rad : energy.Xhi;
182 double ylo = energy.Yhi;
183 double yhi = par_y + cutoff_rad;
184 chisquare += formula_int(xlo, xhi, ylo, yhi, pval,
185 XbinSize, YbinSize, xval);
186 }
187 if (bottom) {
188 double xlo = left ? par_x - cutoff_rad : energy.Xlo;
189 double xhi = right ? par_x + cutoff_rad : energy.Xhi;
190 double ylo = par_y - cutoff_rad;
191 double yhi = energy.Ylo;
192 chisquare += formula_int(xlo, xhi, ylo, yhi, pval,
193 XbinSize, YbinSize, xval);
194 }
195 }
196
197 fcnval = chisquare;
198 }
199 catch (exception ex) {
200 cerr << "Exception in jetfit::fcn" << endl;
201 }
202 }
203
204 bool get_ignorezero() {
205 return ignorezero;
206 }
207
208 void set_ignorezero(bool _iz) {
209 ignorezero = _iz;
210 }
211
212 TFormula * model_def::get_formula() {
213 return indiv_formula;
214 }
215
216 void model_def::set_formula(TFormula *new_formula) {
217 indiv_formula = new_formula;
218 }
219
220 void model_def::get_indiv_par(int i, string &name, double &start, double &step,
221 double &lo, double &hi) {
222 try {
223 name = indiv_par_names.at(i);
224 start = indiv_par_starts.at(i);
225 step = indiv_par_start_steps.at(i);
226 lo = indiv_par_lo.at(i);
227 hi = indiv_par_hi.at(i);
228 } catch (exception ex) {
229 cerr << "exception in jetfit::model_def::get_indiv_par" << endl;
230 }
231 }
232
233 void model_def::set_indiv_par(int i, string name, double start, double step,
234 double lo, double hi) {
235 if (indiv_par_names.size() < i+1) {
236 indiv_par_names.resize(i+1);
237 indiv_par_starts.resize(i+1);
238 indiv_par_start_steps.resize(i+1);
239 indiv_par_lo.resize(i+1);
240 indiv_par_hi.resize(i+1);
241 }
242 try {
243 indiv_par_names.at(i) = name;
244 indiv_par_starts.at(i) = start;
245 indiv_par_start_steps.at(i) = step;
246 indiv_par_lo.at(i) = lo;
247 indiv_par_hi.at(i) = hi;
248 }
249 catch (exception ex) {
250 cerr << "exception in jetfit::model_def::set_indiv_par" << endl;
251 }
252 }
253
254 int model_def::get_indiv_max_E() {
255 return indiv_max_E;
256 }
257
258 void model_def::set_indiv_max_E(int _new_max_E) {
259 indiv_max_E = _new_max_E;
260 }
261
262 int model_def::get_indiv_max_x() {
263 return indiv_max_x;
264 }
265
266 void model_def::set_indiv_max_x(int new_max_x) {
267 indiv_max_x = new_max_x;
268 }
269
270 int model_def::get_indiv_max_y() {
271 return indiv_max_y;
272 }
273
274 void model_def::set_indiv_max_y(int new_max_y) {
275 indiv_max_y = new_max_y;
276 }
277
278 unsigned model_def::get_n_special_par_sets() {
279 return special_par_starts.size();
280 }
281
282 void model_def::get_special_par(int g, int i, double &pstart,
283 double &perr, double &plo, double &phi) {
284 try {
285 pstart = special_par_starts.at(g).at(i);
286 perr = special_par_start_steps.at(g).at(i);
287 plo = special_par_lo.at(g).at(i);
288 phi = special_par_hi.at(g).at(i);
289 } catch (exception ex) {
290 cerr << "Exception in model_def::get_special_par" << endl;
291 }
292 }
293
294 void model_def::set_special_par(int g, int i, double pstart,
295 double perr, double plo, double phi) {
296 if (g+1 > special_par_starts.size()) {
297 special_par_starts.resize(g+1);
298 special_par_start_steps.resize(g+1);
299 special_par_lo.resize(g+1);
300 special_par_hi.resize(g+1);
301 }
302
303 try {
304 if (i+1 > special_par_starts.at(g).size()) {
305 special_par_starts.at(g).resize(i+1);
306 special_par_start_steps.at(g).resize(i+1);
307 special_par_lo.at(g).resize(i+1);
308 special_par_hi.at(g).resize(i+1);
309 }
310
311 special_par_starts.at(g).at(i) = pstart;
312 special_par_start_steps.at(g).at(i) = perr;
313 special_par_lo.at(g).at(i) = plo;
314 special_par_hi.at(g).at(i) = phi;
315 }
316 catch (exception ex) {
317 cerr << "exception in jetfit::model_def::set_special_par" << endl;
318 }
319 }
320
321 // translation of CERN's ERFC function
322 double erfc(double x) {
323 bool lef = false;
324 double p2[5], q2[5];
325
326 const double z1 = 1.0, hf = z1/2.0, c1 = 0.56418958;
327 const double vmax = 7.0;
328 const double switch_ = 4.0;
329
330 double p10 = 3.6767877, q10 = 3.2584593, p11 = -9.7970465e-2;
331 p2[0] = 7.3738883;
332 q2[0] = 7.3739609;
333 p2[1] = 6.8650185;
334 q2[1] = 1.5184908e1;
335 p2[2] = 3.0317993;
336 q2[2] = 1.2795530e1;
337 p2[3] = 5.6316962e-1;
338 q2[3] = 5.3542168;
339 p2[4] = 4.3187787e-5;
340 q2[4] = 1.0;
341
342 double p30 = -1.2436854e-1, q30 = 4.4091706e-1, p31 = -9.6821036e-2;
343
344 double v = fabs(x);
345 double y, h, hc, ap, aq;
346 if (v < hf) {
347 y = v*v;
348 h = x*(p10 + p11*y)/(q10 + y);
349 hc = 1.0 - h;
350 }
351 else {
352 if (v < switch_) {
353 ap = p2[4];
354 aq = q2[4];
355 for (int i = 3; i >= 0; i--) {
356 ap = p2[i] + v*ap;
357 aq = q2[i] + v*aq;
358 }
359 hc = exp(-v*v)*ap/aq;
360 h = 1.0 - hc;
361 }
362 else if (v < vmax) {
363 y = 1/v/v;
364 hc = exp(-v*v)*(c1 + y*(p30 + p31*y)/(q30 + y))/v;
365 h = 1.0 - hc;
366 }
367 // for very big values we can save us any calculation
368 // and the FP-exceptions from exp
369 else {
370 h = 1.0;
371 hc = 0.0;
372 }
373 if (x < 0) {
374 h = -h;
375 hc = 2.0 - hc;
376 }
377 }
378 if (lef) {
379 return h;
380 }
381 else {
382 return hc;
383 }
384 }
385
386 // translation of CERN's PROB function
387 double prob(double x, int n) {
388 const char *name = "PROB";
389 char errtxt[80];
390
391 const double r1 = 1.0,
392 hf = r1/2.0, th = r1/3.0, f1 = 2.0*r1/9.0;
393 const double c1 = 1.128379167095513;
394 const int nmax = 300;
395 // maximum chi2 per df for df >= 2., if chi2/df > chipdf prob=0
396 const double chipdf = 100.0;
397 const double xmax = 174.673, xmax2 = 2.0*xmax;
398 const double xlim = 24.0;
399 const double eps = 1e-30;
400
401 double y = x;
402 double u = hf*y;
403 double h, w, s, t, fi, e;
404 int m;
405 if (n < 0) {
406 h = 0.0;
407 sprintf(errtxt, "n = %d < 1", n);
408 cerr << "PROB: G100.1: "<<errtxt;
409 }
410 else if (y < 0.0) {
411 h = 0.0;
412 sprintf(errtxt, "x = %f < 0", n);
413 cerr << "PROB: G100.2: "<<errtxt;
414 }
415 else if (y == 0.0 || n/20 > y) {
416 h = 1.0;
417 }
418 else if (n == 1) {
419 w = sqrt(u);
420 if (w < xlim) {
421 h = erfc(w);
422 }
423 else {
424 h = 0.0;
425 }
426 }
427 else if (n > nmax) {
428 s = r1 / ((double)n);
429 t = f1 * s;
430 w = (pow(y*s, th) - (1.0 - t)) / sqrt(2.0*t);
431 if (w < -xlim) {
432 h = 1.0;
433 }
434 else if (w < xlim) {
435 h = hf * erfc(w);
436 }
437 else {
438 h = 0.0;
439 }
440 }
441 else {
442 m = n/2;
443 if (u < xmax2 && (y/n) <= chipdf) {
444 s = exp(-hf*u);
445 t = s;
446 e = s;
447 if (2*m == n) {
448 fi = 0.0;
449 for (int i = 1; i < m; i++) {
450 fi += 1.0;
451 t = u*t/fi;
452 s += t;
453 }
454 h = s*e;
455 }
456 else {
457 fi = 1.0;
458 for (int i = 1; i < m; i++) {
459 fi += 2.0;
460 t = t*y/fi;
461 s += t;
462 }
463 w = sqrt(u);
464 if (w < xlim) {
465 h = c1*w*s*e + erfc(w);
466 }
467 else {
468 h = 0.0;
469 }
470 }
471 }
472 else {
473 h = 0.0;
474 }
475 }
476 if (h > eps) {
477 return h;
478 }
479 else {
480 return 0.0;
481 }
482 }
483
484 void par_init(TH2 *hist, TMinuit *gMinuit, vector<TString> &pars,
485 double *pval, double *perr, double *plo, double *phi,
486 int npar, results r) {
487 int npar1 = npar - mdef->get_formula()->GetNpar();
488 bool init_spec_pars = false;
489 if (ngauss <= mdef->get_n_special_par_sets()) {
490 init_spec_pars = true;
491 for (int k = 0; k < ngauss; k++) {
492 int ipar0 = k*mdef->get_formula()->GetNpar(); // index of par 0
493 for (int l = 0; l < mdef->get_formula()->GetNpar(); l++) {
494 int ipar = ipar0 + l;
495 if (ipar < npar)
496 mdef->get_special_par(k, l, pval[ipar], perr[ipar], plo[ipar],
497 phi[ipar]);
498 else
499 cerr << "WARNING: Attempt to set parameter out of index range!"
500 << endl;
501 }
502 }
503 }
504 else {
505 double XbinSize = (energy.Xhi - energy.Xlo)
506 / static_cast<double>(energy.bins.size());
507 double YbinSize = (energy.Xhi - energy.Xlo)
508 / static_cast<double>(energy.bins.at(0).size());
509 vector< vector<double> > sub_energy(energy.bins.size());
510 double max_sub, max_x = 0.0, max_y = 0.0;
511 double pval_other[256];
512 max_sub = -(numeric_limits<double>::infinity());
513 for (int i = 0; i < energy.bins.size(); i++) {
514 sub_energy[i].resize(energy.bins[i].size());
515 for (int j = 0; j < energy.bins[i].size(); j++) {
516 double x = static_cast<double>(i)*(energy.Xhi - energy.Xlo)
517 / static_cast<double>(energy.bins.size()) + energy.Xlo;
518 double y = static_cast<double>(j)*(energy.Yhi - energy.Ylo)
519 / static_cast<double>(energy.bins[i].size()) + energy.Ylo;
520 if (ngauss > 1) {
521 // subtract 4*sigma plus integral of fit function
522 try {
523 int npval_other = r.pval.at(r.pval.size()-1).size();
524 if (npval_other > 256) {
525 cerr << "Parameter overload" << endl;
526 return;
527 }
528 for (int k = 0; k < npval_other; k++) {
529 pval_other[k] = r.pval[r.pval.size()-1][k];
530 }
531 ngauss--;
532 double nu = fit_fcn(x, y, pval_other) * XbinSize * YbinSize;
533 ngauss++;
534 sub_energy[i][j] = energy.bins[i][j] - nu
535 - 4.0*mdef->chisquare_error(nu);
536 }
537 catch (exception ex) {
538 cerr << "Exception in par_init" << endl;
539 }
540 }
541 else {
542 sub_energy[i][j] = energy.bins[i][j];
543 }
544 if (sub_energy[i][j] > max_sub) {
545 max_sub = sub_energy[i][j];
546 max_x = x;
547 max_y = y;
548 }
549 }
550 }
551
552 for (int i = npar1; i < npar; i++) {
553 if (mdef->get_indiv_max_E() == i - npar1) {
554 double nu = 0.0;
555 if (ngauss > 1) {
556 nu = fit_fcn(max_x, max_y, pval_other) * XbinSize * YbinSize;
557 }
558 pval[i] = max_sub + (ngauss > 1 ? 4.0*mdef->chisquare_error(nu)
559 : 0.0);
560 perr[i] = mdef->chisquare_error(pval[i])*0.1;
561 plo[i] = 0.0;
562 phi[i] = 1.0e6;
563 }
564 else if (mdef->get_indiv_max_x() == i - npar1) {
565 pval[i] = max_x;
566 perr[i] = (energy.Xhi - energy.Xlo) / static_cast<double>(hist->GetXaxis()->GetNbins());
567 plo[i] = 0.0;
568 phi[i] = 0.0;
569 }
570 else if (mdef->get_indiv_max_y() == i - npar1) {
571 pval[i] = max_y;
572 perr[i] = (energy.Yhi - energy.Ylo) / static_cast<double>(hist->GetYaxis()->GetNbins());
573 plo[i] = 0.0;
574 phi[i] = 0.0;
575 }
576 else {
577 string dummy;
578 mdef->get_indiv_par(i-npar1, dummy, pval[i], perr[i], plo[i], phi[i]);
579 }
580 }
581 }
582 int n_pars_to_set = init_spec_pars ? ngauss*mdef->get_formula()->GetNpar()
583 : npar - npar1;
584 int init_par_to_set = init_spec_pars ? 0 : npar1;
585 for (int i = 0; i < n_pars_to_set; i++) {
586 double dummy;
587 string s;
588 int ipar = i + init_par_to_set;
589 mdef->get_indiv_par(i % mdef->get_formula()->GetNpar(), s,
590 dummy, dummy, dummy, dummy);
591 ostringstream par_oss;
592 par_oss << s << ipar / (mdef->get_formula()->GetNpar()) << flush;
593 try {
594 pars.at(ipar) = TString(par_oss.str());
595 }
596 catch (exception ex) {
597 cerr << "exception 2 in par_init" << endl;
598 }
599 int error_flag;
600 try {
601 gMinuit->mnparm(ipar, pars.at(ipar),
602 pval[ipar], perr[ipar], plo[ipar], phi[ipar], error_flag);
603 } catch (exception ex) {
604 cerr << "exception 3 in par_init" << endl;
605 }
606 }
607 }
608
609 results fit_histo(TH2 *hist, vector<trouble> &t_vec,
610 void (*cc_minuit)(TMinuit *, TH2 *, int),
611 int start_ngauss,
612 int rebinX, int rebinY,
613 double P_cutoff_val) {
614 TMinuit *gMinuit = new TMinuit();
615 int npar_indiv = mdef->get_formula()->GetNpar();
616 int istat, erflg;
617 results r;
618
619 gMinuit->SetFCN(fcn);
620 gMinuit->mninit(5, 6, 7);
621
622 // set error def and machine accuracy
623 double cs_err_def = 1.0;
624 double fcn_eps = 0.2;
625 gMinuit->mnexcm("SET ERR", &cs_err_def, 1, erflg);
626 gMinuit->mnexcm("SET EPS", &fcn_eps, 1, erflg);
627
628 // rebin histogram
629 TH2 *hist_rebinned;
630 if (rebinX > 1 && rebinY > 1)
631 hist_rebinned = hist->Rebin2D(rebinX, rebinY);
632 else
633 hist_rebinned = hist;
634
635 r.hist_rebinned = hist_rebinned;
636 // load histogram into energies vector
637 energy.bins.resize(hist_rebinned->GetXaxis()->GetNbins());
638 for (int i = 0; i < energy.bins.size(); i++) {
639 energy.bins[i].resize(hist_rebinned->GetYaxis()->GetNbins());
640 for (int j = 0; j < energy.bins[i].size(); j++) {
641 energy.bins[i][j] = hist_rebinned->GetBinContent(i+1, j+1);
642 }
643 }
644
645 energy.Xlo = hist->GetXaxis()->GetXmin();
646 energy.Xhi = hist->GetXaxis()->GetXmax();
647 energy.Ylo = hist->GetYaxis()->GetXmin();
648 energy.Yhi = hist->GetYaxis()->GetXmax();
649
650 if (start_ngauss < 1) {
651 start_ngauss = 1;
652 }
653
654 for (ngauss = start_ngauss;
655 ngauss <= (MAX_GAUSS > start_ngauss ? MAX_GAUSS : start_ngauss);
656 ngauss++) {
657 t_vec.resize(t_vec.size() + 1);
658 int npar = npar_indiv*ngauss;
659 double pval[256], perr[256], plo[256], phi[256];
660 if (npar > 256) {
661 cerr << "Parameter overload" << endl;
662 return r;
663 }
664 vector<TString> pars(npar);
665
666 // initialize parameters
667 par_init(hist, gMinuit, pars, pval, perr, plo, phi, npar, r);
668
669 // minimize
670 double chisquare, edm, errdef;
671 int nvpar, nparx;
672 trouble t;
673 t.occ = T_NULL;
674 t.istat = 3;
675 // fix the N values and sigmas of the Gaussians
676 for (int i = 0; i < ngauss; i++) {
677 double parno[2];
678 parno[0] = i*npar_indiv + 1;
679 parno[1] = i*npar_indiv + 4;
680 gMinuit->mnexcm("FIX", parno, 2, erflg);
681 }
682 gMinuit->mnexcm("SIMPLEX", 0, 0, erflg);
683 gMinuit->mnexcm("MIGRAD", 0, 0, erflg);
684 // release N values and sigmas, fix mu_x and mu_y
685 for (int i = 0; i < ngauss; i++) {
686 double parno[4];
687 parno[0] = i*npar_indiv + 1;
688 parno[1] = i*npar_indiv + 2;
689 parno[2] = i*npar_indiv + 3;
690 parno[3] = i*npar_indiv + 4;
691 gMinuit->mnexcm("RELEASE", parno, 1, erflg);
692 gMinuit->mnexcm("RELEASE", parno+3, 1, erflg);
693 gMinuit->mnexcm("FIX", parno+1, 2, erflg);
694 }
695 gMinuit->mnexcm("MIGRAD", 0, 0, erflg);
696 // release mu_x and mu_y
697 for (int i = 0; i < ngauss; i++) {
698 double parno[4];
699 parno[0] = i*npar_indiv + 1;
700 parno[1] = i*npar_indiv + 2;
701 parno[2] = i*npar_indiv + 3;
702 parno[3] = i*npar_indiv + 4;
703 gMinuit->mnexcm("RELEASE", parno+1, 2, erflg);
704 }
705 gMinuit->mnexcm("MIGRAD", 0, 0, erflg);
706 gMinuit->mnstat(chisquare, edm, errdef, nvpar, nparx, istat);
707 if (istat == 3) {
708 /* we're not concerned about MINOS errors right now
709 gMinuit->mnexcm("MINOS", 0, 0, erflg);
710 gMinuit->mnstat(chisquare, edm, errdef, nvpar, nparx, istat);
711 if (istat != 3) {
712 t.occ = T_MINOS;
713 t.istat = istat;
714 }
715 */
716 }
717 else {
718 t.occ = T_MIGRAD;
719 t.istat = istat;
720 }
721
722 try {
723 if (t_vec.size() < ngauss) {
724 t_vec.resize(ngauss);
725 }
726 t_vec.at(ngauss-1) = t;
727 }
728 catch (exception ex) {
729 cerr << "exception in fit_histo" << endl;
730 }
731
732 // put parameters in map
733 for (int i = 0; i < npar && i < 256; i++) {
734 int iuint; // internal parameter number
735 gMinuit->mnpout(i, pars[i], pval[i], perr[i], plo[i], phi[i], iuint);
736 }
737 vector<double> pval_copy(npar);
738 vector<double> perr_copy(npar);
739 vector<double> plo_copy(npar);
740 vector<double> phi_copy(npar);
741 for (int i = 0; i < npar && i < 256; i++) {
742 pval_copy[i] = pval[i];
743 perr_copy[i] = perr[i];
744 plo_copy[i] = plo[i];
745 phi_copy[i] = phi[i];
746 }
747 r.pars.push_back(pars);
748 r.pval.push_back(pval_copy);
749 r.perr.push_back(perr_copy);
750 r.plo.push_back(plo_copy);
751 r.phi.push_back(phi_copy);
752
753 // execute user minuit code
754 if (cc_minuit != 0)
755 (*cc_minuit)(gMinuit, hist_rebinned, ngauss);
756
757 int ndof = 0;
758 if (!ignorezero)
759 ndof = energy.bins.size() * energy.bins[0].size();
760 else {
761 for (int i = 0; i < energy.bins.size(); i++) {
762 for (int j = 0; j < energy.bins[i].size(); j++) {
763 if (energy.bins[i][j] > 1.0e-30)
764 ndof++;
765 }
766 }
767 }
768 ndof -= npar;
769
770 double P = prob(chisquare, ndof);
771 cout << "P = "<<P << endl;
772 if (P > P_cutoff_val) {
773 break;
774 }
775 }
776
777 delete gMinuit;
778 return r;
779 }
780 }