ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/JetFitAnalyzer/src/jetfit.cpp
Revision: 1.9.2.1
Committed: Wed Nov 11 18:27:36 2009 UTC (15 years, 5 months ago) by dnisson
Branch: V00-01-03-branch
Changes since 1.9: +1 -1 lines
Log Message:
Fixed bug that was causing N values to be constant
`

File Contents

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