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
Error occurred while calculating annotation data.
Log Message:
Removed now-obsolete jetfit.cpp and jetfit.h files

File Contents

# Content
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 #include <TMath.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 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 int model_def::get_ngauss() {
54 return ngauss;
55 }
56
57 void model_def::set_ngauss(int _ngauss) {
58 ngauss = _ngauss;
59 }
60
61 // fit function
62 double model_def::fit_fcn(double x, double y, double *xval) {
63 int npar_indiv = get_formula()->GetNpar();
64 double val = 0.0;
65 for (int i = 0; i < ngauss; i++) {
66 get_formula()->SetParameters(xval + i*npar_indiv);
67 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 double val = mdef->fit_fcn(x[0], x[1], pval);
75 return val;
76 }
77
78 // Integral of (model formula)^2 / chisquare sigma
79 double model_def::formula_int(double xlo, double xhi, double ylo, double yhi,
80 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 int npar = get_formula()->GetNpar();
88 if (npar > 256) {
89 cerr << "Parameter overload" << endl;
90 return 0.0;
91 }
92 get_formula()->GetParameters(pval_old);
93 get_formula()->SetParameters(pval);
94
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 double sigma = fabs(chisquare_error(0.0)) < sig_cut
102 ? sig_cut : chisquare_error(0.0);
103
104 fsum += pow(xstep * ystep * get_formula()->Eval(x, y), 2.0)
105 / sigma / sigma;
106 }
107 }
108
109 get_formula()->SetParameters(pval_old);
110 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 double x = (static_cast<double>(i) + 0.5) * (energy.Xhi - energy.Xlo)
126 / 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 double nu = mdef->fit_fcn(x, y, xval) * XbinSize * YbinSize;
130 double sig_cut = 1.0e-5;
131 if (fabs(mdef->chisquare_error(energy.bins.at(i).at(j))) > sig_cut || !ignorezero) {
132 chisquare += pow(energy.bins.at(i).at(j) - nu, 2.0)
133 / pow(mdef->chisquare_error(energy.bins.at(i).at(j)), 2.0);
134 }
135 else {
136 chisquare += pow(energy.bins.at(i).at(j) - nu, 2.0)
137 / pow(sig_cut, 2.0);
138 }
139 }
140 }
141
142 // add errors due to Gaussians outside histogram
143 double eps = 0.01; // accuracy set for this function
144 for (int i = 0; i < mdef->get_ngauss(); i++) {
145 double *pval = xval+i*(mdef->get_formula()->GetNpar());
146 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 double cutoff_rad = sqrt(-log(eps * 2.0 * PI * par_sig * par_sig
150 / pval[0]) * 2.0 * par_sig * par_sig);
151
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 bool bottom = par_y < energy.Ylo + cutoff_rad;
156
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 chisquare += 2.0*mdef->formula_int(xlo, xhi, ylo, yhi, pval,
163 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 chisquare += 2.0*mdef->formula_int(xlo, xhi, ylo, yhi, pval,
171 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 chisquare += 2.0*mdef->formula_int(xlo, xhi, ylo, yhi, pval,
179 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 chisquare += 2.0*mdef->formula_int(xlo, xhi, ylo, yhi, pval,
187 XbinSize, YbinSize, xval);
188 }
189 }
190
191 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 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 hist->SetBinContent(i+1, j+1, vec[i][j]);
319 }
320 }
321 }
322
323 void model_def::par_init(TH2 *hist, TMinuit *gMinuit, vector<TString> &pars,
324 double *pval, double *perr, double *plo, double *phi,
325 int npar, FitResults r) {
326 int npar1 = npar - get_formula()->GetNpar();
327 bool init_spec_pars = false;
328 if (ngauss <= get_n_special_par_sets()) {
329 init_spec_pars = true;
330 for (int k = 0; k < ngauss; k++) {
331 int ipar0 = k*get_formula()->GetNpar(); // index of indiv par 0
332 for (int l = 0; l < get_formula()->GetNpar(); l++) {
333 int ipar = ipar0 + l;
334 if (ipar < npar)
335 get_special_par(k, l, pval[ipar], perr[ipar], plo[ipar],
336 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 max_sub = -(numeric_limits<double>::max());
352 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 // subtract integral of fit function
361 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 sub_energy[i][j] = energy.bins[i][j] - nu;
374 }
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 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 max_sub = 0.0;
391 max_x = 0.0;
392 max_y = 0.0;
393 for (int i = 1; i <= hist_sub->GetXaxis()->GetNbins(); i++) {
394 for (int j = 1; j <= hist_sub->GetYaxis()->GetNbins(); j++) {
395 double nu = energy.bins[i-1][j-1] - sub_energy[i-1][j-1];
396 if (hist_sub->GetBinContent(i, j)
397 - 3.0*pow(chisquare_error(nu), 2.0) > max_sub) {
398 max_sub = hist_sub->GetBinContent(i, j);
399 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 }
404 }
405 }
406
407 for (int i = npar1; i < npar; i++) {
408 if (get_indiv_max_E() == i - npar1) {
409 pval[i] = max_sub / XbinSize / YbinSize;
410 perr[i] = mdef->chisquare_error(pval[i])*0.5;
411 plo[i] = 0.0;
412 phi[i] = 1.0e6;
413 }
414 else if (get_indiv_max_x() == i - npar1) {
415 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 else if (get_indiv_max_y() == i - npar1) {
421 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 get_indiv_par(i-npar1, dummy, pval[i], perr[i], plo[i], phi[i]);
429 }
430 }
431 }
432 int n_pars_to_set = init_spec_pars ? ngauss*get_formula()->GetNpar()
433 : 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 get_indiv_par(i % get_formula()->GetNpar(), s,
440 dummy, dummy, dummy, dummy);
441 ostringstream par_oss;
442 par_oss << s << ipar / (get_formula()->GetNpar()) << flush;
443 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 FitResults fit_histo(TH2 *hist, vector<trouble> &t_vec,
460 void (*cc_minuit)(TMinuit *, TH2 *, int),
461 int start_ngauss,
462 int rebinX, int rebinY,
463 double P_cutoff_val) {
464 TMinuit *gMinuit = new TMinuit();
465 int npar_indiv = mdef->get_formula()->GetNpar();
466 int istat, erflg;
467 FitResults r;
468
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 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 t_vec.resize(t_vec.size() + 1);
511 int npar = npar_indiv*mdef->get_ngauss();
512 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 mdef->par_init(hist, gMinuit, pars, pval, perr, plo, phi, npar, r);
521
522 // minimize
523 double chisquare, edm, errdef;
524 int nvpar, nparx;
525 trouble t;
526 t.occ = T_NULL;
527 t.istat = 3;
528 // fix sigmas of the Gaussians
529 for (int i = 0; i < ngauss; i++) {
530 double parno[2];
531 parno[0] = i*npar_indiv + 4;
532 gMinuit->mnexcm("FIX", parno, 1, erflg);
533 }
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 r.chisquare.push_back(chisquare);
601 double P = TMath::Prob(chisquare, ndof);
602 if (P > P_cutoff_val) {
603 break;
604 }
605 }
606
607 delete gMinuit;
608 return r;
609 }
610 }