ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/JetFitAnalyzer/src/jetfit.cpp
Revision: 1.10
Committed: Wed Nov 11 01:46:56 2009 UTC (15 years, 5 months ago) by dnisson
Branch: MAIN
Changes since 1.9: +42 -41 lines
Log Message:
Encapsulated functions into class model_def, as appropriate.

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     struct histo {
44     vector< vector<double> > bins;
45     double Xlo, Xhi, Ylo, Yhi;
46     } energy;
47    
48    
49     model_def *mdef;
50    
51     model_def& curr_model_def() {
52     return *mdef;
53     }
54    
55     void set_model_def(model_def *_mdef) {
56     mdef = _mdef;
57     }
58    
59 dnisson 1.10 int model_def::get_ngauss() {
60 dnisson 1.1 return ngauss;
61     }
62    
63 dnisson 1.10 void model_def::set_ngauss(int _ngauss) {
64 dnisson 1.1 ngauss = _ngauss;
65     }
66    
67     // fit function
68 dnisson 1.10 double model_def::fit_fcn(double x, double y, double *xval) {
69     int npar_indiv = get_formula()->GetNpar();
70 dnisson 1.1 double val = 0.0;
71     for (int i = 0; i < ngauss; i++) {
72 dnisson 1.10 get_formula()->SetParameters(xval + i*npar_indiv);
73 dnisson 1.1 val += mdef->get_formula()->Eval(x, y);
74     }
75     return val;
76     }
77    
78     // TF2-compatible fit function
79     double fit_fcn_TF2(double *x, double *pval) {
80 dnisson 1.10 double val = mdef->fit_fcn(x[0], x[1], pval);
81 dnisson 1.1 return val;
82     }
83    
84 dnisson 1.9 // Integral of (model formula)^2 / chisquare sigma
85 dnisson 1.10 double model_def::formula_int(double xlo, double xhi, double ylo, double yhi,
86 dnisson 1.1 double *pval, double XbinSize, double YbinSize,
87     double *xval) {
88     double xstep = (xhi - xlo) / static_cast<double>(20);
89     double ystep = (yhi - ylo) / static_cast<double>(20);
90    
91     double fsum = 0.0;
92     double pval_old[256];
93 dnisson 1.10 int npar = get_formula()->GetNpar();
94 dnisson 1.1 if (npar > 256) {
95     cerr << "Parameter overload" << endl;
96     return 0.0;
97     }
98 dnisson 1.10 get_formula()->GetParameters(pval_old);
99     get_formula()->SetParameters(pval);
100 dnisson 1.1
101     for (int i = 0; i < 20; i++) {
102     for (int j = 0; j < 20; j++) {
103     double x = (static_cast<double>(i) + 0.5)*xstep + xlo;
104     double y = (static_cast<double>(j) + 0.5)*ystep + ylo;
105     double sig_cut = 1.0e-5;
106     double nu = XbinSize * YbinSize * fit_fcn(x, y, xval);
107 dnisson 1.10 double sigma = fabs(chisquare_error(0.0)) < sig_cut
108     ? sig_cut : chisquare_error(0.0);
109 dnisson 1.1
110 dnisson 1.10 fsum += pow(xstep * ystep * get_formula()->Eval(x, y), 2.0)
111 dnisson 1.1 / sigma / sigma;
112     }
113     }
114    
115 dnisson 1.10 get_formula()->SetParameters(pval_old);
116 dnisson 1.1 return fsum;
117     }
118    
119     // MINUIT objective function
120     void fcn(int &npar, double *grad, double &fcnval, double *xval, int iflag)
121     {
122     double chisquare = 0.0;
123     double XbinSize = (energy.Xhi - energy.Xlo)
124     / static_cast<double>(energy.bins.size());
125     double YbinSize = (energy.Yhi - energy.Ylo)
126     / static_cast<double>(energy.bins.at(0).size());
127     try {
128     // add errors in data points in histogram
129     for (int i = 0; i < energy.bins.size(); i++) {
130     for (int j = 0; j < energy.bins.at(i).size(); j++) {
131 dnisson 1.4 double x = (static_cast<double>(i) + 0.5) * (energy.Xhi - energy.Xlo)
132 dnisson 1.1 / static_cast<double>(energy.bins.size()) + energy.Xlo;
133     double y = (static_cast<double>(j) + 0.5) * (energy.Yhi - energy.Ylo)
134     / static_cast<double>(energy.bins.at(i).size()) + energy.Ylo;
135 dnisson 1.10 double nu = mdef->fit_fcn(x, y, xval) * XbinSize * YbinSize;
136 dnisson 1.1 double sig_cut = 1.0e-5;
137 dnisson 1.7 if (fabs(mdef->chisquare_error(energy.bins.at(i).at(j))) > sig_cut || !ignorezero) {
138 dnisson 1.1 chisquare += pow(energy.bins.at(i).at(j) - nu, 2.0)
139 dnisson 1.7 / pow(mdef->chisquare_error(energy.bins.at(i).at(j)), 2.0);
140 dnisson 1.3 }
141     else {
142 dnisson 1.1 chisquare += pow(energy.bins.at(i).at(j) - nu, 2.0)
143     / pow(sig_cut, 2.0);
144 dnisson 1.3 }
145 dnisson 1.1 }
146     }
147 dnisson 1.7
148 dnisson 1.1 // add errors due to Gaussians outside histogram
149 dnisson 1.6 double eps = 0.01; // accuracy set for this function
150 dnisson 1.10 for (int i = 0; i < mdef->get_ngauss(); i++) {
151 dnisson 1.3 double *pval = xval+i*(mdef->get_formula()->GetNpar());
152 dnisson 1.1 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 dnisson 1.7 double cutoff_rad = sqrt(-log(eps * 2.0 * PI * par_sig * par_sig
156     / pval[0]) * 2.0 * par_sig * par_sig);
157 dnisson 1.1
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 dnisson 1.2 bool bottom = par_y < energy.Ylo + cutoff_rad;
162 dnisson 1.1
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 dnisson 1.10 chisquare += 2.0*mdef->formula_int(xlo, xhi, ylo, yhi, pval,
169 dnisson 1.1 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 dnisson 1.10 chisquare += 2.0*mdef->formula_int(xlo, xhi, ylo, yhi, pval,
177 dnisson 1.1 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 dnisson 1.10 chisquare += 2.0*mdef->formula_int(xlo, xhi, ylo, yhi, pval,
185 dnisson 1.1 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 dnisson 1.10 chisquare += 2.0*mdef->formula_int(xlo, xhi, ylo, yhi, pval,
193 dnisson 1.1 XbinSize, YbinSize, xval);
194     }
195     }
196 dnisson 1.7
197 dnisson 1.1 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 dnisson 1.5 void fill_histo_with_vec(TH2 *hist, vector< vector<double> > &vec) {
485     for (int i = 0; i < vec.size(); i++) {
486     for (int j = 0; j < vec[i].size(); j++) {
487 dnisson 1.6 hist->SetBinContent(i+1, j+1, vec[i][j]);
488 dnisson 1.5 }
489     }
490     }
491    
492 dnisson 1.10 void model_def::par_init(TH2 *hist, TMinuit *gMinuit, vector<TString> &pars,
493 dnisson 1.1 double *pval, double *perr, double *plo, double *phi,
494     int npar, results r) {
495 dnisson 1.10 int npar1 = npar - get_formula()->GetNpar();
496 dnisson 1.1 bool init_spec_pars = false;
497 dnisson 1.10 if (ngauss <= get_n_special_par_sets()) {
498 dnisson 1.1 init_spec_pars = true;
499     for (int k = 0; k < ngauss; k++) {
500 dnisson 1.10 int ipar0 = k*get_formula()->GetNpar(); // index of indiv par 0
501     for (int l = 0; l < get_formula()->GetNpar(); l++) {
502 dnisson 1.1 int ipar = ipar0 + l;
503     if (ipar < npar)
504 dnisson 1.10 get_special_par(k, l, pval[ipar], perr[ipar], plo[ipar],
505 dnisson 1.1 phi[ipar]);
506     else
507     cerr << "WARNING: Attempt to set parameter out of index range!"
508     << endl;
509     }
510     }
511     }
512     else {
513     double XbinSize = (energy.Xhi - energy.Xlo)
514     / static_cast<double>(energy.bins.size());
515     double YbinSize = (energy.Xhi - energy.Xlo)
516     / static_cast<double>(energy.bins.at(0).size());
517     vector< vector<double> > sub_energy(energy.bins.size());
518     double max_sub, max_x = 0.0, max_y = 0.0;
519     double pval_other[256];
520 dnisson 1.3 max_sub = -(numeric_limits<double>::max());
521 dnisson 1.1 for (int i = 0; i < energy.bins.size(); i++) {
522     sub_energy[i].resize(energy.bins[i].size());
523     for (int j = 0; j < energy.bins[i].size(); j++) {
524     double x = static_cast<double>(i)*(energy.Xhi - energy.Xlo)
525     / static_cast<double>(energy.bins.size()) + energy.Xlo;
526     double y = static_cast<double>(j)*(energy.Yhi - energy.Ylo)
527     / static_cast<double>(energy.bins[i].size()) + energy.Ylo;
528     if (ngauss > 1) {
529 dnisson 1.6 // subtract integral of fit function
530 dnisson 1.1 try {
531     int npval_other = r.pval.at(r.pval.size()-1).size();
532     if (npval_other > 256) {
533     cerr << "Parameter overload" << endl;
534     return;
535     }
536     for (int k = 0; k < npval_other; k++) {
537     pval_other[k] = r.pval[r.pval.size()-1][k];
538     }
539     ngauss--;
540     double nu = fit_fcn(x, y, pval_other) * XbinSize * YbinSize;
541     ngauss++;
542 dnisson 1.6 sub_energy[i][j] = energy.bins[i][j] - nu;
543 dnisson 1.1 }
544     catch (exception ex) {
545     cerr << "Exception in par_init" << endl;
546     }
547     }
548     else {
549     sub_energy[i][j] = energy.bins[i][j];
550     }
551     }
552     }
553 dnisson 1.5 TH2D *hist_sub = new TH2D("hist_sub", "Subtracted histo",
554     sub_energy.size(), energy.Xlo,
555     energy.Xhi,
556     sub_energy[0].size(), energy.Ylo,
557     energy.Yhi);
558     fill_histo_with_vec(hist_sub, sub_energy);
559 dnisson 1.8 max_sub = 0.0;
560 dnisson 1.9 max_x = 0.0;
561     max_y = 0.0;
562 dnisson 1.8 for (int i = 1; i <= hist_sub->GetXaxis()->GetNbins(); i++) {
563     for (int j = 1; j <= hist_sub->GetYaxis()->GetNbins(); j++) {
564 dnisson 1.9 double nu = energy.bins[i-1][j-1] - sub_energy[i-1][j-1];
565     if (hist_sub->GetBinContent(i, j)
566 dnisson 1.10 - 3.0*pow(chisquare_error(nu), 2.0) > max_sub) {
567 dnisson 1.8 max_sub = hist_sub->GetBinContent(i, j);
568 dnisson 1.9 max_x = static_cast<double>(i-1)*XbinSize
569     + hist_sub->GetXaxis()->GetXmin();
570     max_y = static_cast<double>(j-1)*YbinSize
571     + hist_sub->GetYaxis()->GetXmin();
572 dnisson 1.8 }
573     }
574 dnisson 1.9 }
575 dnisson 1.1
576     for (int i = npar1; i < npar; i++) {
577 dnisson 1.10 if (get_indiv_max_E() == i - npar1) {
578 dnisson 1.9 pval[i] = max_sub / XbinSize / YbinSize;
579 dnisson 1.4 perr[i] = mdef->chisquare_error(pval[i])*0.5;
580 dnisson 1.1 plo[i] = 0.0;
581     phi[i] = 1.0e6;
582     }
583 dnisson 1.10 else if (get_indiv_max_x() == i - npar1) {
584 dnisson 1.1 pval[i] = max_x;
585     perr[i] = (energy.Xhi - energy.Xlo) / static_cast<double>(hist->GetXaxis()->GetNbins());
586     plo[i] = 0.0;
587     phi[i] = 0.0;
588     }
589 dnisson 1.10 else if (get_indiv_max_y() == i - npar1) {
590 dnisson 1.1 pval[i] = max_y;
591     perr[i] = (energy.Yhi - energy.Ylo) / static_cast<double>(hist->GetYaxis()->GetNbins());
592     plo[i] = 0.0;
593     phi[i] = 0.0;
594     }
595     else {
596     string dummy;
597 dnisson 1.10 get_indiv_par(i-npar1, dummy, pval[i], perr[i], plo[i], phi[i]);
598 dnisson 1.1 }
599     }
600     }
601 dnisson 1.10 int n_pars_to_set = init_spec_pars ? ngauss*get_formula()->GetNpar()
602 dnisson 1.1 : npar - npar1;
603     int init_par_to_set = init_spec_pars ? 0 : npar1;
604     for (int i = 0; i < n_pars_to_set; i++) {
605     double dummy;
606     string s;
607     int ipar = i + init_par_to_set;
608 dnisson 1.10 get_indiv_par(i % get_formula()->GetNpar(), s,
609 dnisson 1.1 dummy, dummy, dummy, dummy);
610     ostringstream par_oss;
611 dnisson 1.10 par_oss << s << ipar / (get_formula()->GetNpar()) << flush;
612 dnisson 1.1 try {
613     pars.at(ipar) = TString(par_oss.str());
614     }
615     catch (exception ex) {
616     cerr << "exception 2 in par_init" << endl;
617     }
618     int error_flag;
619     try {
620     gMinuit->mnparm(ipar, pars.at(ipar),
621     pval[ipar], perr[ipar], plo[ipar], phi[ipar], error_flag);
622     } catch (exception ex) {
623     cerr << "exception 3 in par_init" << endl;
624     }
625     }
626     }
627    
628 dnisson 1.10 results model_def::fit_histo(TH2 *hist, vector<trouble> &t_vec,
629     void (*cc_minuit)(TMinuit *, TH2 *, int),
630     int start_ngauss,
631     int rebinX, int rebinY,
632     double P_cutoff_val) {
633     set_model_def(this);
634 dnisson 1.1 TMinuit *gMinuit = new TMinuit();
635     int npar_indiv = mdef->get_formula()->GetNpar();
636     int istat, erflg;
637     results r;
638 dnisson 1.10 r.moddef = this;
639 dnisson 1.1
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 dnisson 1.10
679 dnisson 1.1 t_vec.resize(t_vec.size() + 1);
680     int npar = npar_indiv*ngauss;
681     double pval[256], perr[256], plo[256], phi[256];
682     if (npar > 256) {
683     cerr << "Parameter overload" << endl;
684     return r;
685     }
686     vector<TString> pars(npar);
687    
688     // initialize parameters
689     par_init(hist, gMinuit, pars, pval, perr, plo, phi, npar, r);
690 dnisson 1.5
691 dnisson 1.1 // minimize
692     double chisquare, edm, errdef;
693     int nvpar, nparx;
694     trouble t;
695     t.occ = T_NULL;
696     t.istat = 3;
697 dnisson 1.4 // fix sigmas of the Gaussians
698 dnisson 1.1 for (int i = 0; i < ngauss; i++) {
699     double parno[2];
700 dnisson 1.4 parno[0] = i*npar_indiv + 4;
701     gMinuit->mnexcm("FIX", parno, 1, erflg);
702 dnisson 1.1 }
703     gMinuit->mnexcm("SIMPLEX", 0, 0, erflg);
704     gMinuit->mnexcm("MIGRAD", 0, 0, erflg);
705     gMinuit->mnstat(chisquare, edm, errdef, nvpar, nparx, istat);
706     if (istat == 3) {
707     /* we're not concerned about MINOS errors right now
708     gMinuit->mnexcm("MINOS", 0, 0, erflg);
709     gMinuit->mnstat(chisquare, edm, errdef, nvpar, nparx, istat);
710     if (istat != 3) {
711     t.occ = T_MINOS;
712     t.istat = istat;
713     }
714     */
715     }
716     else {
717     t.occ = T_MIGRAD;
718     t.istat = istat;
719     }
720    
721     try {
722     if (t_vec.size() < ngauss) {
723     t_vec.resize(ngauss);
724     }
725     t_vec.at(ngauss-1) = t;
726     }
727     catch (exception ex) {
728     cerr << "exception in fit_histo" << endl;
729     }
730    
731     // put parameters in map
732     for (int i = 0; i < npar && i < 256; i++) {
733     int iuint; // internal parameter number
734     gMinuit->mnpout(i, pars[i], pval[i], perr[i], plo[i], phi[i], iuint);
735     }
736     vector<double> pval_copy(npar);
737     vector<double> perr_copy(npar);
738     vector<double> plo_copy(npar);
739     vector<double> phi_copy(npar);
740     for (int i = 0; i < npar && i < 256; i++) {
741     pval_copy[i] = pval[i];
742     perr_copy[i] = perr[i];
743     plo_copy[i] = plo[i];
744     phi_copy[i] = phi[i];
745     }
746     r.pars.push_back(pars);
747     r.pval.push_back(pval_copy);
748     r.perr.push_back(perr_copy);
749     r.plo.push_back(plo_copy);
750     r.phi.push_back(phi_copy);
751    
752     // execute user minuit code
753     if (cc_minuit != 0)
754     (*cc_minuit)(gMinuit, hist_rebinned, ngauss);
755    
756     int ndof = 0;
757     if (!ignorezero)
758     ndof = energy.bins.size() * energy.bins[0].size();
759     else {
760     for (int i = 0; i < energy.bins.size(); i++) {
761     for (int j = 0; j < energy.bins[i].size(); j++) {
762     if (energy.bins[i][j] > 1.0e-30)
763     ndof++;
764     }
765     }
766     }
767     ndof -= npar;
768    
769 dnisson 1.2 r.chisquare.push_back(chisquare);
770 dnisson 1.1 double P = prob(chisquare, ndof);
771     if (P > P_cutoff_val) {
772     break;
773     }
774     }
775    
776     delete gMinuit;
777     return r;
778     }
779     }