ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/JetFitAnalyzer/test/JetFinderAnalyzer.cc
Revision: 1.1
Committed: Wed Sep 2 21:48:13 2009 UTC (15 years, 8 months ago) by dnisson
Content type: text/plain
Branch: MAIN
Log Message:
Adding JetFitAnalyzer package to CMS repository.

File Contents

# User Rev Content
1 dnisson 1.1 /* A simple jet-finding analyzer */
2    
3     #include "UserCode/JetFitAnalyzer/interface/JetFitAnalyzer.h"
4    
5     #include "SimDataFormats/HepMCProduct/interface/HepMCProduct.h"
6     #include "fastjet/ClusterSequence.hh"
7     #include "FWCore/ServiceRegistry/interface/Service.h"
8     #include "PhysicsTools/UtilAlgos/interface/TFileService.h"
9    
10     #include <map>
11     #include <vector>
12     #include <limits>
13     #include <cmath>
14     #include <cstdlib>
15     #include <fstream>
16     #include <sstream>
17    
18     #include "TFormula.h"
19     #include "TF2.h"
20    
21     #define PI 3.141593
22    
23     using namespace std;
24     using namespace fastjet;
25    
26     class JetFinderAnalyzer : public JetFitAnalyzer {
27     public:
28     struct jet {
29     double energy;
30     double eta;
31     double phi;
32     };
33    
34     explicit JetFinderAnalyzer( const edm::ParameterSet&);
35     ~JetFinderAnalyzer() {}
36    
37     private:
38     static map<TH2 *, vector< vector<jet> > > unique_jets;
39    
40     static double phi_cutoff_;
41    
42     static double g2int(double xlo, double xhi, double ylo, double yhi,
43     double *pval) {
44     double sum1 = 0.0;
45     double sum2 = 0.0;
46     double xmid = 0.5 * (xlo + xhi);
47     double ymid = 0.5 * (ylo + yhi);
48     double xstep = (xhi - xlo) / 50.0;
49     double ystep = (yhi - ylo) / 50.0;
50     for (int i = 0; i < 50; i++) {
51     double x = (static_cast<double>(i) + 0.5) * xstep + xlo;
52     sum1 += xstep * jetfit::fit_fcn(x, ymid, pval);
53     }
54     for (int i = 0; i < 50; i++) {
55     double y = (static_cast<double>(i) + 0.5) * ystep + ylo;
56     sum2 += ystep * jetfit::fit_fcn(xmid, y, pval);
57     }
58     return sum1 * sum2;
59     }
60    
61     static void jetfinder(TMinuit *gMinuit, TH2 *hist, int ngauss) {
62     double dist_sq = numeric_limits<double>::infinity();
63     unique_jets[hist].resize(ngauss);
64     int nbinsX = hist->GetXaxis()->GetNbins();
65     int nbinsY = hist->GetYaxis()->GetNbins();
66     double XbinSize = (hist->GetXaxis()->GetXmax()
67     - hist->GetXaxis()->GetXmin())
68     / static_cast<double>(nbinsX);
69     double YbinSize = (hist->GetYaxis()->GetXmax()
70     - hist->GetYaxis()->GetXmin())
71     / static_cast<double>(nbinsY);
72     for (int i = 0; i < ngauss; i++) {
73     double N, mu_x, mu_y, sig, err, lo, hi;
74     int iuint;
75     TString name;
76     gMinuit->mnpout(4*i, name, N, err, lo, hi, iuint);
77     gMinuit->mnpout(4*i + 1, name, mu_x, err, lo, hi, iuint);
78     gMinuit->mnpout(4*i + 2, name, mu_y, err, lo, hi, iuint);
79     gMinuit->mnpout(4*i + 3, name, sig, err, lo, hi, iuint);
80     for (int j = 0; j < i; j++) {
81     double N2, mu_x2, mu_y2, sig2;
82     gMinuit->mnpout(4*j, name, N2, err, lo, hi, iuint);
83     gMinuit->mnpout(4*j + 1, name, mu_x2, err, lo, hi, iuint);
84     gMinuit->mnpout(4*j + 2, name, mu_y2, err, lo, hi, iuint);
85     gMinuit->mnpout(4*j + 3, name, sig2, err, lo, hi, iuint);
86     double _dist_sq = (mu_x2 - mu_x)*(mu_x2 - mu_x)
87     + (mu_y2 - mu_y)*(mu_y2 - mu_y);
88     if (_dist_sq < dist_sq)
89     dist_sq = _dist_sq;
90     }
91    
92     jet j;
93     j.energy = N;
94     j.eta = mu_x; j.phi = mu_y;
95     unique_jets[hist][ngauss-1].push_back(j);
96     }
97     }
98    
99     virtual void beginJob(const edm::EventSetup&);
100     virtual TH2D* make_histo(const edm::Event&, const edm::EventSetup&);
101     virtual jetfit::model_def& make_model_def(const edm::Event&,
102     const edm::EventSetup&,
103     TH2 *);
104     virtual void analyze_results(jetfit::results r,
105     std::vector<jetfit::trouble> t, TH2 *);
106    
107     fstream ofs;
108     double smear_;
109     int smear_coord_;
110     };
111    
112     map<TH2 *, vector< vector< JetFinderAnalyzer::jet > > >
113     JetFinderAnalyzer::unique_jets;
114    
115     JetFinderAnalyzer::JetFinderAnalyzer(const edm::ParameterSet &pSet)
116     : JetFitAnalyzer(pSet) // this is important!
117     {
118     smear_ = pSet.getUntrackedParameter("smear", 0.02);
119     smear_coord_ = pSet.getUntrackedParameter("smear_coord", 0);
120     // 0 = eta-phi smear
121     // 1 = proper angle smear
122     set_user_minuit(jetfinder);
123     }
124    
125     TH2D * JetFinderAnalyzer::make_histo(const edm::Event &evt, const edm::EventSetup&) {
126     ostringstream oss;
127     oss << "eta_phi_energy_unred"<<evt.id().event() << flush;
128     TH2D *unred_histo = new TH2D(oss.str().c_str(), oss.str().c_str(),
129     600, -2.5, 2.5, 600, -PI, PI);
130    
131     // fill unreduced histo
132     edm::Handle<edm::HepMCProduct> hRaw;
133     evt.getByLabel("source",
134     hRaw);
135     vector<HepMC::GenParticle *> particles;
136     const HepMC::GenEvent *hmcEvt = hRaw->GetEvent();
137     for (HepMC::GenEvent::particle_const_iterator
138     pit = hmcEvt->particles_begin(); pit != hmcEvt->particles_end();
139     pit++) {
140     if ((*pit)->status() == 1) {
141     particles.push_back(*pit);
142     }
143     }
144    
145     for (int i = 0; i < particles.size(); i++) {
146     unred_histo->Fill(particles[i]->momentum().eta(),
147     particles[i]->momentum().phi(),
148     particles[i]->momentum().e());
149     }
150    
151     // reduce histo
152     ostringstream oss2;
153     oss2 << "eta_phi_energy_red"<<evt.id().event() << flush;
154     edm::Service<TFileService> fs;
155     // draw cone of radius 0.5 around highest energy bin, reduce
156     double maxE = 0.0;
157     int max_i = 29, max_j = 29;
158     for (int i = 0; i < unred_histo->GetNbinsX(); i++) {
159     for (int j = 0; j < unred_histo->GetNbinsY(); j++) {
160     double E = unred_histo->GetBinContent(i+1, j+1);
161     if (E > maxE) {
162     maxE = E;
163     max_i = i;
164     max_j = j;
165     }
166     }
167     }
168    
169     double rcone = 0.5;
170     double Xlo = unred_histo->GetXaxis()->GetXmin();
171     double Xhi = unred_histo->GetXaxis()->GetXmax();
172     double Ylo = unred_histo->GetYaxis()->GetXmin();
173     double Yhi = unred_histo->GetYaxis()->GetXmax();
174     double XbinSize = (Xhi - Xlo) /
175     static_cast<double>(unred_histo->GetXaxis()->GetNbins());
176     double YbinSize = (Yhi - Ylo) /
177     static_cast<double>(unred_histo->GetYaxis()->GetNbins());
178     double max_x = (static_cast<double>(max_i) + 0.5) * XbinSize + Xlo;
179     double max_y = (static_cast<double>(max_j) + 0.5) * YbinSize + Ylo;
180     TH2D *histo = fs->make<TH2D>(oss2.str().c_str(), oss2.str().c_str(),
181     60, max_x-rcone, max_x+rcone,
182     60, max_y-rcone, max_y+rcone);
183    
184     // create an unsmeared reduced histo
185     TH2D *histo_unsmeared = fs->make<TH2D>((oss2.str()+"_unsmeared").c_str(),
186     (oss2.str()+"_unsmeared").c_str(),
187     60, max_x-rcone, max_x+rcone,
188     60, max_y-rcone, max_y+rcone);
189     for (int i = 0; i < particles.size(); i++) {
190     double N = particles[i]->momentum().e();
191     double x = particles[i]->momentum().eta();
192     double y = particles[i]->momentum().phi();
193     histo_unsmeared->Fill(x, y, N);
194     }
195    
196     // create a smeared reduced histo
197     // create a temporary 2D vector for smeared energies
198     XbinSize = (histo->GetXaxis()->GetXmax()
199     - histo->GetXaxis()->GetXmin()) /
200     static_cast<double>(histo->GetXaxis()->GetNbins());
201     YbinSize = (histo->GetYaxis()->GetXmax()
202     - histo->GetYaxis()->GetXmin()) /
203     static_cast<double>(histo->GetYaxis()->GetNbins());
204     vector< vector<double> > smeared(60, vector<double>(60, 0.0) );
205     switch (smear_coord_) {
206     case 1:
207     for (int i = 0; i < particles.size(); i++) {
208     double N = particles[i]->momentum().e();
209     double x = particles[i]->momentum().eta();
210     double y = particles[i]->momentum().phi();
211     // loop over bins and add Gaussian in proper angle to smeared
212     for (vector< vector<double> >::size_type i2 = 0; i2 < 60; i2++) {
213     for (vector< double >::size_type j2 = 0; j2 < 60; j2++) {
214     double eta = static_cast<double>((signed int)i2) * XbinSize +
215     max_x - rcone - x;
216     double phi = acos(cos(static_cast<double>((signed int)j2) * YbinSize +
217     max_y - rcone - y));
218     phi = sin(phi) > 0 ? phi : -phi;
219    
220     // transform eta, phi to proper angle
221     double theta = 2.0*atan(exp(-eta));
222     double iota = asin(sin(theta)*sin(phi));
223    
224     smeared[i2][j2] += (N*XbinSize*YbinSize/(2.0*PI*smear_*smear_))
225     * exp(-0.5*(theta*theta + iota*iota)/(smear_*smear_));
226     }
227     }
228     }
229     break;
230     case 0:
231     default:
232     for (int i = 0; i < particles.size(); i++) {
233     double N = particles[i]->momentum().e();
234     double x = particles[i]->momentum().eta();
235     double y = particles[i]->momentum().phi();
236     // loop over bins and add Gaussian to smeared
237     for (vector< vector<double> >::size_type i2 = 0; i2 < 60; i2++) {
238     for (vector< double >::size_type j2 = 0; j2 < 60; j2++) {
239     double eta = static_cast<double>((signed int)i2) * XbinSize
240     + max_x - rcone - x;
241     double phi = acos(cos(static_cast<double>((signed int)j2) * YbinSize
242     + max_y - rcone - y));
243     phi = sin(phi) > 0 ? phi : -phi;
244     smeared[i2][j2] += (N*XbinSize*YbinSize/(2.0*PI*smear_*smear_))
245     * exp(-0.5*(eta*eta + phi*phi)/(smear_*smear_));
246     }
247     }
248     }
249     }
250     // set histogram to match smear vector
251     for (int i = 1; i <= 60; i++) {
252     for (int j = 1; j <= 60; j++) {
253     histo->SetBinContent(i, j, smeared[i-1][j-1]);
254     }
255     }
256    
257     return histo;
258     }
259    
260     void seed_with_CA(const edm::Event &evt, TH2 *histo,
261     jetfit::model_def &_mdef) {
262     edm::Handle<edm::HepMCProduct> hMC;
263     evt.getByLabel("source", hMC);
264    
265     // create a PseudoJet vector
266     vector<PseudoJet> particles;
267     const HepMC::GenEvent *hmcEvt = hMC->GetEvent();
268     for (HepMC::GenEvent::particle_const_iterator
269     pit = hmcEvt->particles_begin(); pit != hmcEvt->particles_end();
270     pit++) {
271     if ((*pit)->status() == 1) {
272     double x_max = (histo->GetXaxis()->GetXmax()
273     + histo->GetXaxis()->GetXmin()) / 2.0;
274     double y_max = (histo->GetYaxis()->GetXmax()
275     + histo->GetYaxis()->GetXmin()) / 2.0;
276     valarray<double> pmom(4);
277     pmom[0] = (*pit)->momentum().px();
278     pmom[1] = (*pit)->momentum().py();
279     pmom[2] = (*pit)->momentum().pz();
280     pmom[3] = (*pit)->momentum().e();
281     double eta = (*pit)->momentum().eta();
282     double phi = (*pit)->momentum().phi();
283     if ((eta - x_max)*(eta - x_max) + (phi - y_max)*(phi - y_max) < 0.25) {
284     PseudoJet j(pmom);
285     particles.push_back(j);
286     }
287     }
288     }
289    
290     // choose a jet definition
291     double R = 0.2;
292     JetDefinition jet_def(cambridge_algorithm, R);
293    
294     // run clustering and extract the jets
295     ClusterSequence cs(particles, jet_def);
296     vector<PseudoJet> jets = cs.inclusive_jets();
297    
298     double XbinSize = (histo->GetXaxis()->GetXmax()
299     - histo->GetXaxis()->GetXmin()) /
300     static_cast<double>(histo->GetXaxis()->GetNbins());
301     double YbinSize = (histo->GetYaxis()->GetXmax()
302     - histo->GetYaxis()->GetXmin()) /
303     static_cast<double>(histo->GetYaxis()->GetNbins());
304    
305     // seed with C-A jets
306     int ijset = 0;
307     for (unsigned ij = 0; ij < jets.size(); ij++) {
308     double N = jets[ij].e();
309     if (N > 10.0) {
310     _mdef.set_special_par(ijset, 0, N, _mdef.chisquare_error(N)*0.1,
311     0.0, 1.0e6);
312     _mdef.set_special_par(ijset, 1, jets[ij].eta(), 0.01,
313     0.0, 0.0);
314     double mdef_phi = jets[ij].phi() > PI ? jets[ij].phi() - 2*PI
315     : jets[ij].phi();
316     _mdef.set_special_par(ijset, 2, mdef_phi, 0.01,
317     0.0, 0.0);
318     _mdef.set_special_par(ijset, 3, 0.1, 0.001, 0.0, 0.0);
319     ijset++;
320     }
321     }
322     }
323    
324     jetfit::model_def& JetFinderAnalyzer::make_model_def(const edm::Event& evt,
325     const edm::EventSetup&,
326     TH2 *histo) {
327     class jf_model_def : public jetfit::model_def {
328     public:
329     virtual double chisquare_error(double E) {
330     return 0.97*E + 14.0;
331     // study from 08-27-09
332     }
333     };
334    
335     jf_model_def *_mdef = new jf_model_def();
336     TFormula *formula = new TFormula("gaus2d",
337     "[0]*exp(-0.5*((x-[1])**2 + (y-[2])**2)/([3]**2))/(2*pi*[3]**2)");
338     _mdef->set_formula(formula);
339     _mdef->set_indiv_max_E(0);
340     _mdef->set_indiv_max_x(1);
341     _mdef->set_indiv_max_y(2);
342     _mdef->set_indiv_par(0, string("N"), 0.0, 0.0, 0.0, 1.0e6);
343     _mdef->set_indiv_par(1, string("mu_x"), 0.0, 0.0, 0.0, 0.0);
344     _mdef->set_indiv_par(2, string("mu_y"), 0.0, 0.0, 0.0, 0.0);
345     _mdef->set_indiv_par(3, string("sig"), 0.1, 0.001, 0.0, 0.0);
346    
347     seed_with_CA(evt, histo, *_mdef);
348    
349     jetfit::set_model_def(_mdef);
350    
351     // generate initial fit histogram
352     edm::Service<TFileService> fs;
353     TH2D *init_fit_histo = fs->make<TH2D>(("init_fit_"+string(histo->GetName()))
354     .c_str(),
355     ("Initial fit for "
356     +string(histo->GetName())).c_str(),
357     histo->GetXaxis()->GetNbins(),
358     histo->GetXaxis()->GetXmin(),
359     histo->GetXaxis()->GetXmax(),
360     histo->GetXaxis()->GetNbins(),
361     histo->GetXaxis()->GetXmin(),
362     histo->GetXaxis()->GetXmax());
363     double XbinSize = (histo->GetXaxis()->GetXmax()
364     - histo->GetXaxis()->GetXmin()) /
365     static_cast<double>(histo->GetXaxis()->GetNbins());
366     double YbinSize = (histo->GetYaxis()->GetXmax()
367     - histo->GetYaxis()->GetXmin()) /
368     static_cast<double>(histo->GetYaxis()->GetNbins());
369     double Xlo = histo->GetXaxis()->GetXmin();
370     double Xhi = histo->GetXaxis()->GetXmax();
371     double Ylo = histo->GetYaxis()->GetXmin();
372     double Yhi = histo->GetYaxis()->GetXmax();
373    
374     for (int i = 0; i < 60; i++) {
375     for (int j = 0; j < 60; j++) {
376     double x = (static_cast<double>(i) + 0.5)*XbinSize + Xlo;
377     double y = (static_cast<double>(j) + 0.5)*YbinSize + Ylo;
378     double pval[256];
379     if (_mdef->get_n_special_par_sets() > 64) {
380     cerr << "Parameter overload" << endl;
381     return *_mdef;
382     }
383     else {
384     for (int is = 0; is < _mdef->get_n_special_par_sets(); is++) {
385     for (int ii = 0; ii < 4; ii++) {
386     double spval, sperr, splo, sphi;
387     _mdef->get_special_par(is, ii, spval, sperr, splo, sphi);
388     pval[4*is + ii] = spval;
389     }
390     }
391     }
392     jetfit::set_ngauss(_mdef->get_n_special_par_sets());
393     init_fit_histo->SetBinContent(i+1, j+1,
394     jetfit::fit_fcn(x, y, pval));
395     }
396     }
397    
398     return *_mdef;
399     }
400    
401     void JetFinderAnalyzer::beginJob(const edm::EventSetup &es) {
402     ofs.open("jetfindlog.txt", ios::out);
403     if (ofs.fail()) {
404     cerr << "Opening jetfindlog.txt FAILED" << endl;
405     }
406     ofs << "Jetfinder log" << endl
407     << "=============" << endl << endl;
408     }
409    
410     ostream& operator<<(ostream &out, jetfit::trouble t) {
411     string action, error_string;
412    
413     if (t.istat != 3) {
414     switch(t.occ) {
415     case jetfit::T_NULL:
416     action = "Program"; break;
417     case jetfit::T_SIMPLEX:
418     action = "SIMPLEX"; break;
419     case jetfit::T_MIGRAD:
420     action = "MIGRAD"; break;
421     case jetfit::T_MINOS:
422     action = "MINOS"; break;
423     default:
424     action = "Program"; break;
425     }
426    
427     switch (t.istat) {
428     case 0:
429     error_string = "Unable to calculate error matrix"; break;
430     case 1:
431     error_string = "Error matrix a diagonal approximation"; break;
432     case 2:
433     error_string = "Error matrix not positive definite"; break;
434     case 3:
435     error_string = "Converged successfully"; break;
436     default:
437     ostringstream oss;
438     oss<<"Unknown status code "<<t.istat << flush;
439     error_string = oss.str(); break;
440     }
441    
442     if (t.occ != jetfit::T_NULL)
443     out << action<<" trouble: "<<error_string;
444     else
445     out << "Not calculated" << endl;
446     }
447    
448     return out;
449     }
450    
451     void JetFinderAnalyzer::analyze_results(jetfit::results r,
452     std::vector<jetfit::trouble> t,
453     TH2 *hist_orig) {
454     ofs << "Histogram "<<hist_orig->GetName() << endl;
455     for (int i = 0; i < unique_jets[hist_orig].size(); i++) {
456     ofs << "For "<<i+1<<" gaussians: " << endl
457     << t.at(i) << endl
458     << unique_jets[hist_orig][i].size()<<" unique jets found" << endl;
459     for (int j = 0; j < unique_jets[hist_orig][i].size(); j++) {
460     jet _jet = unique_jets[hist_orig][i][j];
461     ofs << "Jet "<<j<<": Energy = "<<_jet.energy<<", eta = "<<_jet.eta
462     << ", phi = "<<_jet.phi << endl;
463     }
464     ofs << endl;
465     }
466     ofs << endl;
467    
468     // save fit function histograms to root file
469     edm::Service<TFileService> fs;
470     for (vector< vector<double> >::size_type i = 0;
471     i < r.pval.size(); i++) {
472     jetfit::set_ngauss(r.pval[i].size() / 4);
473     TF2 *tf2 = new TF2("fit_func", jetfit::fit_fcn_TF2,
474     hist_orig->GetXaxis()->GetXmin(),
475     hist_orig->GetXaxis()->GetXmax(),
476     hist_orig->GetYaxis()->GetXmin(),
477     hist_orig->GetYaxis()->GetXmax(),
478     r.pval[i].size());
479     for (vector<double>::size_type j = 0; j < r.pval[i].size(); j++) {
480     tf2->SetParameter(j, r.pval[i][j]);
481     }
482     ostringstream fit_histo_oss;
483     fit_histo_oss << hist_orig->GetName()<<"_fit_"<<i << flush;
484     tf2->SetNpx(hist_orig->GetXaxis()->GetNbins());
485     tf2->SetNpy(hist_orig->GetYaxis()->GetNbins());
486     TH2D *fit_histo = fs->make<TH2D>(fit_histo_oss.str().c_str(),
487     fit_histo_oss.str().c_str(),
488     hist_orig->GetXaxis()->GetNbins(),
489     hist_orig->GetXaxis()->GetXmin(),
490     hist_orig->GetXaxis()->GetXmax(),
491     hist_orig->GetYaxis()->GetNbins(),
492     hist_orig->GetYaxis()->GetXmin(),
493     hist_orig->GetYaxis()->GetXmax());
494     TH1 *tf2_histo = tf2->CreateHistogram();
495     double XbinSize = (fit_histo->GetXaxis()->GetXmax()
496     - fit_histo->GetXaxis()->GetXmin())
497     / static_cast<double>(fit_histo->GetXaxis()->GetNbins());
498     double YbinSize = (fit_histo->GetYaxis()->GetXmax()
499     - fit_histo->GetYaxis()->GetXmin())
500     / static_cast<double>(fit_histo->GetYaxis()->GetNbins());
501     for (int ih = 0; ih < tf2->GetNpx(); ih++) {
502     for (int jh = 0; jh < tf2->GetNpy(); jh++) {
503     fit_histo->SetBinContent(ih+1, jh+1,
504     tf2_histo->GetBinContent(ih+1, jh+1)
505     * XbinSize * YbinSize);
506     }
507     }
508     }
509    
510     // save results to file
511     ostringstream res_tree_oss, rt_title_oss;
512     res_tree_oss << hist_orig->GetName()<<"_results" << flush;
513     rt_title_oss << "Fit results for "<<hist_orig->GetName() << flush;
514     }
515    
516     DEFINE_FWK_MODULE(JetFinderAnalyzer);