ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/JetFitAnalyzer/test/JetFinderAnalyzer.cc
Revision: 1.4
Committed: Fri Sep 4 15:01:32 2009 UTC (15 years, 7 months ago) by dnisson
Content type: text/plain
Branch: MAIN
Changes since 1.3: +45 -80 lines
Log Message:
Changed from HepMC::GenParticle to reco::GenParticle, obviating need for class GenericParticle

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