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