test
CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
MuScleFitUtils.cc
Go to the documentation of this file.
1 
6 // Some notes:
7 // - M(Z) after simulation needs to be extracted as a function of |y_Z| in order to be
8 // a better reference point for calibration. In fact, the variation of PDF with y_Z
9 // in production is sizable <---- need to check though.
10 // - ResHalfWidth needs to be optimized - this depends on the level of background.
11 // - Background parametrization still to be worked on, so far only a constant (type=1, and
12 // parameter 2 fixed to 0) works.
13 // - weights have to be assigned to dimuon mass values in regions where different resonances
14 // overlap, and one has to decide which resonance mass to assign the event to - this until
15 // we implement in the fitter a sum of probabilities of an event to belong to different
16 // resonances. The weight has to depend on the mass and has relative cross sections of
17 // Y(1S), 2S, 3S as parameters. Some overlap is also expected in the J/psi-Psi(2S) region
18 // when reconstructing masses with Standalone muons.
19 //
20 // MODS 7/7/08 TD:
21 // - changed parametrization of resolution in Pt: from sigma_pt = a*Pt + b*|eta| to
22 // sigma_pt = (a*Pt + b*|eta|)*Pt
23 // which is more correct (I hope)
24 // - changed parametrization of resolution in cotgth: from sigma_cotgth = f(eta) to f(cotgth)
25 // --------------------------------------------------------------------------------------------
26 
27 #include "MuScleFitUtils.h"
32 #include "TString.h"
33 #include "TFile.h"
34 #include "TTree.h"
35 #include "TCanvas.h"
36 #include "TH2F.h"
37 #include "TF1.h"
38 #include "TF2.h"
39 #include <iostream>
40 #include <fstream>
41 #include <memory> // to use the auto_ptr
42 
43 // Includes the definitions of all the bias and scale functions
44 // These functions are selected in the constructor according
45 // to the input parameters.
47 
48 // To use callgrind for code profiling uncomment also the following define.
49 //#define USE_CALLGRIND
50 #ifdef USE_CALLGRIND
51 #include "valgrind/callgrind.h"
52 #endif
53 
54 // Lorenzian Peak function
55 // -----------------------
56 Double_t lorentzianPeak (Double_t *x, Double_t *par) {
57  return (0.5*par[0]*par[1]/TMath::Pi()) /
58  TMath::Max(1.e-10,(x[0]-par[2])*(x[0]-par[2]) + .25*par[1]*par[1]);
59 }
60 
61 // Gaussian function
62 // -----------------
63 Double_t Gaussian (Double_t *x, Double_t *par) {
64  return par[0]*exp(-0.5*((x[0]-par[1])/par[2])*((x[0]-par[1])/par[2]));
65 }
66 
67 // Array with number of parameters in the fitting functions
68 // (not currently in use)
69 // --------------------------------------------------------
70 //const int nparsResol[2] = {6, 4};
71 //const int nparsScale[13] = {2, 2, 2, 3, 3, 3, 4, 4, 2, 3, 4, 6, 8};
72 //const int nparsBgr[3] = {1, 2, 3};
73 
74 // Quantities used for h-value computation
75 // ---------------------------------------
76 double mzsum;
77 double isum;
78 double f[11][100];
79 double g[11][100];
80 
81 // Lorentzian convoluted with a gaussian:
82 // --------------------------------------
83 TF1 * GL = new TF1 ("GL",
84  "0.5/3.1415926*[0]/(pow(x-[1],2)+pow(0.5*[0],2))*exp(-0.5*pow((x-[2])/[3],2))/([3]*sqrt(6.283185))",
85  0, 1000);
86 
87 TF2 * GL2= new TF2 ("GL2",
88  "0.5/3.1415926*[0]/(pow(x-[1],2)+pow(0.5*[0],2))*exp(-0.5*pow((x-y)/[2],2))/([2]*sqrt(6.283185))",
89  0, 200, 0, 200);
90 
91 // // Lorentzian convoluted with a gaussian over a linear background:
92 // // ---------------------------------------------------------------
93 // TF1 * GLBL = new TF1 ("GLBL",
94 // "0.5/3.1415926*[0]/(pow(x-[1],2)+pow(0.5*[0],2))*exp(-0.5*pow((x-[2])/[3],2))/([3]*sqrt(6.283185))+[4]+[5]*x",
95 // 0, 1000);
96 
97 // // Lorentzian convoluted with a gaussian over an exponential background:
98 // // ---------------------------------------------------------------
99 // TF1 * GLBE = new TF1 ("GLBE",
100 // "0.5/3.1415926*[0]/(pow(x-[1],2)+pow(0.5*[0],2))*exp(-0.5*pow((x-[2])/[3],2))/([3]*sqrt(6.283185))+exp([4]+[5]*x)",
101 // 0, 1000);
102 
103 std::vector<int> MuScleFitUtils::doResolFit;
104 std::vector<int> MuScleFitUtils::doScaleFit;
105 std::vector<int> MuScleFitUtils::doCrossSectionFit;
106 std::vector<int> MuScleFitUtils::doBackgroundFit;
107 
112 
113 bool MuScleFitUtils::duringMinos_ = false;
114 
115 const int MuScleFitUtils::totalResNum = 6;
116 
120 // No error, we take functions from the same group for bias and scale.
129 
131 // const int MuScleFitUtils::backgroundFunctionsRegions = 3;
132 // backgroundFunctionBase * MuScleFitUtils::backgroundFunctionForRegion[MuScleFitUtils::backgroundFunctionsRegions];
133 // backgroundFunctionBase * MuScleFitUtils::backgroundFunction[MuScleFitUtils::totalResNum];
135 std::vector<double> MuScleFitUtils::parBias;
136 std::vector<double> MuScleFitUtils::parSmear;
137 std::vector<double> MuScleFitUtils::parResol;
138 std::vector<double> MuScleFitUtils::parResolStep;
139 std::vector<double> MuScleFitUtils::parResolMin;
140 std::vector<double> MuScleFitUtils::parResolMax;
141 std::vector<double> MuScleFitUtils::parScale;
142 std::vector<double> MuScleFitUtils::parScaleStep;
143 std::vector<double> MuScleFitUtils::parScaleMin;
144 std::vector<double> MuScleFitUtils::parScaleMax;
145 std::vector<double> MuScleFitUtils::parCrossSection;
146 std::vector<double> MuScleFitUtils::parBgr;
147 std::vector<int> MuScleFitUtils::parResolFix;
148 std::vector<int> MuScleFitUtils::parScaleFix;
149 std::vector<int> MuScleFitUtils::parCrossSectionFix;
150 std::vector<int> MuScleFitUtils::parBgrFix;
151 std::vector<int> MuScleFitUtils::parResolOrder;
152 std::vector<int> MuScleFitUtils::parScaleOrder;
153 std::vector<int> MuScleFitUtils::parCrossSectionOrder;
154 std::vector<int> MuScleFitUtils::parBgrOrder;
155 
156 std::vector<int> MuScleFitUtils::resfind;
157 int MuScleFitUtils::debug = 0;
158 
159 bool MuScleFitUtils::ResFound = false;
162 
163 std::vector<std::vector<double> > MuScleFitUtils::parvalue;
164 
165 int MuScleFitUtils::FitStrategy = 1; // Strategy in likelihood fit (1 or 2)
166 bool MuScleFitUtils::speedup = false; // Whether to cut corners (no sim study, fewer histos)
167 
168 std::vector<std::pair<lorentzVector, lorentzVector> > MuScleFitUtils::SavedPair; // Pairs of reconstructed muons making resonances
169 std::vector<std::pair<lorentzVector, lorentzVector> > MuScleFitUtils::ReducedSavedPair; // Pairs of reconstructed muons making resonances inside smaller windows
170 std::vector<std::pair<lorentzVector, lorentzVector> > MuScleFitUtils::genPair; // Pairs of generated muons making resonances
171 std::vector<std::pair<MuScleFitMuon, MuScleFitMuon> > MuScleFitUtils::SavedPairMuScleFitMuons; // Pairs of reconstructed muons making resonances
172 std::vector<std::pair<MuScleFitMuon, MuScleFitMuon> > MuScleFitUtils::genMuscleFitPair; // Pairs of generated muons making resonances
173 //std::vector<GenMuonPair> MuScleFitUtils::genPairMuScleMuons; // Pairs of generated muons making resonances
174 std::vector<std::pair<lorentzVector, lorentzVector> > MuScleFitUtils::simPair; // Pairs of simulated muons making resonances
175 
176 // Smearing parameters
177 // -------------------
178 double MuScleFitUtils::x[][10000];
179 
180 // Probability matrices and normalization values
181 // ---------------------------------------------
182 int MuScleFitUtils::nbins = 1000;
183 double MuScleFitUtils::GLZValue[][1001][1001];
184 double MuScleFitUtils::GLZNorm[][1001];
185 double MuScleFitUtils::GLValue[][1001][1001];
186 double MuScleFitUtils::GLNorm[][1001];
188 
189 // Masses and widths from PDG 2006, half widths to be revised
190 // NB in particular, halfwidths have to be made a function of muonType
191 // -------------------------------------------------------------------
192 const double MuScleFitUtils::mMu2 = 0.011163612;
193 const double MuScleFitUtils::muMass = 0.105658;
198 
199 double MuScleFitUtils::ResGamma[] = {2.4952, 0.000020, 0.000032, 0.000054, 0.000317, 0.0000932 };
200 // ATTENTION:
201 // This is left because the values are used by the BackgroundHandler to define the center of the regions windows,
202 // but the values used in the code are read computed using the probability histograms ranges.
203 // The histograms are read after the initialization of the BackgroundHandler (this can be improved so that
204 // the background handler too could use the new values).
205 // At this time the values are consistent.
206 double MuScleFitUtils::ResMinMass[] = {-99, -99, -99, -99, -99, -99};
207 double MuScleFitUtils::ResMass[] = {91.1876, 10.3552, 10.0233, 9.4603, 3.68609, 3.0969};
208 // From Summer08 generator production TWiki: https://twiki.cern.ch/twiki/bin/view/CMS/ProductionSummer2008
209 // - Z->mumu 1.233 nb
210 // - Upsilon3S->mumu 0.82 nb
211 // - Upsilon2S->mumu 6.33 nb
212 // - Upsilon1S->mumu 13.9 nb
213 // - Prompt Psi2S->mumu 2.169 nb
214 // - Prompt J/Psi->mumu 127.2 nb
215 // double MuScleFitUtils::crossSection[] = {1.233, 0.82, 6.33, 13.9, 2.169, 127.2};
216 // double MuScleFitUtils::crossSection[] = {1.233, 2.07, 6.33, 13.9, 2.169, 127.2};
217 
218 unsigned int MuScleFitUtils::loopCounter = 5;
219 
220 // According to the pythia manual, there is only a code for the Upsilon and Upsilon'. It does not distinguish
221 // between Upsilon(2S) and Upsilon(3S)
222 const unsigned int MuScleFitUtils::motherPdgIdArray[] = {23, 100553, 100553, 553, 100443, 443};
223 
224 // double MuScleFitUtils::leftWindowFactor = 1.;
225 // double MuScleFitUtils::rightWindowFactor = 1.;
226 
227 // double MuScleFitUtils::internalLeftWindowFactor = 1.;
228 // double MuScleFitUtils::internalRightWindowFactor = 1.;
229 
230 // int MuScleFitUtils::backgroundWindowEvents_ = 0;
231 // int MuScleFitUtils::resonanceWindowEvents_ = 0;
232 
233 // double MuScleFitUtils::oldEventsOutInRatio_ = 0.;
234 
236 
237 bool MuScleFitUtils::sherpa_ = false;
238 
240 
242 
244 double MuScleFitUtils::minMuonPt_ = 0.;
245 double MuScleFitUtils::maxMuonPt_ = 100000000.;
250 double MuScleFitUtils::deltaPhiMinCut_ = -100.;
251 double MuScleFitUtils::deltaPhiMaxCut_ = 100.;
252 
255 
257 TMinuit * MuScleFitUtils::rminPtr_ = 0;
260 
264 
265 int MuScleFitUtils::iev_ = 0;
267 
268 // Find the best simulated resonance from a vector of simulated muons (SimTracks)
269 // and return its decay muons
270 // ------------------------------------------------------------------------------
271 std::pair<SimTrack,SimTrack> MuScleFitUtils::findBestSimuRes (const std::vector<SimTrack>& simMuons) {
272 
273  std::pair<SimTrack, SimTrack> simMuFromBestRes;
274  double maxprob = -0.1;
275 
276  // Double loop on muons
277  // --------------------
278  for (std::vector<SimTrack>::const_iterator simMu1=simMuons.begin(); simMu1!=simMuons.end(); simMu1++) {
279  for (std::vector<SimTrack>::const_iterator simMu2=simMu1+1; simMu2!=simMuons.end(); simMu2++) {
280  if (((*simMu1).charge()*(*simMu2).charge())>0) {
281  continue; // this also gets rid of simMu1==simMu2...
282  }
283  // Choose the best resonance using its mass. Check Z, Y(3S,2S,1S), Psi(2S), J/Psi in order
284  // ---------------------------------------------------------------------------------------
285  double mcomb = ((*simMu1).momentum()+(*simMu2).momentum()).mass();
286  double Y = ((*simMu1).momentum()+(*simMu2).momentum()).Rapidity();
287  for (int ires=0; ires<6; ires++) {
288  if (resfind[ires]>0) {
289  double prob = massProb( mcomb, Y, ires, 0. );
290  if (prob>maxprob) {
291  simMuFromBestRes.first = (*simMu1);
292  simMuFromBestRes.second = (*simMu2);
293  maxprob = prob;
294  }
295  }
296  }
297  }
298  }
299 
300  // Return most likely combination of muons making a resonance
301  // ----------------------------------------------------------
302  return simMuFromBestRes;
303 }
304 
305 // Find the best reconstructed resonance from a collection of reconstructed muons
306 // (MuonCollection) and return its decay muons
307 // ------------------------------------------------------------------------------
308 std::pair<MuScleFitMuon, MuScleFitMuon> MuScleFitUtils::findBestRecoRes(const std::vector<MuScleFitMuon>& muons){
309  // NB this routine returns the resonance, but it also sets the ResFound flag, which
310  // is used in MuScleFit to decide whether to use the event or not.
311  // --------------------------------------------------------------------------------
312  if (debug>0) std::cout << "In findBestRecoRes" << std::endl;
313  ResFound = false;
314  std::pair<MuScleFitMuon, MuScleFitMuon> recMuFromBestRes;
315 
316  // Choose the best resonance using its mass probability
317  // ----------------------------------------------------
318  double maxprob = -0.1;
319  double minDeltaMass = 999999;
320  std::pair<MuScleFitMuon, MuScleFitMuon> bestMassMuons;
321  for (std::vector<MuScleFitMuon>::const_iterator Muon1=muons.begin(); Muon1!=muons.end(); ++Muon1) {
322  //rc2010
323  if (debug>0) std::cout << "muon_1_charge:"<<(*Muon1).charge() << std::endl;
324  for (std::vector<MuScleFitMuon>::const_iterator Muon2=Muon1+1; Muon2!=muons.end(); ++Muon2) {
325  //rc2010
326  if (debug>0) std::cout << "after_2" << std::endl;
327  if ((((*Muon1).charge())*((*Muon2).charge()))>0) {
328  continue; // This also gets rid of Muon1==Muon2...
329  }
330  // To allow the selection of ranges at negative and positive eta independently we define two
331  // ranges of eta: (minMuonEtaFirstRange_, maxMuonEtaFirstRange_) and (minMuonEtaSecondRange_, maxMuonEtaSecondRange_).
332  double ch1 = (*Muon1).charge();
333  double ch2 = (*Muon2).charge();
334  double pt1 = (*Muon1).Pt();
335  double pt2 = (*Muon2).Pt();
336  double eta1 = (*Muon1).Eta();
337  double eta2 = (*Muon2).Eta();
338  if (
339  pt1 >= minMuonPt_ && pt1 < maxMuonPt_ &&
340  pt2 >= minMuonPt_ && pt2 < maxMuonPt_ &&
341  (
342  (
343  eta1 >= minMuonEtaFirstRange_ && eta1 < maxMuonEtaFirstRange_ && eta2 >= minMuonEtaSecondRange_ && eta2 < maxMuonEtaSecondRange_ && ch1>=ch2 // In the configuration file, MuonOne==MuonPlus
344  ) || (
345  eta1 >= minMuonEtaSecondRange_ && eta1 < maxMuonEtaSecondRange_ && eta2 >= minMuonEtaFirstRange_ && eta2 < maxMuonEtaFirstRange_ && ch1<ch2
346  )
347  )
348  ){
349  double mcomb = ((*Muon1).p4()+(*Muon2).p4()).mass();
350  double Y = ((*Muon1).p4()+(*Muon2).p4()).Rapidity();
351  if (debug>1) {
352  std::cout<<"muon1 "<<(*Muon1).p4().Px()<<", "<<(*Muon1).p4().Py()<<", "<<(*Muon1).p4().Pz()<<", "<<(*Muon1).p4().E()<<", "<<(*Muon1).charge()<<std::endl;
353  std::cout<<"muon2 "<<(*Muon2).p4().Px()<<", "<<(*Muon2).p4().Py()<<", "<<(*Muon2).p4().Pz()<<", "<<(*Muon2).p4().E()<<", "<<(*Muon2).charge()<<std::endl;
354  std::cout<<"mcomb "<<mcomb<<std::endl;
355  }
356  double massResol = 0.;
357  if (useProbsFile_) {
358  massResol = massResolution((*Muon1).p4(), (*Muon2).p4(), parResol);
359  }
360  double prob = 0;
361  for (int ires=0; ires<6; ires++) {
362  if (resfind[ires]>0) {
363  if (useProbsFile_) {
364  prob = massProb(mcomb, Y, ires, massResol);
365  }
366  if (prob>maxprob) {
367  if (ch1<0) { // store first the mu minus and then the mu plus
368  recMuFromBestRes.first = (*Muon1);
369  recMuFromBestRes.second = (*Muon2);
370  }
371  else {
372  recMuFromBestRes.first = (*Muon2);
373  recMuFromBestRes.second = (*Muon1);
374  }
375  if (debug>0) std::cout << "muon_1_charge (after swapping):"<<recMuFromBestRes.first.charge() << std::endl;
376  ResFound = true; // NNBB we accept "resonances" even outside mass bounds
377  maxprob = prob;
378  }
379  // if( ResMass[ires] == 0 ) {
380  // std::cout << "Error: ResMass["<<ires<<"] = " << ResMass[ires] << std::endl;
381  // exit(1);
382  // }
383  double deltaMass = fabs(mcomb-ResMass[ires])/ResMass[ires];
384  if (deltaMass<minDeltaMass){
385  bestMassMuons = std::make_pair((*Muon1), (*Muon2));
386  minDeltaMass = deltaMass;
387  }
388  }
389  }
390  }
391  }
392  }
393  //If outside mass window (maxprob==0) then take the two muons with best invariant mass
394  //(anyway they will not be used in the likelihood calculation, only to fill plots)
395  if (!maxprob){
396  if (bestMassMuons.first.charge()<0){
397  recMuFromBestRes.first = bestMassMuons.first;
398  recMuFromBestRes.second = bestMassMuons.second;
399  }
400  else{
401  recMuFromBestRes.second = bestMassMuons.first;
402  recMuFromBestRes.first = bestMassMuons.second;
403  }
404  }
405  return recMuFromBestRes;
406 }
407 
408 // Resolution smearing function called to worsen muon Pt resolution at start
409 // -------------------------------------------------------------------------
411 {
412  double pt = muon.Pt();
413  double eta = muon.Eta();
414  double phi = muon.Phi();
415  double E = muon.E();
416 
417  double y[7] = {};
418  for (int i=0; i<SmearType+3; i++) {
419  y[i] = x[i][goodmuon%10000];
420  }
421 
422  // Use the smear function selected in the constructor
423  smearFunction->smear( pt, eta, phi, y, parSmear );
424 
425  if (debug>9) {
426  std::cout << "Smearing Pt,eta,phi = " << pt << " " << eta << " "
427  << phi << "; x = ";
428  for (int i=0; i<SmearType+3; i++) {
429  std::cout << y[i];
430  }
431  std::cout << std::endl;
432  }
433 
434  double ptEtaPhiE[4] = {pt, eta, phi, E};
435  return( fromPtEtaPhiToPxPyPz(ptEtaPhiE) );
436 }
437 
438 // Biasing function called to modify muon Pt scale at the start.
439 // -------------------------------------------------------------
441 {
442  double ptEtaPhiE[4] = {muon.Pt(),muon.Eta(),muon.Phi(),muon.E()};
443 
444  if (MuScleFitUtils::debug>1) std::cout << "pt before bias = " << ptEtaPhiE[0] << std::endl;
445 
446  // Use functors (although not with the () operator)
447  // Note that we always pass pt, eta and phi, but internally only the needed
448  // values are used.
449  // The functors used are takend from the same group used for the scaling
450  // thus the name of the method used is "scale".
451  ptEtaPhiE[0] = biasFunction->scale(ptEtaPhiE[0], ptEtaPhiE[1], ptEtaPhiE[2], chg, MuScleFitUtils::parBias);
452 
453  if (MuScleFitUtils::debug>1) std::cout << "pt after bias = " << ptEtaPhiE[0] << std::endl;
454 
455  return( fromPtEtaPhiToPxPyPz(ptEtaPhiE) );
456 }
457 
458 // Version of applyScale accepting a std::vector<double> of parameters
459 // --------------------------------------------------------------
461  const std::vector<double> & parval, const int chg)
462 {
463  double * p = new double[(int)(parval.size())];
464  // Replaced by auto_ptr, which handles delete at the end
465  // std::auto_ptr<double> p(new double[(int)(parval.size())]);
466  // Removed auto_ptr, check massResolution for an explanation.
467  int id = 0;
468  for (std::vector<double>::const_iterator it=parval.begin(); it!=parval.end(); ++it, ++id) {
469  //(&*p)[id] = *it;
470  // Also ok would be (p.get())[id] = *it;
471  p[id] = *it;
472  }
473  lorentzVector tempScaleVec( applyScale (muon, p, chg) );
474  delete[] p;
475  return tempScaleVec;
476 }
477 
478 // This is called by the likelihood to "taste" different values for additional corrections
479 // ---------------------------------------------------------------------------------------
481  double* parval, const int chg)
482 {
483  double ptEtaPhiE[4] = {muon.Pt(),muon.Eta(),muon.Phi(),muon.E()};
484  int shift = parResol.size();
485 
486  if (MuScleFitUtils::debug>1) std::cout << "pt before scale = " << ptEtaPhiE[0] << std::endl;
487 
488  // the address of parval[shift] is passed as pointer to double. Internally it is used as a normal array, thus:
489  // array[0] = parval[shift], array[1] = parval[shift+1], ...
490  ptEtaPhiE[0] = scaleFunction->scale(ptEtaPhiE[0], ptEtaPhiE[1], ptEtaPhiE[2], chg, &(parval[shift]));
491 
492  if (MuScleFitUtils::debug>1) std::cout << "pt after scale = " << ptEtaPhiE[0] << std::endl;
493 
494  return( fromPtEtaPhiToPxPyPz(ptEtaPhiE) );
495 }
496 
497 // Useful function to convert 4-vector coordinates
498 // -----------------------------------------------
500 {
501  double px = ptEtaPhiE[0]*cos(ptEtaPhiE[2]);
502  double py = ptEtaPhiE[0]*sin(ptEtaPhiE[2]);
503  double tmp = 2*atan(exp(-ptEtaPhiE[1]));
504  double pz = ptEtaPhiE[0]*cos(tmp)/sin(tmp);
505  double E = sqrt(px*px+py*py+pz*pz+muMass*muMass);
506 
507  // lorentzVector corrMu(px,py,pz,E);
508  // To fix memory leaks, this is to be substituted with
509  // std::auto_ptr<lorentzVector> corrMu(new lorentzVector(px, py, pz, E));
510 
511  return lorentzVector(px,py,pz,E);
512 }
513 
514 // Dimuon mass
515 // -----------
517  const lorentzVector& mu2 )
518 {
519  return (mu1+mu2).mass();
520 }
521 
522 // Mass resolution - version accepting a std::vector<double> parval
523 // -----------------------------------------------------------
525  const lorentzVector& mu2,
526  const std::vector<double> & parval )
527 {
528  // double * p = new double[(int)(parval.size())];
529  // Replaced by auto_ptr, which handles delete at the end
530  // --------- //
531  // ATTENTION //
532  // --------- //
533  // auto_ptr calls delete, not delete[] and thus it must
534  // not be used with arrays. There are alternatives see
535  // e.g.: http://www.gotw.ca/gotw/042.htm. The best
536  // alternative seems to be to switch to vector though.
537  // std::auto_ptr<double> p(new double[(int)(parval.size())]);
538 
539  double * p = new double[(int)(parval.size())];
540  std::vector<double>::const_iterator it = parval.begin();
541  int id = 0;
542  for ( ; it!=parval.end(); ++it, ++id) {
543  // (&*p)[id] = *it;
544  p[id] = *it;
545  }
546  double massRes = massResolution (mu1, mu2, p);
547  delete[] p;
548  return massRes;
549 }
550 
569  const lorentzVector& mu2,
570  double* parval )
571 {
572  double mass = (mu1+mu2).mass();
573  double pt1 = mu1.Pt();
574  double phi1 = mu1.Phi();
575  double eta1 = mu1.Eta();
576  double theta1 = 2*atan(exp(-eta1));
577  double pt2 = mu2.Pt();
578  double phi2 = mu2.Phi();
579  double eta2 = mu2.Eta();
580  double theta2 = 2*atan(exp(-eta2));
581 
582  double dmdpt1 = (pt1/std::pow(sin(theta1),2)*sqrt((std::pow(pt2/sin(theta2),2)+mMu2)/(std::pow(pt1/sin(theta1),2)+mMu2))-
583  pt2*(cos(phi1-phi2)+cos(theta1)*cos(theta2)/(sin(theta1)*sin(theta2))))/mass;
584  double dmdpt2 = (pt2/std::pow(sin(theta2),2)*sqrt((std::pow(pt1/sin(theta1),2)+mMu2)/(std::pow(pt2/sin(theta2),2)+mMu2))-
585  pt1*(cos(phi2-phi1)+cos(theta2)*cos(theta1)/(sin(theta2)*sin(theta1))))/mass;
586  double dmdphi1 = pt1*pt2/mass*sin(phi1-phi2);
587  double dmdphi2 = pt2*pt1/mass*sin(phi2-phi1);
588  double dmdcotgth1 = (pt1*pt1*cos(theta1)/sin(theta1)*
589  sqrt((std::pow(pt2/sin(theta2),2)+mMu2)/(std::pow(pt1/sin(theta1),2)+mMu2)) -
590  pt1*pt2*cos(theta2)/sin(theta2))/mass;
591  double dmdcotgth2 = (pt2*pt2*cos(theta2)/sin(theta2)*
592  sqrt((std::pow(pt1/sin(theta1),2)+mMu2)/(std::pow(pt2/sin(theta2),2)+mMu2)) -
593  pt2*pt1*cos(theta1)/sin(theta1))/mass;
594 
595  if( debugMassResol_ ) {
596  massResolComponents.dmdpt1 = dmdpt1;
597  massResolComponents.dmdpt2 = dmdpt2;
598  massResolComponents.dmdphi1 = dmdphi1;
599  massResolComponents.dmdphi2 = dmdphi2;
600  massResolComponents.dmdcotgth1 = dmdcotgth1;
601  massResolComponents.dmdcotgth2 = dmdcotgth2;
602  }
603 
604  // Resolution parameters:
605  // ----------------------
606  double sigma_pt1 = resolutionFunction->sigmaPt( pt1,eta1,parval );
607  double sigma_pt2 = resolutionFunction->sigmaPt( pt2,eta2,parval );
608  double sigma_phi1 = resolutionFunction->sigmaPhi( pt1,eta1,parval );
609  double sigma_phi2 = resolutionFunction->sigmaPhi( pt2,eta2,parval );
610  double sigma_cotgth1 = resolutionFunction->sigmaCotgTh( pt1,eta1,parval );
611  double sigma_cotgth2 = resolutionFunction->sigmaCotgTh( pt2,eta2,parval );
612  double cov_pt1pt2 = resolutionFunction->covPt1Pt2( pt1, eta1, pt2, eta2, parval );
613 
614  // Sigma_Pt is defined as a relative sigmaPt/Pt for this reason we need to
615  // multiply it by pt.
616  double mass_res = sqrt(std::pow(dmdpt1*sigma_pt1*pt1,2)+std::pow(dmdpt2*sigma_pt2*pt2,2)+
617  std::pow(dmdphi1*sigma_phi1,2)+std::pow(dmdphi2*sigma_phi2,2)+
618  std::pow(dmdcotgth1*sigma_cotgth1,2)+std::pow(dmdcotgth2*sigma_cotgth2,2)+
619  2*dmdpt1*dmdpt2*cov_pt1pt2*sigma_pt1*sigma_pt2);
620 
621  if (debug>19) {
622  std::cout << " Pt1=" << pt1 << " phi1=" << phi1 << " cotgth1=" << cos(theta1)/sin(theta1) << " - Pt2=" << pt2
623  << " phi2=" << phi2 << " cotgth2=" << cos(theta2)/sin(theta2) << std::endl;
624  std::cout << " P[0]="
625  << parval[0] << " P[1]=" << parval[1] << "P[2]=" << parval[2] << " P[3]=" << parval[3] << std::endl;
626  std::cout << " Dmdpt1= " << dmdpt1 << " dmdpt2= " << dmdpt2 << " sigma_pt1="
627  << sigma_pt1 << " sigma_pt2=" << sigma_pt2 << std::endl;
628  std::cout << " Dmdphi1= " << dmdphi1 << " dmdphi2= " << dmdphi2 << " sigma_phi1="
629  << sigma_phi1 << " sigma_phi2=" << sigma_phi2 << std::endl;
630  std::cout << " Dmdcotgth1= " << dmdcotgth1 << " dmdcotgth2= " << dmdcotgth2
631  << " sigma_cotgth1="
632  << sigma_cotgth1 << " sigma_cotgth2=" << sigma_cotgth2 << std::endl;
633  std::cout << " Mass resolution (pval) for muons of Pt = " << pt1 << " " << pt2
634  << " : " << mass << " +- " << mass_res << std::endl;
635  }
636 
637  // Debug std::cout
638  // ----------
639  bool didit = false;
640  for (int ires=0; ires<6; ires++) {
641  if (!didit && resfind[ires]>0 && fabs(mass-ResMass[ires])<ResHalfWidth[ires]) {
642  if (mass_res>ResMaxSigma[ires] && counter_resprob<100) {
643  counter_resprob++;
644  LogDebug("MuScleFitUtils") << "RESOLUTION PROBLEM: ires=" << ires << std::endl;
645  didit = true;
646  }
647  }
648  }
649 
650  return mass_res;
651 }
652 
658  const lorentzVector& mu2,
659  const ResolutionFunction & resolFunc )
660 {
661  double mass = (mu1+mu2).mass();
662  double pt1 = mu1.Pt();
663  double phi1 = mu1.Phi();
664  double eta1 = mu1.Eta();
665  double theta1 = 2*atan(exp(-eta1));
666  double pt2 = mu2.Pt();
667  double phi2 = mu2.Phi();
668  double eta2 = mu2.Eta();
669  double theta2 = 2*atan(exp(-eta2));
670 
671  double dmdpt1 = (pt1/std::pow(sin(theta1),2)*sqrt((std::pow(pt2/sin(theta2),2)+mMu2)/(std::pow(pt1/sin(theta1),2)+mMu2))-
672  pt2*(cos(phi1-phi2)+cos(theta1)*cos(theta2)/(sin(theta1)*sin(theta2))))/mass;
673  double dmdpt2 = (pt2/std::pow(sin(theta2),2)*sqrt((std::pow(pt1/sin(theta1),2)+mMu2)/(std::pow(pt2/sin(theta2),2)+mMu2))-
674  pt1*(cos(phi2-phi1)+cos(theta2)*cos(theta1)/(sin(theta2)*sin(theta1))))/mass;
675  double dmdphi1 = pt1*pt2/mass*sin(phi1-phi2);
676  double dmdphi2 = pt2*pt1/mass*sin(phi2-phi1);
677  double dmdcotgth1 = (pt1*pt1*cos(theta1)/sin(theta1)*
678  sqrt((std::pow(pt2/sin(theta2),2)+mMu2)/(std::pow(pt1/sin(theta1),2)+mMu2)) -
679  pt1*pt2*cos(theta2)/sin(theta2))/mass;
680  double dmdcotgth2 = (pt2*pt2*cos(theta2)/sin(theta2)*
681  sqrt((std::pow(pt1/sin(theta1),2)+mMu2)/(std::pow(pt2/sin(theta2),2)+mMu2)) -
682  pt2*pt1*cos(theta1)/sin(theta1))/mass;
683 
684  // Resolution parameters:
685  // ----------------------
686  double sigma_pt1 = resolFunc.sigmaPt( mu1 );
687  double sigma_pt2 = resolFunc.sigmaPt( mu2 );
688  double sigma_phi1 = resolFunc.sigmaPhi( mu1 );
689  double sigma_phi2 = resolFunc.sigmaPhi( mu2 );
690  double sigma_cotgth1 = resolFunc.sigmaCotgTh( mu1 );
691  double sigma_cotgth2 = resolFunc.sigmaCotgTh( mu2 );
692 
693  // Sigma_Pt is defined as a relative sigmaPt/Pt for this reason we need to
694  // multiply it by pt.
695  double mass_res = sqrt(std::pow(dmdpt1*sigma_pt1*pt1,2)+std::pow(dmdpt2*sigma_pt2*pt2,2)+
696  std::pow(dmdphi1*sigma_phi1,2)+std::pow(dmdphi2*sigma_phi2,2)+
697  std::pow(dmdcotgth1*sigma_cotgth1,2)+std::pow(dmdcotgth2*sigma_cotgth2,2));
698 
699  return mass_res;
700 }
701 
702 
703 // Mass probability - version with linear background included, accepts std::vector<double> parval
704 // -----------------------------------------------------------------------------------------
705 double MuScleFitUtils::massProb( const double & mass, const double & resEta, const double & rapidity, const double & massResol, const std::vector<double> & parval, const bool doUseBkgrWindow, const double & eta1, const double & eta2 )
706 {
707 #ifdef USE_CALLGRIND
708  CALLGRIND_START_INSTRUMENTATION;
709 #endif
710 
711  double * p = new double[(int)(parval.size())];
712  // Replaced by auto_ptr, which handles delete at the end
713  // Removed auto_ptr, check massResolution for an explanation.
714  // std::auto_ptr<double> p(new double[(int)(parval.size())]);
715 
716  std::vector<double>::const_iterator it = parval.begin();
717  int id = 0;
718  for ( ; it!=parval.end(); ++it, ++id) {
719  // (&*p)[id] = *it;
720  p[id] = *it;
721  }
722  // p must be passed by value as below:
723  double massProbability = massProb( mass, resEta, rapidity, massResol, p, doUseBkgrWindow, eta1, eta2 );
724  delete[] p;
725 
726 #ifdef USE_CALLGRIND
727  CALLGRIND_STOP_INSTRUMENTATION;
728  CALLGRIND_DUMP_STATS;
729 #endif
730 
731  return massProbability;
732 }
733 
739 double MuScleFitUtils::probability( const double & mass, const double & massResol,
740  const double GLvalue[][1001][1001], const double GLnorm[][1001],
741  const int iRes, const int iY )
742 {
743  if( iRes == 0 && iY > 23 ) {
744  std::cout << "WARNING: rapidity bin selected = " << iY << " but there are only histograms for the first 24 bins" << std::endl;
745  }
746 
747  double PS = 0.;
748  bool insideProbMassWindow = true;
749  // Interpolate the four values of GLZValue[] in the
750  // grid square within which the (mass,sigma) values lay
751  // ----------------------------------------------------
752  // This must be done with respect to the width used in the computation of the probability distribution,
753  // so that the bin 0 really matches the bin 0 of that distribution.
754  // double fracMass = (mass-(ResMass[iRes]-ResHalfWidth[iRes]))/(2*ResHalfWidth[iRes]);
755  double fracMass = (mass - ResMinMass[iRes])/(2*ResHalfWidth[iRes]);
756  if (debug>1) std::cout << std::setprecision(9)<<"mass ResMinMass[iRes] ResHalfWidth[iRes] ResHalfWidth[iRes]"
757  << mass << " "<<ResMinMass[iRes]<<" "<<ResHalfWidth[iRes]<<" "<<ResHalfWidth[iRes]<<std::endl;
758  int iMassLeft = (int)(fracMass*(double)nbins);
759  int iMassRight = iMassLeft+1;
760  double fracMassStep = (double)nbins*(fracMass - (double)iMassLeft/(double)nbins);
761  if (debug>1) std::cout<<"nbins iMassLeft fracMass "<<nbins<<" "<<iMassLeft<<" "<<fracMass<<std::endl;
762 
763  // Simple protections for the time being: the region where we fit should not include
764  // values outside the boundaries set by ResMass-ResHalfWidth : ResMass+ResHalfWidth
765  // ---------------------------------------------------------------------------------
766  if (iMassLeft<0) {
767  edm::LogInfo("probability") << "WARNING: fracMass=" << fracMass << ", iMassLeft="
768  << iMassLeft << "; mass = " << mass << " and bounds are " << ResMinMass[iRes]
769  << ":" << ResMinMass[iRes]+2*ResHalfWidth[iRes] << " - iMassLeft set to 0" << std::endl;
770  iMassLeft = 0;
771  iMassRight = 1;
772  insideProbMassWindow = false;
773  }
774  if (iMassRight>nbins) {
775  edm::LogInfo("probability") << "WARNING: fracMass=" << fracMass << ", iMassRight="
776  << iMassRight << "; mass = " << mass << " and bounds are " << ResMinMass[iRes]
777  << ":" << ResMass[iRes]+2*ResHalfWidth[iRes] << " - iMassRight set to " << nbins-1 << std::endl;
778  iMassLeft = nbins-1;
779  iMassRight = nbins;
780  insideProbMassWindow = false;
781  }
782  double fracSigma = (massResol/ResMaxSigma[iRes]);
783  int iSigmaLeft = (int)(fracSigma*(double)nbins);
784  int iSigmaRight = iSigmaLeft+1;
785  double fracSigmaStep = (double)nbins * (fracSigma - (double)iSigmaLeft/(double)nbins);
786  // std::cout << "massResol = " << massResol << std::endl;
787  // std::cout << "ResMaxSigma["<<iRes<<"] = " << ResMaxSigma[iRes] << std::endl;
788  // std::cout << "fracSigma = " << fracSigma << std::endl;
789  // std::cout << "nbins = " << nbins << std::endl;
790  // std::cout << "ISIGMALEFT = " << iSigmaLeft << std::endl;
791  // std::cout << "ISIGMARIGHT = " << iSigmaRight << std::endl;
792  // std::cout << "fracSigmaStep = " << fracSigmaStep << std::endl;
793 
794  // Simple protections for the time being: they should not affect convergence, since
795  // ResMaxSigma is set to very large values, and if massResol exceeds them the fit
796  // should not get any prize for that (for large sigma, the prob. distr. becomes flat)
797  // ----------------------------------------------------------------------------------
798  if (iSigmaLeft<0) {
799  edm::LogInfo("probability") << "WARNING: fracSigma = " << fracSigma << ", iSigmaLeft="
800  << iSigmaLeft << ", with massResol = " << massResol << " and ResMaxSigma[iRes] = "
801  << ResMaxSigma[iRes] << " - iSigmaLeft set to 0" << std::endl;
802  iSigmaLeft = 0;
803  iSigmaRight = 1;
804  }
805  if (iSigmaRight>nbins ) {
806  if (counter_resprob<100)
807  edm::LogInfo("probability") << "WARNING: fracSigma = " << fracSigma << ", iSigmaRight="
808  << iSigmaRight << ", with massResol = " << massResol << " and ResMaxSigma[iRes] = "
809  << ResMaxSigma[iRes] << " - iSigmaRight set to " << nbins-1 << std::endl;
810  iSigmaLeft = nbins-1;
811  iSigmaRight = nbins;
812  }
813 
814  // If f11,f12,f21,f22 are the values at the four corners, one finds by linear interpolation the
815  // formula below for PS
816  // --------------------------------------------------------------------------------------------
817  if( insideProbMassWindow ) {
818  double f11 = 0.;
819  if (GLnorm[iY][iSigmaLeft]>0)
820  f11 = GLvalue[iY][iMassLeft][iSigmaLeft] / GLnorm[iY][iSigmaLeft];
821  double f12 = 0.;
822  if (GLnorm[iY][iSigmaRight]>0)
823  f12 = GLvalue[iY][iMassLeft][iSigmaRight] / GLnorm[iY][iSigmaRight];
824  double f21 = 0.;
825  if (GLnorm[iY][iSigmaLeft]>0)
826  f21 = GLvalue[iY][iMassRight][iSigmaLeft] / GLnorm[iY][iSigmaLeft];
827  double f22 = 0.;
828  if (GLnorm[iY][iSigmaRight]>0)
829  f22 = GLvalue[iY][iMassRight][iSigmaRight] / GLnorm[iY][iSigmaRight];
830  PS = f11 + (f12-f11)*fracSigmaStep + (f21-f11)*fracMassStep +
831  (f22-f21-f12+f11)*fracMassStep*fracSigmaStep;
832  if (PS>0.1 || debug>1) LogDebug("MuScleFitUtils") << "iRes = " << iRes << " PS=" << PS << " f11,f12,f21,f22="
833  << f11 << " " << f12 << " " << f21 << " " << f22 << " "
834  << " fSS=" << fracSigmaStep << " fMS=" << fracMassStep << " iSL, iSR="
835  << iSigmaLeft << " " << iSigmaRight
836  << " GLvalue["<<iY<<"]["<<iMassLeft<<"] = " << GLvalue[iY][iMassLeft][iSigmaLeft]
837  << " GLnorm["<<iY<<"]["<<iSigmaLeft<<"] = " << GLnorm[iY][iSigmaLeft] << std::endl;
838 
839 // if (PS>0.1) std::cout << "iRes = " << iRes << " PS=" << PS << " f11,f12,f21,f22="
840 // << f11 << " " << f12 << " " << f21 << " " << f22 << " "
841 // << " fSS=" << fracSigmaStep << " fMS=" << fracMassStep << " iSL, iSR="
842 // << iSigmaLeft << " " << iSigmaRight << " GLV,GLN="
843 // << GLvalue[iY][iMassLeft][iSigmaLeft]
844 // << " " << GLnorm[iY][iSigmaLeft] << std::endl;
845 
846  }
847  else {
848  edm::LogInfo("probability") << "outside mass probability window. Setting PS["<<iRes<<"] = 0" << std::endl;
849  }
850 
851 // if( PS != PS ) {
852 // std::cout << "ERROR: PS = " << PS << " for iRes = " << iRes << std::endl;
853 
854 // std::cout << "mass = " << mass << ", massResol = " << massResol << std::endl;
855 // std::cout << "fracMass = " << fracMass << ", iMassLeft = " << iMassLeft
856 // << ", iMassRight = " << iMassRight << ", fracMassStep = " << fracMassStep << std::endl;
857 // std::cout << "fracSigma = " << fracSigma << ", iSigmaLeft = " << iSigmaLeft
858 // << ", iSigmaRight = " << iSigmaRight << ", fracSigmaStep = " << fracSigmaStep << std::endl;
859 // std::cout << "ResMaxSigma["<<iRes<<"] = " << ResMaxSigma[iRes] << std::endl;
860 
861 // std::cout << "GLvalue["<<iY<<"]["<<iMassLeft<<"] = " << GLvalue[iY][iMassLeft][iSigmaLeft]
862 // << " GLnorm["<<iY<<"]["<<iSigmaLeft<<"] = " << GLnorm[iY][iSigmaLeft] << std::endl;
863 // }
864 
865  return PS;
866 }
867 
868 // Mass probability - version with linear background included
869 // ----------------------------------------------------------
870 double MuScleFitUtils::massProb( const double & mass, const double & resEta, const double & rapidity, const double & massResol, double * parval, const bool doUseBkgrWindow, const double & eta1, const double & eta2 ) {
871 
872  // This routine computes the likelihood that a given measured mass "measMass" is
873  // the result of a reference mass ResMass[] if the resolution
874  // expected for the two muons is massResol.
875  // This version includes two parameters (the last two in parval, by default)
876  // to size up the background fraction and its relative normalization with respect
877  // to the signal shape.
878  //
879  // We model the signal probability with a Lorentz L(M,H) of resonance mass M and natural width H
880  // convoluted with a gaussian G(m,s) of measured mass m and expected mass resolution s,
881  // by integrating over the intersection of the supports of L and G (which can be made to coincide with
882  // the region where L is non-zero, given that H<<s in most cases) the product L(M,H)*G(m,s) dx as follows:
883  //
884  // GL(m,s) = Int(M-10H,M+10H) [ L(x-M,H) * G(x-m,s) ] dx
885  //
886  // The above convolution is computed numerically by an independent root macro, Probs.C, which outputs
887  // the values in six 1001x1001 grids, one per resonance.
888  //
889  // NB THe following block of explanations for background models is outdated, see detailed
890  // explanations where the code computes PB.
891  // +++++++++++++++++++++++
892  // For the background, instead, we have two choices: a linear and an exponential model.
893  // * For the linear model, we choose a one-parameter form whereby the line is automatically normalized
894  // in the support [x1,x2] where we defined our "signal region", as follows:
895  //
896  // B(x;b) = 1/(x2-x1) + {x - (x2+x1)/2} * b
897  //
898  // Defined as above, B(x) is a line passing for the point of coordinates (x1+x2)/2, 1/(x2-x1),
899  // whose slope b has as support the interval ( -2/[(x1-x2)*(x1+x2)], 2/[(x1-x2)*(x1+x2)] )
900  // so that B(x) is always positive-definite in [x1,x2].
901  //
902  // * For the exponential model, we define B(x;b) as
903  //
904  // B(x;b) = b * { exp(-b*x) / [exp(-b*x1)-exp(-b*x2)] }
905  //
906  // This one-parameter definition is automatically normalized to unity in [x1,x2], with a parameter
907  // b which has to be positive in order for the slope to be negative.
908  // Please note that this model is not useful in most circumstances; a more useful form would be one
909  // which included a linear component.
910  // ++++++++++++++++++++++
911  //
912  // Once GL(m,s) and B(x;b) are defined, we introduce a further parameter a, such that we can have the
913  // likelihood control the relative fraction of signal and background. We first normalize GL(m,s) for
914  // any given s by taking the integral
915  //
916  // Int(x1,x2) GL(m,s) dm = K_s
917  //
918  // We then define the probability as
919  //
920  // P(m,s,a,b) = GL(m,s)/K_s * a + B(x,b) * (1-a)
921  //
922  // with a taking on values in the interval [0,1].
923  // Defined as above, the probability is well-behaved, in the sense that it has a value between 0 and 1,
924  // and the four parameters m,s,a,b fully control its shape.
925  //
926  // It is to be noted that the formulation above requires the computation of two rather time-consuming
927  // integrals. The one defining GL(m,s) can be stored in a TH2D and loaded by the constructor from a
928  // file suitably prepared, and this will save loads of computing time.
929  // ----------------------------------------------------------------------------------------------------
930 
931  double P = 0.;
932  int crossSectionParShift = parResol.size() + parScale.size();
933  // Take the relative cross sections
934  std::vector<double> relativeCrossSections = crossSectionHandler->relativeCrossSections(&(parval[crossSectionParShift]), resfind);
935  // for( unsigned int i=0; i<relativeCrossSections.size(); ++i ) {
936  // std::cout << "relativeCrossSections["<<i<<"] = " << relativeCrossSections[i] << std::endl;
937  // std::cout << "parval["<<crossSectionParShift+i<<"] = " << parval[crossSectionParShift+i] << std::endl;
938  // }
939 
940  // int bgrParShift = crossSectionParShift + parCrossSection.size();
941  int bgrParShift = crossSectionParShift + crossSectionHandler->parNum();
942  double Bgrp1 = 0.;
943  // double Bgrp2 = 0.;
944  // double Bgrp3 = 0.;
945 
946  // NB defined as below, P is a non-rigorous "probability" that we observe
947  // a dimuon mass "mass", given ResMass[], gamma, and massResol. It is what we need for the
948  // fit which finds the best resolution parameters, though. A definition which is
949  // more properly a probability is given below (in massProb2()), where the result
950  // cannot be used to fit resolution parameters because the fit would always prefer
951  // to set the res parameters to the minimum possible value (best resolution),
952  // to have a probability close to one of observing any mass.
953  // -------------------------------------------------------------------------------
954 
955  // Determine what resonance(s) we have to deal with
956  // NB for now we assume equal xs for each resonance
957  // so we do not assign them different weights
958  // ------------------------------------------------
959  double PS[6] = {0.};
960  double PB = 0.;
961  double PStot[6] = {0.};
962 
963  // Should be removed because it is not used
964  bool resConsidered[6] = {false};
965 
966  bool useBackgroundWindow = (doBackgroundFit[loopCounter] || doUseBkgrWindow);
967  // bool useBackgroundWindow = (doBackgroundFit[loopCounter]);
968 
969  // First check the Z, which is divided in 24 rapidity bins
970  // NB max value of Z rapidity to be considered is 2.4 here
971  // -------------------------------------------------------
972 
973  // Do this only if we want to use the rapidity bins for the Z
975  // ATTENTION: cut on Z rapidity at 2.4 since we only have histograms up to that value
976  // std::pair<double, double> windowFactors = backgroundHandler->windowFactors( useBackgroundWindow, 0 );
977  std::pair<double, double> windowBorders = backgroundHandler->windowBorders( useBackgroundWindow, 0 );
978  if( resfind[0]>0
979  // && checkMassWindow( mass, 0,
980  // backgroundHandler->resMass( useBackgroundWindow, 0 ),
981  // windowFactors.first, windowFactors.second )
982  && checkMassWindow( mass, windowBorders.first, windowBorders.second )
983  // && fabs(rapidity)<2.4
984  ) {
985 
986  int iY = (int)(fabs(rapidity)*10.);
987  if( iY > 23 ) iY = 23;
988 
989  if (MuScleFitUtils::debug>1) std::cout << "massProb:resFound = 0, rapidity bin =" << iY << std::endl;
990 
991  // In this case the last value is the rapidity bin
992  PS[0] = probability(mass, massResol, GLZValue, GLZNorm, 0, iY);
993 
994  if( PS[0] != PS[0] ) {
995  std::cout << "ERROR: PS[0] = nan, setting it to 0" << std::endl;
996  PS[0] = 0;
997  }
998 
999  // std::pair<double, double> bgrResult = backgroundHandler->backgroundFunction( doBackgroundFit[loopCounter],
1000  // &(parval[bgrParShift]), MuScleFitUtils::totalResNum, 0,
1001  // resConsidered, ResMass, ResHalfWidth, MuonType, mass, resEta );
1002 
1003  std::pair<double, double> bgrResult = backgroundHandler->backgroundFunction( doBackgroundFit[loopCounter],
1004  &(parval[bgrParShift]), MuScleFitUtils::totalResNum, 0,
1005  resConsidered, ResMass, ResHalfWidth, MuonType, mass, eta1, eta2 );
1006 
1007  Bgrp1 = bgrResult.first;
1008  // When fitting the background we have only one Bgrp1
1009  // When not fitting the background we have many only in a superposition region and this case is treated
1010  // separately after this loop
1011  PB = bgrResult.second;
1012  if( PB != PB ) PB = 0;
1013  PStot[0] = (1-Bgrp1)*PS[0] + Bgrp1*PB;
1014 
1015 
1016  // PStot[0] *= crossSectionHandler->crossSection(0);
1017  // PStot[0] *= parval[crossSectionParShift];
1018  PStot[0] *= relativeCrossSections[0];
1019  if ( MuScleFitUtils::debug > 0 ) std::cout << "PStot["<<0<<"] = " << "(1-"<<Bgrp1<<")*"<<PS[0]<<" + "<<Bgrp1<<"*"<<PB<<" = " << PStot[0] << " (reletiveXS = )" << relativeCrossSections[0] << std::endl;
1020  }
1021  else {
1022  if( debug > 0 ) {
1023  std::cout << "Mass = " << mass << " outside range with rapidity = " << rapidity << std::endl;
1024  std::cout << "with resMass = " << backgroundHandler->resMass( useBackgroundWindow, 0 ) << " and left border = " << windowBorders.first << " right border = " << windowBorders.second << std::endl;
1025  }
1026  }
1027  }
1028  // Next check the other resonances
1029  // -------------------------------
1030  int firstRes = 1;
1031  if( !MuScleFitUtils::rapidityBinsForZ_ ) firstRes = 0;
1032  for( int ires=firstRes; ires<6; ++ires ) {
1033  if( resfind[ires] > 0 ) {
1034  // First is left, second is right (returns (1,1) in the case of resonances, it could be improved avoiding the call in this case)
1035  // std::pair<double, double> windowFactor = backgroundHandler->windowFactors( useBackgroundWindow, ires );
1036  std::pair<double, double> windowBorder = backgroundHandler->windowBorders( useBackgroundWindow, ires );
1037  if( checkMassWindow(mass, windowBorder.first, windowBorder.second) ) {
1038  if (MuScleFitUtils::debug>1) std::cout << "massProb:resFound = " << ires << std::endl;
1039 
1040  // In this case the rapidity value is instead the resonance index again.
1041  PS[ires] = probability(mass, massResol, GLValue, GLNorm, ires, ires);
1042 
1043  std::pair<double, double> bgrResult = backgroundHandler->backgroundFunction( doBackgroundFit[loopCounter],
1044  &(parval[bgrParShift]), MuScleFitUtils::totalResNum, ires,
1045  // resConsidered, ResMass, ResHalfWidth, MuonType, mass, resEta );
1046  resConsidered, ResMass, ResHalfWidth, MuonType, mass, eta1, eta2 );
1047  Bgrp1 = bgrResult.first;
1048  PB = bgrResult.second;
1049 
1050  if( PB != PB ) PB = 0;
1051  PStot[ires] = (1-Bgrp1)*PS[ires] + Bgrp1*PB;
1052  if( MuScleFitUtils::debug>0 ) std::cout << "PStot["<<ires<<"] = " << "(1-"<<Bgrp1<<")*"<<PS[ires]<<" + "<<Bgrp1<<"*"<<PB<<" = " << PStot[ires] << std::endl;
1053 
1054  PStot[ires] *= relativeCrossSections[ires];
1055  }
1056  }
1057  }
1058 
1059  for( int i=0; i<6; ++i ) {
1060  P += PStot[i];
1061  }
1062 
1064  double PStotTemp = 0.;
1065  for( int i=0; i<6; ++i ) {
1066  PStotTemp += PS[i]*relativeCrossSections[i];
1067  }
1068  if( PStotTemp != PStotTemp ) {
1069  std::cout << "ERROR: PStotTemp = nan!!!!!!!!!" << std::endl;
1070  int parnumber = (int)(parResol.size()+parScale.size()+crossSectionHandler->parNum()+parBgr.size());
1071  for( int i=0; i<6; ++i ) {
1072  std::cout << "PS[i] = " << PS[i] << std::endl;
1073  if( PS[i] != PS[i] ) {
1074  std::cout << "mass = " << mass << std::endl;
1075  std::cout << "massResol = " << massResol << std::endl;
1076  for( int j=0; j<parnumber; ++j ) {
1077  std::cout << "parval["<<j<<"] = " << parval[j] << std::endl;
1078  }
1079  }
1080  }
1081  }
1082  if( PStotTemp == PStotTemp ) {
1084  }
1085  if (debug>0) std::cout << "mass = " << mass << ", P = " << P << ", PStot = " << PStotTemp << ", PB = " << PB << ", bgrp1 = " << Bgrp1 << std::endl;
1086 
1088  }
1089  return P;
1090 }
1091 
1092 // Method to check if the mass value is within the mass window of the i-th resonance.
1093 // inline bool MuScleFitUtils::checkMassWindow( const double & mass, const int ires, const double & resMass, const double & leftFactor, const double & rightFactor )
1094 // {
1095 // return( mass-resMass > -leftFactor*massWindowHalfWidth[MuonTypeForCheckMassWindow][ires]
1096 // && mass-resMass < rightFactor*massWindowHalfWidth[MuonTypeForCheckMassWindow][ires] );
1097 // }
1098 inline bool MuScleFitUtils::checkMassWindow( const double & mass, const double & leftBorder, const double & rightBorder )
1099 {
1100  return( (mass > leftBorder) && (mass < rightBorder) );
1101 }
1102 
1103 // Function that returns the weight for a muon pair
1104 // ------------------------------------------------
1105 double MuScleFitUtils::computeWeight( const double & mass, const int iev, const bool doUseBkgrWindow )
1106 {
1107  // Compute weight for this event
1108  // -----------------------------
1109  double weight = 0.;
1110 
1111  // Take the highest-mass resonance within bounds
1112  // NB this must be revised once credible estimates of the relative xs of Y(1S), (2S), and (3S)
1113  // are made. Those are priors in the decision of which resonance to assign to an in-between event.
1114  // -----------------------------------------------------------------------------------------------
1115 
1116  if( doUseBkgrWindow && (debug > 0) ) std::cout << "using backgrond window for mass = " << mass << std::endl;
1117  // bool useBackgroundWindow = (doBackgroundFit[loopCounter] || doUseBkgrWindow);
1118  bool useBackgroundWindow = (doBackgroundFit[loopCounter]);
1119 
1120  for (int ires=0; ires<6; ires++) {
1121  if (resfind[ires]>0 && weight==0.) {
1122  // std::pair<double, double> windowFactor = backgroundHandler->windowFactors( useBackgroundWindow, ires );
1123  std::pair<double, double> windowBorder = backgroundHandler->windowBorders( useBackgroundWindow, ires );
1124  // if( checkMassWindow(mass, ires, backgroundHandler->resMass( useBackgroundWindow, ires ),
1125  // windowFactor.first, windowFactor.second) ) {
1126  if( checkMassWindow(mass, windowBorder.first, windowBorder.second) ) {
1127  weight = 1.0;
1128  if( doUseBkgrWindow && (debug > 0) ) std::cout << "setting weight to = " << weight << std::endl;
1129  }
1130  }
1131  }
1132 
1133  return weight;
1134 }
1135 
1136 // Likelihood minimization routine
1137 // -------------------------------
1139 {
1140  // Output file with fit parameters resulting from minimization
1141  // -----------------------------------------------------------
1142  std::ofstream FitParametersFile;
1143  FitParametersFile.open ("FitParameters.txt", std::ios::app);
1144  FitParametersFile << "Fitting with resolution, scale, bgr function # "
1145  << ResolFitType << " " << ScaleFitType << " " << BgrFitType
1146  << " - Iteration " << loopCounter << std::endl;
1147 
1148  // Fill parvalue and other vectors needed for the fitting
1149  // ------------------------------------------------------
1150 
1151 
1152 
1153 
1154 
1155  // ----- //
1156  // FIXME //
1157  // ----- //
1158  // this was changed to verify the possibility that fixed parameters influence the errors.
1159  // It must be 0 otherwise the parameters for resonances will not be passed by minuit (will be always 0).
1160  // Should be removed.
1161  int parForResonanceWindows = 0;
1162  // int parnumber = (int)(parResol.size()+parScale.size()+parCrossSection.size()+parBgr.size() - parForResonanceWindows);
1163  int parnumber = (int)(parResol.size()+parScale.size()+crossSectionHandler->parNum()+parBgr.size() - parForResonanceWindows);
1164 
1165 
1166 
1167 
1168 
1169 
1170  int parnumberAll = (int)(parResol.size()+parScale.size()+crossSectionHandler->parNum()+parBgr.size());
1171 
1172  // parvalue is a std::vector<std::vector<double> > storing all the parameters from all the loops
1173  parvalue.push_back(parResol);
1174  std::vector<double> *tmpVec = &(parvalue.back());
1175 
1176  // If this is not the first loop we want to start from neutral values
1177  // Otherwise the scale will start with values correcting again a bias
1178  // that is already corrected.
1179  if( scaleFitNotDone_ ) {
1180  tmpVec->insert( tmpVec->end(), parScale.begin(), parScale.end() );
1181  std::cout << "scaleFitNotDone: tmpVec->size() = " << tmpVec->size() << std::endl;
1182  }
1183  else {
1184  scaleFunction->resetParameters(tmpVec);
1185  std::cout << "scaleFitDone: tmpVec->size() = " << tmpVec->size() << std::endl;
1186  }
1187  tmpVec->insert( tmpVec->end(), parCrossSection.begin(), parCrossSection.end() );
1188  tmpVec->insert( tmpVec->end(), parBgr.begin(), parBgr.end() );
1189  int i = 0;
1190  std::vector<double>::const_iterator it = tmpVec->begin();
1191  for( ; it != tmpVec->end(); ++it, ++i ) {
1192  std::cout << "tmpVec["<<i<<"] = " << *it << std::endl;
1193  }
1194 
1195  // Empty vector of size = number of cross section fitted parameters. Note that the cross section
1196  // fit works in a different way than the others and it uses ratios of the paramters passed via cfg.
1197  // We use this empty vector for compatibility with the rest of the structure.
1198  std::vector<int> crossSectionParNumSizeVec( MuScleFitUtils::crossSectionHandler->parNum(), 0 );
1199 
1200  std::vector<int> parfix(parResolFix);
1201  parfix.insert( parfix.end(), parScaleFix.begin(), parScaleFix.end() );
1202  parfix.insert( parfix.end(), crossSectionParNumSizeVec.begin(), crossSectionParNumSizeVec.end() );
1203  parfix.insert( parfix.end(), parBgrFix.begin(), parBgrFix.end() );
1204 
1205  std::vector<int> parorder(parResolOrder);
1206  parorder.insert( parorder.end(), parScaleOrder.begin(), parScaleOrder.end() );
1207  parorder.insert( parorder.end(), crossSectionParNumSizeVec.begin(), crossSectionParNumSizeVec.end() );
1208  parorder.insert( parorder.end(), parBgrOrder.begin(), parBgrOrder.end() );
1209 
1210  // This is filled later
1211  std::vector<double> parerr(3*parnumberAll,0.);
1212 
1213  if (debug>19) {
1214  std::cout << "[MuScleFitUtils-minimizeLikelihood]: Parameters before likelihood " << std::endl;
1215  for (unsigned int i=0; i<(unsigned int)parnumberAll; i++) {
1216  std::cout << " Par # " << i << " = " << parvalue[loopCounter][i] << " : free = " << parfix[i] << "; order = "
1217  << parorder[i] << std::endl;
1218  }
1219  }
1220 
1221 // // Background rescaling from regions to resonances
1222 // // -----------------------------------------------
1223 // // If we are in a loop > 0 and we are not fitting the background, but we have fitted it in the previous iteration
1224 // if( loopCounter > 0 && !(doBackgroundFit[loopCounter]) && doBackgroundFit[loopCounter-1] ) {
1225 // // This rescales from regions to resonances
1226 // int localMuonType = MuonType;
1227 // if( MuonType > 2 ) localMuonType = 2;
1228 // backgroundHandler->rescale( parBgr, ResMass, massWindowHalfWidth[localMuonType],
1229 // MuScleFitUtils::SavedPair);
1230 // }
1231 
1232  // Init Minuit
1233  // -----------
1234  TMinuit rmin (parnumber);
1235  rminPtr_ = &rmin;
1236  rmin.SetFCN (likelihood); // Unbinned likelihood
1237  // Standard initialization of minuit parameters:
1238  // sets input to be $stdin, output to be $stdout
1239  // and saving to a file.
1240  rmin.mninit (5, 6, 7);
1241  int ierror = 0;
1242  int istat;
1243  double arglis[4];
1244  arglis[0] = FitStrategy; // Strategy 1 or 2
1245  // 1 standard
1246  // 2 try to improve minimum (slower)
1247  rmin.mnexcm ("SET STR", arglis, 1, ierror);
1248 
1249  arglis[0] = 10001;
1250  // Set the random seed for the generator used in SEEk to a fixed value for reproducibility
1251  rmin.mnexcm("SET RAN", arglis, 1, ierror);
1252 
1253  // Set fit parameters
1254  // ------------------
1255  double * Start = new double[parnumberAll];
1256  double * Step = new double[parnumberAll];
1257  double * Mini = new double[parnumberAll];
1258  double * Maxi = new double[parnumberAll];
1259  int * ind = new int[parnumberAll]; // Order of release of parameters
1260  TString * parname = new TString[parnumberAll];
1261 
1262  if( !parResolStep.empty() && !parResolMin.empty() && !parResolMax.empty() ) {
1263  MuScleFitUtils::resolutionFunctionForVec->setParameters( Start, Step, Mini, Maxi, ind, parname, parResol, parResolOrder, parResolStep, parResolMin, parResolMax, MuonType );
1264  }
1265  else {
1266  MuScleFitUtils::resolutionFunctionForVec->setParameters( Start, Step, Mini, Maxi, ind, parname, parResol, parResolOrder, MuonType );
1267  }
1268 
1269  // Take the number of parameters in the resolutionFunction and displace the arrays passed to the scaleFunction
1270  int resParNum = MuScleFitUtils::resolutionFunctionForVec->parNum();
1271 
1272  if( !parScaleStep.empty() && !parScaleMin.empty() && !parScaleMax.empty() ) {
1273  MuScleFitUtils::scaleFunctionForVec->setParameters( &(Start[resParNum]), &(Step[resParNum]),
1274  &(Mini[resParNum]), &(Maxi[resParNum]),
1275  &(ind[resParNum]), &(parname[resParNum]),
1278  }
1279  else {
1280  MuScleFitUtils::scaleFunctionForVec->setParameters( &(Start[resParNum]), &(Step[resParNum]),
1281  &(Mini[resParNum]), &(Maxi[resParNum]),
1282  &(ind[resParNum]), &(parname[resParNum]),
1284  }
1285 
1286  // Initialize cross section parameters
1287  int crossSectionParShift = resParNum + MuScleFitUtils::scaleFunctionForVec->parNum();
1288  MuScleFitUtils::crossSectionHandler->setParameters( &(Start[crossSectionParShift]), &(Step[crossSectionParShift]), &(Mini[crossSectionParShift]),
1289  &(Maxi[crossSectionParShift]), &(ind[crossSectionParShift]), &(parname[crossSectionParShift]),
1291 
1292  // Initialize background parameters
1293  int bgrParShift = crossSectionParShift + crossSectionHandler->parNum();
1294  MuScleFitUtils::backgroundHandler->setParameters( &(Start[bgrParShift]), &(Step[bgrParShift]), &(Mini[bgrParShift]), &(Maxi[bgrParShift]),
1295  &(ind[bgrParShift]), &(parname[bgrParShift]), parBgr, parBgrOrder, MuonType );
1296 
1297  for( int ipar=0; ipar<parnumber; ++ipar ) {
1298  std::cout << "parname["<<ipar<<"] = " << parname[ipar] << std::endl;
1299  std::cout << "Start["<<ipar<<"] = " << Start[ipar] << std::endl;
1300  std::cout << "Step["<<ipar<<"] = " << Step[ipar] << std::endl;
1301  std::cout << "Mini["<<ipar<<"] = " << Mini[ipar] << std::endl;
1302  std::cout << "Maxi["<<ipar<<"] = " << Maxi[ipar] << std::endl;
1303 
1304 
1305  rmin.mnparm( ipar, parname[ipar], Start[ipar], Step[ipar], Mini[ipar], Maxi[ipar], ierror );
1306 
1307 
1308  // Testing without limits
1309  // rmin.mnparm( ipar, parname[ipar], Start[ipar], Step[ipar], 0, 0, ierror );
1310 
1311 
1312  }
1313 
1314  // Do minimization
1315  // ---------------
1316  if (debug>19)
1317  std::cout << "[MuScleFitUtils-minimizeLikelihood]: Starting minimization" << std::endl;
1318  double fmin;
1319  double fdem;
1320  double errdef;
1321  int npari;
1322  int nparx;
1323  rmin.mnexcm ("CALL FCN", arglis, 1, ierror);
1324 
1325  // First, fix all parameters
1326  // -------------------------
1327  if (debug>19)
1328  std::cout << "[MuScleFitUtils-minimizeLikelihood]: First fix all parameters ...";
1329  for (int ipar=0; ipar<parnumber; ipar++) {
1330  rmin.FixParameter (ipar);
1331  }
1332 
1333  // Then release them in the specified order and refit
1334  // --------------------------------------------------
1335  if (debug>19) std::cout << " Then release them in order..." << std::endl;
1336 
1337  TString name;
1338  double pval;
1339  double pmin;
1340  double pmax;
1341  double errp;
1342  double errl;
1343  double errh;
1344  int ivar;
1345  double erro;
1346  double cglo;
1347  int n_times = 0;
1348  // n_times = number of loops required to unlock all parameters.
1349 
1350  if (debug>19) std::cout << "Before scale parNum" << std::endl;
1351  int scaleParNum = scaleFunction->parNum();
1352  if (debug>19) std::cout << "After scale parNum" << std::endl;
1353  // edm::LogInfo("minimizeLikelihood") << "number of parameters for scaleFunction = " << scaleParNum << std::endl;
1354  // edm::LogInfo("minimizeLikelihood") << "number of parameters for resolutionFunction = " << resParNum << std::endl;
1355  // edm::LogInfo("minimizeLikelihood") << "number of parameters for cross section = " << crossSectionHandler->parNum() << std::endl;
1356  // edm::LogInfo("minimizeLikelihood") << "number of parameters for backgroundFunction = " << parBgr.size() << std::endl;
1357  std::cout << "number of parameters for scaleFunction = " << scaleParNum << std::endl;
1358  std::cout << "number of parameters for resolutionFunction = " << resParNum << std::endl;
1359  std::cout << "number of parameters for cross section = " << crossSectionHandler->parNum() << std::endl;
1360  std::cout << "number of parameters for backgroundFunction = " << parBgr.size() << std::endl;
1361  // edm::LogInfo("minimizeLikelihood") << "number of parameters for backgroundFunction = " << backgroundFunction->parNum() << std::endl;
1362 
1363  for (int i=0; i<parnumber; i++) {
1364  // NB ind[] has been set as parorder[] previously
1365  if (n_times<ind[i]) {
1366  edm::LogInfo("minimizeLikelihood") << "n_times = " << n_times << ", ind["<<i<<"] = " << ind[i] << ", scaleParNum = " << scaleParNum << ", doScaleFit["<<loopCounter<<"] = " << doScaleFit[loopCounter] << std::endl;
1367  // Set the n_times only if we will do the fit
1368  if ( i<resParNum ) {
1369  if( doResolFit[loopCounter] ) n_times = ind[i];
1370  }
1371  else if( i<resParNum+scaleParNum ) {
1372  if( doScaleFit[loopCounter] ) n_times = ind[i];
1373  }
1374  else if( doBackgroundFit[loopCounter] ) n_times = ind[i];
1375  }
1376  }
1377  for (int iorder=0; iorder<n_times+1; iorder++) { // Repeat fit n_times times
1378  std::cout << "Starting minimization " << iorder << " of " << n_times << std::endl;
1379 
1380  bool somethingtodo = false;
1381 
1382  // Use parameters from cfg to select which fit to do
1383  // -------------------------------------------------
1384  if( doResolFit[loopCounter] ) {
1385  // Release resolution parameters and fit them
1386  // ------------------------------------------
1387  for( unsigned int ipar=0; ipar<parResol.size(); ++ipar ) {
1388  if( parfix[ipar]==0 && ind[ipar]==iorder ) {
1389  rmin.Release( ipar );
1390  somethingtodo = true;
1391  }
1392  }
1393  }
1394  if( doScaleFit[loopCounter] ) {
1395  // Release scale parameters and fit them
1396  // -------------------------------------
1397  for( unsigned int ipar=parResol.size(); ipar<parResol.size()+parScale.size(); ++ipar ) {
1398  if( parfix[ipar]==0 && ind[ipar]==iorder ) { // parfix=0 means parameter is free
1399  rmin.Release( ipar );
1400  somethingtodo = true;
1401  }
1402  }
1403  scaleFitNotDone_ = false;
1404  }
1405  unsigned int crossSectionParShift = parResol.size()+parScale.size();
1406  if( doCrossSectionFit[loopCounter] ) {
1407  // Release cross section parameters and fit them
1408  // ---------------------------------------------
1409  // Note that only cross sections of resonances that are being fitted are released
1410  bool doCrossSection = crossSectionHandler->releaseParameters( rmin, resfind, parfix, ind, iorder, crossSectionParShift );
1411  if( doCrossSection ) somethingtodo = true;
1412  }
1413  if( doBackgroundFit[loopCounter] ) {
1414  // Release background parameters and fit them
1415  // ------------------------------------------
1416  // for( int ipar=parResol.size()+parScale.size(); ipar<parnumber; ++ipar ) {
1417  // Free only the parameters for the regions, as the resonances intervals are never used to fit the background
1418  unsigned int bgrParShift = crossSectionParShift+crossSectionHandler->parNum();
1419  for( unsigned int ipar = bgrParShift; ipar < bgrParShift+backgroundHandler->regionsParNum(); ++ipar ) {
1420  // Release only those parameters for the resonances we are fitting
1421  if( parfix[ipar]==0 && ind[ipar]==iorder && backgroundHandler->unlockParameter(resfind, ipar - bgrParShift) ) {
1422  rmin.Release( ipar );
1423  somethingtodo = true;
1424  }
1425  }
1426  }
1427 
1428  // OK, now do minimization if some parameter has been released
1429  // -----------------------------------------------------------
1430  if( somethingtodo ) {
1431 // #ifdef DEBUG
1432 
1433  std::stringstream fileNum;
1434  fileNum << loopCounter;
1435 
1436  minuitLoop_ = 0;
1437  char name[50];
1438  sprintf(name, "likelihoodInLoop_%d_%d", loopCounter, iorder);
1439  TH1D * tempLikelihoodInLoop = new TH1D(name, "likelihood value in minuit loop", 10000, 0, 10000);
1440  likelihoodInLoop_ = tempLikelihoodInLoop;
1441  char signalProbName[50];
1442  sprintf(signalProbName, "signalProb_%d_%d", loopCounter, iorder);
1443  TH1D * tempSignalProb = new TH1D(signalProbName, "signal probability", 10000, 0, 10000);
1444  signalProb_ = tempSignalProb;
1445  char backgroundProbName[50];
1446  sprintf(backgroundProbName, "backgroundProb_%d_%d", loopCounter, iorder);
1447  TH1D * tempBackgroundProb = new TH1D(backgroundProbName, "background probability", 10000, 0, 10000);
1448  backgroundProb_ = tempBackgroundProb;
1449 // #endif
1450 
1451 
1452 
1453  // Before we start the minimization we create a list of events with only the events inside a smaller
1454  // window than the one in which the probability is != 0. We will compute the probability for all those
1455  // events and hopefully the margin will avoid them to get a probability = 0 (which causes a discontinuity
1456  // in the likelihood function). The width of this smaller window must be optimized, but we can start using
1457  // an 90% of the normalization window.
1458  double protectionFactor = 0.9;
1459 
1461  for( unsigned int nev=0; nev<MuScleFitUtils::SavedPair.size(); ++nev ) {
1462  const lorentzVector * recMu1 = &(MuScleFitUtils::SavedPair[nev].first);
1463  const lorentzVector * recMu2 = &(MuScleFitUtils::SavedPair[nev].second);
1464  double mass = MuScleFitUtils::invDimuonMass( *recMu1, *recMu2 );
1465  // Test all resonances to see if the mass is inside at least one of the windows
1466  bool check = false;
1467  for( int ires = 0; ires < 6; ++ires ) {
1468  // std::pair<double, double> windowFactor = backgroundHandler->windowFactors( doBackgroundFit[loopCounter], ires );
1469  std::pair<double, double> windowBorder = backgroundHandler->windowBorders( doBackgroundFit[loopCounter], ires );
1470  // if( resfind[ires] && checkMassWindow( mass, ires, backgroundHandler->resMass( doBackgroundFit[loopCounter], ires ),
1471  // 0.9*windowFactor.first, 0.9*windowFactor.second ) ) {
1472  // double resMassValue = backgroundHandler->resMass( doBackgroundFit[loopCounter], ires );
1473  // double windowBorderLeft = resMassValue - protectionFactor*(resMassValue - windowBorder.first);
1474  // double windowBorderRight = resMassValue + protectionFactor*(windowBorder.second - resMassValue);
1475  double windowBorderShift = (windowBorder.second - windowBorder.first)*(1-protectionFactor)/2.;
1476  double windowBorderLeft = windowBorder.first + windowBorderShift;
1477  double windowBorderRight = windowBorder.second - windowBorderShift;
1478  if( resfind[ires] && checkMassWindow( mass, windowBorderLeft, windowBorderRight ) ) {
1479  check = true;
1480  }
1481  }
1482  if( check ) {
1483  MuScleFitUtils::ReducedSavedPair.push_back(std::make_pair(*recMu1, *recMu2));
1484  }
1485  }
1486  std::cout << "Fitting with " << MuScleFitUtils::ReducedSavedPair.size() << " events" << std::endl;
1487 
1488 
1489  // rmin.SetMaxIterations(500*parnumber);
1490 
1491  //Print some informations
1492  std::cout<<"MINUIT is starting the minimization for the iteration number "<<loopCounter<<std::endl;
1493 
1494  //Try to set iterations
1495  // rmin.SetMaxIterations(100000);
1496 
1497  std::cout<<"maxNumberOfIterations (just set) = "<<rmin.GetMaxIterations()<<std::endl;
1498 
1500 
1501  // Maximum number of iterations
1502  arglis[0] = 100000;
1503  // tolerance
1504  arglis[1] = 0.1;
1505 
1506  // Run simplex first to get an initial estimate of the minimum
1507  if( startWithSimplex_ ) {
1508  rmin.mnexcm( "SIMPLEX", arglis, 0, ierror );
1509  }
1510 
1511  rmin.mnexcm( "MIGRAD", arglis, 2, ierror );
1512 
1513 
1514 
1515 
1516 // #ifdef DEBUG
1517  likelihoodInLoop_->Write();
1518  signalProb_->Write();
1519  backgroundProb_->Write();
1520  delete tempLikelihoodInLoop;
1521  delete tempSignalProb;
1522  delete tempBackgroundProb;
1523  likelihoodInLoop_ = 0;
1524  signalProb_ = 0;
1525  backgroundProb_ = 0;
1526 // #endif
1527 
1528 
1529  // Compute again the error matrix
1530  rmin.mnexcm( "HESSE", arglis, 0, ierror );
1531 
1532  // Peform minos error analysis.
1533  if( computeMinosErrors_ ) {
1534  duringMinos_ = true;
1535  rmin.mnexcm( "MINOS", arglis, 0, ierror );
1536  duringMinos_ = false;
1537  }
1538 
1539  if( normalizationChanged_ > 1 ) {
1540  std::cout << "WARNING: normalization changed during fit meaning that events exited from the mass window. This causes a discontinuity in the likelihood function. Please check the scan of the likelihood as a function of the parameters to see if there are discontinuities around the minimum." << std::endl;
1541  }
1542  }
1543 
1544  // bool notWritten = true;
1545  for (int ipar=0; ipar<parnumber; ipar++) {
1546 
1547  rmin.mnpout (ipar, name, pval, erro, pmin, pmax, ivar);
1548  // Save parameters in parvalue[] vector
1549  // ------------------------------------
1550  if (ierror!=0 && debug>0) {
1551  std::cout << "[MuScleFitUtils-minimizeLikelihood]: ierror!=0, bogus pars" << std::endl;
1552  }
1553  // for (int ipar=0; ipar<parnumber; ipar++) {
1554  // rmin.mnpout (ipar, name, pval, erro, pmin, pmax, ivar);
1555  parvalue[loopCounter][ipar] = pval;
1556  // }
1557 
1558 
1559  // int ilax2 = 0;
1560  // Double_t val2pl, val2mi;
1561  // rmin.mnmnot (ipar+1, ilax2, val2pl, val2mi);
1562  rmin.mnerrs (ipar, errh, errl, errp, cglo);
1563 
1564 
1565  // Set error on params
1566  // -------------------
1567  if (errp!=0) {
1568  parerr[3*ipar] = errp;
1569  } else {
1570  parerr[3*ipar] = (((errh)>(fabs(errl)))?(errh):(fabs(errl)));
1571  }
1572  parerr[3*ipar+1] = errl;
1573  parerr[3*ipar+2] = errh;
1574 
1575  if( ipar == 0 ) {
1576  FitParametersFile << " Resolution fit parameters:" << std::endl;
1577  }
1578  if( ipar == int(parResol.size()) ) {
1579  FitParametersFile << " Scale fit parameters:" << std::endl;
1580  }
1581  if( ipar == int(parResol.size()+parScale.size()) ) {
1582  FitParametersFile << " Cross section fit parameters:" << std::endl;
1583  }
1584  if( ipar == int(parResol.size()+parScale.size()+crossSectionHandler->parNum()) ) {
1585  FitParametersFile << " Background fit parameters:" << std::endl;
1586  }
1587 // if( ipar >= int(parResol.size()+parScale.size()) && ipar < int(parResol.size()+parScale.size()+crossSectionHandler->parNum()) && notWritted ) {
1588 
1589 // std::vector<double> relativeCrossSections = crossSectionHandler->relativeCrossSections(&(parvalue[loopCounter][parResol.size()+parScale.size()]));
1590 // std::vector<double>::const_iterator it = relativeCrossSections.begin();
1591 // for( ; it != relativeCrossSections.end(); ++it ) {
1592 // FitParametersFile << " Results of the fit: parameter " << ipar << " has value "
1593 // << *it << "+-" << 0
1594 // << " + " << 0 << " - " << 0
1595 // << " /t/t (" << 0 << ")" << std::endl;
1596 // }
1597 
1598 // notWritten = false;
1599 // }
1600 // else {
1601  FitParametersFile << " Results of the fit: parameter " << ipar << " has value "
1602  << pval << "+-" << parerr[3*ipar]
1603  << " + " << parerr[3*ipar+1] << " - " << parerr[3*ipar+2]
1604  // << " \t\t (" << parname[ipar] << ")"
1605  << std::endl;
1606 
1607 
1608 
1609  }
1610  rmin.mnstat (fmin, fdem, errdef, npari, nparx, istat); // NNBB Commented for a check!
1611  FitParametersFile << std::endl;
1612 
1613  if( minimumShapePlots_ ) {
1614  // Create plots of the minimum vs parameters
1615  // -----------------------------------------
1616  // Keep this after the parameters filling because it recomputes the values and it can compromise the fit results.
1617  if( somethingtodo ) {
1618  std::stringstream iorderString;
1619  iorderString << iorder;
1620  std::stringstream iLoopString;
1621  iLoopString << loopCounter;
1622 
1623  for (int ipar=0; ipar<parnumber; ipar++) {
1624  if( parfix[ipar] == 1 ) continue;
1625  std::cout << "plotting parameter = " << ipar+1 << std::endl;
1626  std::stringstream iparString;
1627  iparString << ipar+1;
1628  std::stringstream iparStringName;
1629  iparStringName << ipar;
1630  rmin.mncomd( ("scan "+iparString.str()).c_str(), ierror );
1631  if( ierror == 0 ) {
1632  TCanvas * canvas = new TCanvas(("likelihoodCanvas_loop_"+iLoopString.str()+"_oder_"+iorderString.str()+"_par_"+iparStringName.str()).c_str(), ("likelihood_"+iparStringName.str()).c_str(), 1000, 800);
1633  canvas->cd();
1634  // arglis[0] = ipar;
1635  // rmin.mnexcm( "SCA", arglis, 0, ierror );
1636  TGraph * graph = (TGraph*)rmin.GetPlot();
1637  graph->Draw("AP");
1638  // graph->SetTitle(("parvalue["+iparStringName.str()+"]").c_str());
1639  graph->SetTitle(parname[ipar]);
1640  // graph->Write();
1641 
1642  canvas->Write();
1643  }
1644  }
1645 
1646  // // Draw contours of the fit
1647  // TCanvas * canvas = new TCanvas(("contourCanvas_oder_"+iorderString.str()).c_str(), "contour", 1000, 800);
1648  // canvas->cd();
1649  // TGraph * contourGraph = (TGraph*)rmin.Contour(4, 2, 4);
1650  // if( (rmin.GetStatus() == 0) || (rmin.GetStatus() >= 3) ) {
1651  // contourGraph->Draw("AP");
1652  // }
1653  // else {
1654  // std::cout << "Contour graph error: status = " << rmin.GetStatus() << std::endl;
1655  // }
1656  // canvas->Write();
1657  }
1658  }
1659 
1660  } // end loop on iorder
1661  FitParametersFile.close();
1662 
1663  std::cout << "[MuScleFitUtils-minimizeLikelihood]: Parameters after likelihood " << std::endl;
1664  for (unsigned int ipar=0; ipar<(unsigned int)parnumber; ipar++) {
1665  std::cout << ipar << " " << parvalue[loopCounter][ipar] << " : free = "
1666  << parfix[ipar] << "; order = " << parorder[ipar] << std::endl;
1667  }
1668 
1669  // Put back parvalue into parResol, parScale, parCrossSection, parBgr
1670  // ------------------------------------------------------------------
1671  for( int i=0; i<(int)(parResol.size()); ++i ) {
1673  }
1674  for( int i=0; i<(int)(parScale.size()); ++i ) {
1675  parScale[i] = parvalue[loopCounter][i+parResol.size()];
1676  }
1678  for( unsigned int i=0; i<parCrossSection.size(); ++i ) {
1679  // parCrossSection[i] = parvalue[loopCounter][i+parResol.size()+parScale.size()];
1680  std::cout << "relative cross section["<<i<<"] = " << parCrossSection[i] << std::endl;
1681  }
1682  // Save only the fitted background parameters
1683  for( unsigned int i = 0; i<(parBgr.size() - parForResonanceWindows); ++i ) {
1685  }
1686 
1687  // Background rescaling from regions to resonances
1688  // -----------------------------------------------
1689  // Only if we fitted the background
1690  if( doBackgroundFit[loopCounter] ) {
1691  // This rescales from regions to resonances
1692  int localMuonType = MuonType;
1693  if( MuonType > 2 ) localMuonType = 2;
1696  }
1697 
1698  // Delete the arrays used to set some parameters
1699  delete[] Start;
1700  delete[] Step;
1701  delete[] Mini;
1702  delete[] Maxi;
1703  delete[] ind;
1704  delete[] parname;
1705 }
1706 
1707 // Likelihood function
1708 // -------------------
1709 extern "C" void likelihood( int& npar, double* grad, double& fval, double* xval, int flag ) {
1710 
1711  if (MuScleFitUtils::debug>19) std::cout << "[MuScleFitUtils-likelihood]: In likelihood function" << std::endl;
1712 
1713  const lorentzVector * recMu1;
1714  const lorentzVector * recMu2;
1715  lorentzVector corrMu1;
1716  lorentzVector corrMu2;
1717 
1718  // if (MuScleFitUtils::debug>19) {
1719  // int parnumber = (int)(MuScleFitUtils::parResol.size()+MuScleFitUtils::parScale.size()+
1720  // MuScleFitUtils::parCrossSection.size()+MuScleFitUtils::parBgr.size());
1721  // std::cout << "[MuScleFitUtils-likelihood]: Looping on tree with ";
1722  // for (int ipar=0; ipar<parnumber; ipar++) {
1723  // std::cout << "Parameter #" << ipar << " with value " << xval[ipar] << " ";
1724  // }
1725  // std::cout << std::endl;
1726  // }
1727 
1728  // Loop on the tree
1729  // ----------------
1730  double flike = 0;
1731  int evtsinlik = 0;
1732  int evtsoutlik = 0;
1733  // std::cout << "SavedPair.size() = " << MuScleFitUtils::SavedPair.size() << std::endl;
1734  if( MuScleFitUtils::debug>0 ) {
1735  std::cout << "SavedPair.size() = " << MuScleFitUtils::SavedPair.size() << std::endl;
1736  std::cout << "ReducedSavedPair.size() = " << MuScleFitUtils::ReducedSavedPair.size() << std::endl;
1737  }
1738  // for( unsigned int nev=0; nev<MuScleFitUtils::SavedPair.size(); ++nev ) {
1739  for( unsigned int nev=0; nev<MuScleFitUtils::ReducedSavedPair.size(); ++nev ) {
1740 
1741  // recMu1 = &(MuScleFitUtils::SavedPair[nev].first);
1742  // recMu2 = &(MuScleFitUtils::SavedPair[nev].second);
1743  recMu1 = &(MuScleFitUtils::ReducedSavedPair[nev].first);
1744  recMu2 = &(MuScleFitUtils::ReducedSavedPair[nev].second);
1745 
1746  // Compute original mass
1747  // ---------------------
1748  double mass = MuScleFitUtils::invDimuonMass( *recMu1, *recMu2 );
1749 
1750  // Compute weight and reference mass (from original mass)
1751  // ------------------------------------------------------
1753  if( weight!=0. ) {
1754  // Compute corrected mass (from previous biases) only if we are currently fitting the scale
1755  // ----------------------------------------------------------------------------------------
1757 // std::cout << "Original pt1 = " << corrMu1.Pt() << std::endl;
1758 // std::cout << "Original pt2 = " << corrMu2.Pt() << std::endl;
1759  corrMu1 = MuScleFitUtils::applyScale(*recMu1, xval, -1);
1760  corrMu2 = MuScleFitUtils::applyScale(*recMu2, xval, 1);
1761 
1762 // if( (corrMu1.Pt() != corrMu1.Pt()) || (corrMu2.Pt() != corrMu2.Pt()) ) {
1763 // std::cout << "Rescaled pt1 = " << corrMu1.Pt() << std::endl;
1764 // std::cout << "Rescaled pt2 = " << corrMu2.Pt() << std::endl;
1765 // }
1766 // std::cout << "Rescaled pt1 = " << corrMu1.Pt() << std::endl;
1767 // std::cout << "Rescaled pt2 = " << corrMu2.Pt() << std::endl;
1768  }
1769  else {
1770  corrMu1 = *recMu1;
1771  corrMu2 = *recMu2;
1772 
1773 // if( (corrMu1.Pt() != corrMu1.Pt()) || (corrMu2.Pt() != corrMu2.Pt()) ) {
1774 // std::cout << "Not rescaled pt1 = " << corrMu1.Pt() << std::endl;
1775 // std::cout << "Not rescaled pt2 = " << corrMu2.Pt() << std::endl;
1776 // }
1777  }
1778  double corrMass = MuScleFitUtils::invDimuonMass(corrMu1, corrMu2);
1779  double Y = (corrMu1+corrMu2).Rapidity();
1780  double resEta = (corrMu1+corrMu2).Eta();
1781  if( MuScleFitUtils::debug>19 ) {
1782  std::cout << "[MuScleFitUtils-likelihood]: Original/Corrected resonance mass = " << mass
1783  << " / " << corrMass << std::endl;
1784  }
1785 
1786  // Compute mass resolution
1787  // -----------------------
1788  double massResol = MuScleFitUtils::massResolution(corrMu1, corrMu2, xval);
1789  if (MuScleFitUtils::debug>19)
1790  std::cout << "[MuScleFitUtils-likelihood]: Resolution is " << massResol << std::endl;
1791 
1792  // Compute probability of this mass value including background modeling
1793  // --------------------------------------------------------------------
1794  if (MuScleFitUtils::debug>1) std::cout << "calling massProb inside likelihood function" << std::endl;
1795 
1796  // double prob = MuScleFitUtils::massProb( corrMass, resEta, Y, massResol, xval );
1797  double prob = MuScleFitUtils::massProb( corrMass, resEta, Y, massResol, xval, false, corrMu1.eta(), corrMu2.eta() );
1798  if (MuScleFitUtils::debug>1) std::cout << "likelihood:massProb = " << prob << std::endl;
1799 
1800  // Compute likelihood
1801  // ------------------
1802  if( prob>0 ) {
1803  // flike += log(prob*10000)*weight; // NNBB! x10000 to see if we can recover the problem of boundary
1804  flike += log(prob)*weight;
1805  evtsinlik += 1; // NNBB test: see if likelihood per event is smarter (boundary problem)
1806  } else {
1807  if( MuScleFitUtils::debug > 0 ) {
1808  std::cout << "WARNING: corrMass = " << corrMass << " outside window, this will cause a discontinuity in the likelihood. Consider increasing the safety bands which are now set to 90% of the normalization window to avoid this problem" << std::endl;
1809  std::cout << "Original mass was = " << mass << std::endl;
1810  std::cout << "WARNING: massResol = " << massResol << " outside window" << std::endl;
1811  }
1812  evtsoutlik += 1;
1813  }
1814  if (MuScleFitUtils::debug>19)
1815  std::cout << "[MuScleFitUtils-likelihood]: Mass probability = " << prob << std::endl;
1816  } // weight!=0
1817 
1818  } // End of loop on tree events
1819 
1820 // // Protection for low statistic. If the likelihood manages to throw out all the signal
1821 // // events and stays with ~ 10 events in the resonance window it could have a better likelihood
1822 // // because of ~ uniformly distributed events (a random combination could be good and spoil the fit).
1823 // // We require that the number of events included in the fit does not change more than 5% in each minuit loop.
1824 // bool lowStatPenalty = false;
1825 // if( MuScleFitUtils::minuitLoop_ > 0 ) {
1826 // double newEventsOutInRatio = double(evtsinlik);
1827 // // double newEventsOutInRatio = double(evtsoutlik)/double(evtsinlik);
1828 // double ratio = newEventsOutInRatio/MuScleFitUtils::oldEventsOutInRatio_;
1829 // MuScleFitUtils::oldEventsOutInRatio_ = newEventsOutInRatio;
1830 // if( ratio < 0.8 || ratio > 1.2 ) {
1831 // std::cout << "Warning: too much change from oldEventsInLikelihood to newEventsInLikelihood, ratio is = " << ratio << std::endl;
1832 // std::cout << "oldEventsInLikelihood = " << MuScleFitUtils::oldEventsOutInRatio_ << ", newEventsInLikelihood = " << newEventsOutInRatio << std::endl;
1833 // lowStatPenalty = true;
1834 // }
1835 // }
1836 
1837  // It is a product of probabilities, we compare the sqrt_N of them. Thus N becomes a denominator of the logarithm.
1838  if( evtsinlik != 0 ) {
1839 
1841  // && !(MuScleFitUtils::duringMinos_) ) {
1842  if( MuScleFitUtils::rminPtr_ == 0 ) {
1843  std::cout << "ERROR: rminPtr_ = " << MuScleFitUtils::rminPtr_ << ", code will crash" << std::endl;
1844  }
1845  double normalizationArg[] = {1/double(evtsinlik)};
1846  // Reset the normalizationArg only if it changed
1847  if( MuScleFitUtils::oldNormalization_ != normalizationArg[0] ) {
1848  int ierror = 0;
1849 // if( MuScleFitUtils::likelihoodInLoop_ != 0 ) {
1850 // // This condition is set only when minimizing. Later calls of hesse and minos will not change the value
1851 // // This is done to avoid minos being confused by changing the UP parameter during its computation.
1852 // MuScleFitUtils::rminPtr_->mnexcm("SET ERR", normalizationArg, 1, ierror);
1853 // }
1854  MuScleFitUtils::rminPtr_->mnexcm("SET ERR", normalizationArg, 1, ierror);
1855  std::cout << "oldNormalization = " << MuScleFitUtils::oldNormalization_ << " new = " << normalizationArg[0] << std::endl;
1856  MuScleFitUtils::oldNormalization_ = normalizationArg[0];
1858  }
1859  fval = -2.*flike/double(evtsinlik);
1860  // fval = -2.*flike;
1861  // if( lowStatPenalty ) {
1862  // fval *= 100;
1863  // }
1864  }
1865  else {
1866  fval = -2.*flike;
1867  }
1868  }
1869  else {
1870  std::cout << "Problem: Events in likelihood = " << evtsinlik << std::endl;
1871  fval = 999999999.;
1872  }
1873  // fval = -2.*flike;
1874  if (MuScleFitUtils::debug>19)
1875  std::cout << "[MuScleFitUtils-likelihood]: End tree loop with likelihood value = " << fval << std::endl;
1876 
1877 // #ifdef DEBUG
1878 
1879 // if( MuScleFitUtils::minuitLoop_ < 10000 ) {
1883  }
1884  // }
1885  // else std::cout << "minuitLoop over 10000. Not filling histogram" << std::endl;
1886 
1887  std::cout<<"MINUIT loop number "<<MuScleFitUtils::minuitLoop_<<", likelihood = "<<fval<<std::endl;
1888 
1889  if( MuScleFitUtils::debug > 0 ) {
1890  // if( MuScleFitUtils::duringMinos_ ) {
1891  // int parnumber = (int)(MuScleFitUtils::parResol.size()+MuScleFitUtils::parScale.size()+
1892  // MuScleFitUtils::parCrossSection.size()+MuScleFitUtils::parBgr.size());
1893  // std::cout << "[MuScleFitUtils-likelihood]: Looping on tree with ";
1894  // for (int ipar=0; ipar<parnumber; ipar++) {
1895  // std::cout << "Parameter #" << ipar << " with value " << xval[ipar] << " ";
1896  // }
1897  // std::cout << std::endl;
1898  // std::cout << "[MuScleFitUtils-likelihood]: likelihood value = " << fval << std::endl;
1899  // }
1900  std::cout << "Events in likelihood = " << evtsinlik << std::endl;
1901  std::cout << "Events out likelihood = " << evtsoutlik << std::endl;
1902  }
1903 
1904 // #endif
1905 }
1906 
1907 // Mass fitting routine
1908 // --------------------
1909 std::vector<TGraphErrors*> MuScleFitUtils::fitMass (TH2F* histo) {
1910 
1911  if (MuScleFitUtils::debug>0) std::cout << "Fitting " << histo->GetName() << std::endl;
1912 
1913  std::vector<TGraphErrors *> results;
1914 
1915  // Results of the fit
1916  // ------------------
1917  std::vector<double> Ftop;
1918  std::vector<double> Fwidth;
1919  std::vector<double> Fmass;
1920  std::vector<double> Etop;
1921  std::vector<double> Ewidth;
1922  std::vector<double> Emass;
1923  std::vector<double> Fchi2;
1924  // X bin center and width
1925  // ----------------------
1926  std::vector<double> Xcenter;
1927  std::vector<double> Ex;
1928 
1929  // Fit with lorentzian peak
1930  // ------------------------
1931  TF1 *fitFcn = new TF1 ("fitFcn", lorentzianPeak, 70, 110, 3);
1932  fitFcn->SetParameters (100, 3, 91);
1933  fitFcn->SetParNames ("Ftop", "Fwidth", "Fmass");
1934  fitFcn->SetLineWidth (2);
1935 
1936  // Fit slices projected along Y from bins in X
1937  // -------------------------------------------
1938  double cont_min = 20; // Minimum number of entries
1939  Int_t binx = histo->GetXaxis()->GetNbins();
1940  // TFile *f= new TFile("prova.root", "recreate");
1941  // histo->Write();
1942  for (int i=1; i<=binx; i++) {
1943  TH1 * histoY = histo->ProjectionY ("", i, i);
1944  // histoY->Write();
1945  double cont = histoY->GetEntries();
1946  if (cont>cont_min) {
1947  histoY->Fit ("fitFcn", "0", "", 70, 110);
1948  double *par = fitFcn->GetParameters();
1949  const double *err = fitFcn->GetParErrors();
1950 
1951  Ftop.push_back(par[0]);
1952  Fwidth.push_back(par[1]);
1953  Fmass.push_back(par[2]);
1954  Etop.push_back(err[0]);
1955  Ewidth.push_back(err[1]);
1956  Emass.push_back(err[2]);
1957 
1958  double chi2 = fitFcn->GetChisquare();
1959  Fchi2.push_back(chi2);
1960 
1961  double xx = histo->GetXaxis()->GetBinCenter(i);
1962  Xcenter.push_back(xx);
1963  double ex = 0; // FIXME: you can use the bin width
1964  Ex.push_back(ex);
1965  }
1966  }
1967  // f->Close();
1968 
1969  // Put the fit results in arrays for TGraphErrors
1970  // ----------------------------------------------
1971  const int nn = Fmass.size();
1972  double *x = new double[nn];
1973  double *ym = new double[nn];
1974  double *e = new double[nn];
1975  double *eym = new double[nn];
1976  double *yw = new double[nn];
1977  double *eyw = new double[nn];
1978  double *yc = new double[nn];
1979 
1980  for (int j=0; j<nn; j++) {
1981  x[j] = Xcenter[j];
1982  ym[j] = Fmass[j];
1983  eym[j] = Emass[j];
1984  yw[j] = Fwidth[j];
1985  eyw[j] = Ewidth[j];
1986  yc[j] = Fchi2[j];
1987  e[j] = Ex[j];
1988  }
1989 
1990  // Create TGraphErrors
1991  // -------------------
1992  TString name = histo->GetName();
1993  TGraphErrors *grM = new TGraphErrors (nn, x, ym, e, eym);
1994  grM->SetTitle (name+"_M");
1995  grM->SetName (name+"_M");
1996  TGraphErrors *grW = new TGraphErrors (nn, x, yw, e, eyw);
1997  grW->SetTitle (name+"_W");
1998  grW->SetName (name+"_W");
1999  TGraphErrors *grC = new TGraphErrors (nn, x, yc, e, e);
2000  grC->SetTitle (name+"_chi2");
2001  grC->SetName (name+"_chi2");
2002 
2003  // Cleanup
2004  // -------
2005  delete[] x;
2006  delete[] ym;
2007  delete[] eym;
2008  delete[] yw;
2009  delete[] eyw;
2010  delete[] yc;
2011  delete[] e;
2012  delete fitFcn;
2013 
2014  results.push_back(grM);
2015  results.push_back(grW);
2016  results.push_back(grC);
2017  return results;
2018 }
2019 
2020 // Resolution fitting routine
2021 // --------------------------
2022 std::vector<TGraphErrors*> MuScleFitUtils::fitReso (TH2F* histo) {
2023  std::cout << "Fitting " << histo->GetName() << std::endl;
2024  std::vector<TGraphErrors *> results;
2025 
2026  // Results from fit
2027  // ----------------
2028  std::vector<double> maxs;
2029  std::vector<double> means;
2030  std::vector<double> sigmas;
2031  std::vector<double> chi2s;
2032  std::vector<double> Emaxs;
2033  std::vector<double> Emeans;
2034  std::vector<double> Esigmas;
2035 
2036  // X bin center and width
2037  // ----------------------
2038  std::vector<double> Xcenter;
2039  std::vector<double> Ex;
2040 
2041  // Fit with a gaussian
2042  // -------------------
2043  TF1 *fitFcn = new TF1 ("fitFunc", Gaussian, -0.2, 0.2, 3);
2044  fitFcn->SetParameters (100, 0, 0.02);
2045  fitFcn->SetParNames ("max", "mean", "sigma");
2046  fitFcn->SetLineWidth (2);
2047 
2048  // Fit slices projected along Y from bins in X
2049  // -------------------------------------------
2050  double cont_min = 20; // Minimum number of entries
2051  Int_t binx = histo->GetXaxis()->GetNbins();
2052  for (int i=1; i<=binx; i++) {
2053  TH1 * histoY = histo->ProjectionY ("", i, i);
2054  double cont = histoY->GetEntries();
2055  if (cont>cont_min) {
2056  histoY->Fit ("fitFunc", "0", "", -0.2, 0.2);
2057  double *par = fitFcn->GetParameters();
2058  const double *err = fitFcn->GetParErrors();
2059 
2060  maxs.push_back (par[0]);
2061  means.push_back (par[1]);
2062  sigmas.push_back (par[2]);
2063  Emaxs.push_back (err[0]);
2064  Emeans.push_back (err[1]);
2065  Esigmas.push_back (err[2]);
2066 
2067  double chi2 = fitFcn->GetChisquare();
2068  chi2s.push_back (chi2);
2069 
2070  double xx = histo->GetXaxis()->GetBinCenter(i);
2071  Xcenter.push_back (xx);
2072  double ex = 0; // FIXME: you can use the bin width
2073  Ex.push_back (ex);
2074  }
2075  }
2076 
2077  // Put the fit results in arrays for TGraphErrors
2078  // ----------------------------------------------
2079  const int nn = means.size();
2080  double *x = new double[nn];
2081  double *ym = new double[nn];
2082  double *e = new double[nn];
2083  double *eym = new double[nn];
2084  double *yw = new double[nn];
2085  double *eyw = new double[nn];
2086  double *yc = new double[nn];
2087 
2088  for (int j=0; j<nn; j++) {
2089  x[j] = Xcenter[j];
2090  ym[j] = means[j];
2091  eym[j] = Emeans[j];
2092  // yw[j] = maxs[j];
2093  // eyw[j] = Emaxs[j];
2094  yw[j] = sigmas[j];
2095  eyw[j] = Esigmas[j];
2096  yc[j] = chi2s[j];
2097  e[j] = Ex[j];
2098  }
2099 
2100  // Create TGraphErrors
2101  // -------------------
2102  TString name = histo->GetName();
2103  TGraphErrors *grM = new TGraphErrors (nn, x, ym, e, eym);
2104  grM->SetTitle (name+"_mean");
2105  grM->SetName (name+"_mean");
2106  TGraphErrors *grW = new TGraphErrors (nn, x, yw, e, eyw);
2107  grW->SetTitle (name+"_sigma");
2108  grW->SetName (name+"_sigma");
2109  TGraphErrors *grC = new TGraphErrors (nn, x, yc, e, e);
2110  grC->SetTitle (name+"_chi2");
2111  grC->SetName (name+"_chi2");
2112 
2113  // Cleanup
2114  // -------
2115  delete[] x;
2116  delete[] ym;
2117  delete[] eym;
2118  delete[] yw;
2119  delete[] eyw;
2120  delete[] yc;
2121  delete[] e;
2122  delete fitFcn;
2123 
2124  results.push_back (grM);
2125  results.push_back (grW);
2126  results.push_back (grC);
2127  return results;
2128 }
2129 
2130 // Mass probability for likelihood computation - no-background version (not used anymore)
2131 // --------------------------------------------------------------------------------------
2132 double MuScleFitUtils::massProb( const double & mass, const double & rapidity, const int ires, const double & massResol )
2133 {
2134  // This routine computes the likelihood that a given measured mass "measMass" is
2135  // the result of resonance #ires if the resolution expected for the two muons is massResol
2136  // ---------------------------------------------------------------------------------------
2137 
2138  double P = 0.;
2139 
2140  // Return Lorentz value for zero resolution cases (like MC)
2141  // --------------------------------------------------------
2142  if (massResol==0.) {
2143  if (debug>9) std::cout << "Mass, gamma , mref, width, P: " << mass
2144  << " " << ResGamma[ires] << " " << ResMass[ires]<< " " << massResol
2145  << " : used Lorentz P-value" << std::endl;
2146  return (0.5*ResGamma[ires]/TMath::Pi())/((mass-ResMass[ires])*(mass-ResMass[ires])+
2147  .25*ResGamma[ires]*ResGamma[ires]);
2148  }
2149 
2150  // NB defined as below, P is not a "probability" but a likelihood that we observe
2151  // a dimuon mass "mass", given mRef, gamma, and massResol. It is what we need for the
2152  // fit which finds the best resolution parameters, though. A definition which is
2153  // more properly a probability is given below (in massProb2()), where the result
2154  // cannot be used to fit resolution parameters because the fit would always prefer
2155  // to set the res parameters to the minimum possible value (best resolution),
2156  // to have a probability close to one of observing any mass.
2157  // -------------------------------------------------------------------------------
2158  // NNBB the following two lines have been replaced with the six following them,
2159  // which provide an improvement of a factor 9 in speed of execution at a
2160  // negligible price in precision.
2161  // ----------------------------------------------------------------------------
2162  // GL->SetParameters(gamma,mRef,mass,massResol);
2163  // P = GL->Integral(mass-5*massResol, mass+5*massResol);
2164 
2165  Int_t np = 100;
2166  double * x = new double[np];
2167  double * w = new double[np];
2168  GL->SetParameters (ResGamma[ires], ResMass[ires], mass, massResol);
2169  GL->CalcGaussLegendreSamplingPoints (np, x, w, 0.1e-15);
2170  P = GL->IntegralFast (np, x, w, ResMass[ires]-10*ResGamma[ires], ResMass[ires]+10*ResGamma[ires]);
2171  delete[] x;
2172  delete[] w;
2173 
2174  // If we are too far away we set P to epsilon and forget about this event
2175  // ----------------------------------------------------------------------
2176  if (P<1.0e-12) {
2177  P = 1.0e-12;
2178  if (debug>9) std::cout << "Mass, gamma , mref, width, P: " << mass
2179  << " " << ResGamma[ires] << " " << ResMass[ires] << " " << massResol
2180  << ": used epsilon" << std::endl;
2181  return P;
2182  }
2183 
2184  if (debug>9) std::cout << "Mass, gamma , mref, width, P: " << mass
2185  << " " << ResGamma[ires] << " " << ResMass[ires] << " " << massResol
2186  << " " << P << std::endl;
2187  return P;
2188 }
2189 
2190 std::pair<lorentzVector, lorentzVector> MuScleFitUtils::findSimMuFromRes( const edm::Handle<edm::HepMCProduct> & evtMC,
2191  const edm::Handle<edm::SimTrackContainer> & simTracks )
2192 {
2193  //Loop on simulated tracks
2194  std::pair<lorentzVector, lorentzVector> simMuFromRes;
2195  for( edm::SimTrackContainer::const_iterator simTrack=simTracks->begin(); simTrack!=simTracks->end(); ++simTrack ) {
2196  //Chose muons
2197  if (fabs((*simTrack).type())==13) {
2198  //If tracks from IP than find mother
2199  if ((*simTrack).genpartIndex()>0) {
2200  HepMC::GenParticle* gp = evtMC->GetEvent()->barcode_to_particle ((*simTrack).genpartIndex());
2201  if( gp != 0 ) {
2202 
2203  for (HepMC::GenVertex::particle_iterator mother = gp->production_vertex()->particles_begin(HepMC::ancestors);
2204  mother!=gp->production_vertex()->particles_end(HepMC::ancestors); ++mother) {
2205 
2206  bool fromRes = false;
2207  unsigned int motherPdgId = (*mother)->pdg_id();
2208  for( int ires = 0; ires < 6; ++ires ) {
2209  if( motherPdgId == motherPdgIdArray[ires] && resfind[ires] ) fromRes = true;
2210  }
2211  if( fromRes ) {
2212  if(gp->pdg_id() == 13)
2213  simMuFromRes.first = lorentzVector(simTrack->momentum().px(),simTrack->momentum().py(),
2214  simTrack->momentum().pz(),simTrack->momentum().e());
2215  else
2216  simMuFromRes.second = lorentzVector(simTrack->momentum().px(),simTrack->momentum().py(),
2217  simTrack->momentum().pz(),simTrack->momentum().e());
2218  }
2219  }
2220  }
2221  // else LogDebug("MuScleFitUtils") << "WARNING: no matching genParticle found for simTrack" << std::endl;
2222  }
2223  }
2224  }
2225  return simMuFromRes;
2226 }
2227 
2228 std::pair<lorentzVector, lorentzVector> MuScleFitUtils::findGenMuFromRes( const edm::HepMCProduct* evtMC )
2229 {
2230  const HepMC::GenEvent* Evt = evtMC->GetEvent();
2231  std::pair<lorentzVector,lorentzVector> muFromRes;
2232  //Loop on generated particles
2233  for (HepMC::GenEvent::particle_const_iterator part=Evt->particles_begin();
2234  part!=Evt->particles_end(); part++) {
2235  if (fabs((*part)->pdg_id())==13 && (*part)->status()==1) {
2236  bool fromRes = false;
2237  for (HepMC::GenVertex::particle_iterator mother = (*part)->production_vertex()->particles_begin(HepMC::ancestors);
2238  mother != (*part)->production_vertex()->particles_end(HepMC::ancestors); ++mother) {
2239  unsigned int motherPdgId = (*mother)->pdg_id();
2240 
2241  // For sherpa the resonance is not saved. The muons from the resonance can be identified
2242  // by having as mother a muon of status 3.
2243  if( sherpa_ ) {
2244  if( motherPdgId == 13 && (*mother)->status() == 3 ) fromRes = true;
2245  }
2246  else {
2247  for( int ires = 0; ires < 6; ++ires ) {
2248  if( motherPdgId == motherPdgIdArray[ires] && resfind[ires] ) fromRes = true;
2249  }
2250  }
2251  }
2252  if(fromRes){
2253  if((*part)->pdg_id()==13)
2254  // muFromRes.first = (*part)->momentum();
2255  muFromRes.first = (lorentzVector((*part)->momentum().px(),(*part)->momentum().py(),
2256  (*part)->momentum().pz(),(*part)->momentum().e()));
2257  else
2258  muFromRes.second = (lorentzVector((*part)->momentum().px(),(*part)->momentum().py(),
2259  (*part)->momentum().pz(),(*part)->momentum().e()));
2260  }
2261  }
2262  }
2263  return muFromRes;
2264 }
2265 
2266 std::pair<lorentzVector, lorentzVector> MuScleFitUtils::findGenMuFromRes( const reco::GenParticleCollection* genParticles)
2267 {
2268  std::pair<lorentzVector,lorentzVector> muFromRes;
2269 
2270  //Loop on generated particles
2271  if( debug>0 ) std::cout << "Starting loop on " << genParticles->size() << " genParticles" << std::endl;
2272  for( reco::GenParticleCollection::const_iterator part=genParticles->begin(); part!=genParticles->end(); ++part ) {
2273  if (fabs(part->pdgId())==13 && part->status()==1) {
2274  bool fromRes = false;
2275  unsigned int motherPdgId = part->mother()->pdgId();
2276  if( debug>0 ) {
2277  std::cout << "Found a muon with mother: " << motherPdgId << std::endl;
2278  }
2279  for( int ires = 0; ires < 6; ++ires ) {
2280  if( motherPdgId == motherPdgIdArray[ires] && resfind[ires] ) fromRes = true;
2281  }
2282  if(fromRes){
2283  if(part->pdgId()==13) {
2284  muFromRes.first = part->p4();
2285  if( debug>0 ) std::cout << "Found a genMuon + : " << muFromRes.first << std::endl;
2286  // muFromRes.first = (lorentzVector(part->p4().px(),part->p4().py(),
2287  // part->p4().pz(),part->p4().e()));
2288  }
2289  else {
2290  muFromRes.second = part->p4();
2291  if( debug>0 ) std::cout << "Found a genMuon - : " << muFromRes.second << std::endl;
2292  // muFromRes.second = (lorentzVector(part->p4().px(),part->p4().py(),
2293  // part->p4().pz(),part->p4().e()));
2294  }
2295  }
2296  }
2297  }
2298  return muFromRes;
2299 }
#define LogDebug(id)
static std::vector< std::pair< lorentzVector, lorentzVector > > simPair
const double Pi
static std::vector< int > doScaleFit
TF2 * GL2
std::vector< GenParticle > GenParticleCollection
collection of GenParticles
static std::vector< int > doResolFit
static std::pair< lorentzVector, lorentzVector > findGenMuFromRes(const reco::GenParticleCollection *genParticles)
double sigmaPt(const U &track, const int i=0) const
The second, optional, parameter is the iteration number.
static double GLValue[6][1001][1001]
int i
Definition: DBlmapReader.cc:9
static std::vector< double > parBias
static std::vector< int > parCrossSectionOrder
static smearFunctionBase * smearFunction
static std::vector< int > parScaleOrder
static std::vector< int > doCrossSectionFit
static void minimizeLikelihood()
static double maxMuonEtaSecondRange_
Double_t Gaussian(Double_t *x, Double_t *par)
int regionsParNum()
Returns the total number of parameters used for the regions.
static std::vector< int > parBgrOrder
static std::vector< int > parfix
static double deltaPhiMaxCut_
static unsigned int loopCounter
double sigmaCotgTh(const U &track, const int i=0) const
The second, optional, parameter is the iteration number.
tuple cont
load Luminosity info ##
Definition: generateEDF.py:622
const double w
Definition: UKUtility.cc:23
static std::vector< double > parResolMax
static std::pair< lorentzVector, lorentzVector > findSimMuFromRes(const edm::Handle< edm::HepMCProduct > &evtMC, const edm::Handle< edm::SimTrackContainer > &simTracks)
static std::vector< std::pair< MuScleFitMuon, MuScleFitMuon > > SavedPairMuScleFitMuons
static int nbins
void likelihood(int &npar, double *grad, double &fval, double *xval, int flag)
static std::vector< std::pair< MuScleFitMuon, MuScleFitMuon > > genMuscleFitPair
const float chg[109]
Definition: CoreSimTrack.cc:5
static bool startWithSimplex_
static std::vector< int > doBackgroundFit
static std::vector< double > parResol
static bool debugMassResol_
void setParameters(double *Start, double *Step, double *Mini, double *Maxi, int *ind, TString *parname, const std::vector< double > &parCrossSection, const std::vector< int > &parCrossSectionOrder, const std::vector< int > &resfind)
Initializes the arrays needed by Minuit.
int ires[2]
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
static double ResMinMass[6]
static TH1D * backgroundProb_
virtual void smear(double &pt, double &eta, double &phi, const double *y, const std::vector< double > &parSmear)=0
static BackgroundHandler * backgroundHandler
static double x[7][10000]
std::pair< double, double > backgroundFunction(const bool doBackgroundFit, const double *parval, const int resTotNum, const int ires, const bool *resConsidered, const double *ResMass, const double ResHalfWidth[], const int MuonType, const double &mass, const double &eta1, const double &eta2)
static int debug
static std::vector< TGraphErrors * > fitMass(TH2F *histo)
static double ResMass[6]
static double massWindowHalfWidth[3][6]
TF1 * GL
static bool speedup
static bool scaleFitNotDone_
static unsigned int normalizationChanged_
#define P
static bool ResFound
static scaleFunctionBase< std::vector< double > > * biasFunction
double isum
static bool checkMassWindow(const double &mass, const double &leftBorder, const double &rightBorder)
Method to check if the mass value is within the mass window of the i-th resonance.
static std::vector< int > parBgrFix
static std::vector< double > parResolMin
static bool minimumShapePlots_
static int MuonTypeForCheckMassWindow
static double minMuonEtaFirstRange_
static double massProb(const double &mass, const double &rapidity, const int ires, const double &massResol)
static struct MuScleFitUtils::massResolComponentsStruct massResolComponents
static int BiasType
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
Definition: Activities.doc:4
static std::vector< int > parScaleFix
static bool computeMinosErrors_
reco::Particle::LorentzVector lorentzVector
Definition: GenMuonPair.h:9
static scaleFunctionBase< std::vector< double > > * scaleFunctionForVec
def canvas
Definition: svgfig.py:481
static std::pair< SimTrack, SimTrack > findBestSimuRes(const std::vector< SimTrack > &simMuons)
static std::vector< std::vector< double > > parvalue
virtual double sigmaPt(const double &pt, const double &eta, const T &parval)=0
static double maxMuonPt_
T x() const
Cartesian x coordinate.
static std::pair< MuScleFitMuon, MuScleFitMuon > findBestRecoRes(const std::vector< MuScleFitMuon > &muons)
static int ScaleFitType
static std::vector< std::pair< lorentzVector, lorentzVector > > genPair
static std::vector< std::pair< lorentzVector, lorentzVector > > ReducedSavedPair
static const int totalResNum
static const double muMass
static double massResolution(const lorentzVector &mu1, const lorentzVector &mu2)
int np
Definition: AMPTWrapper.h:33
static const unsigned int motherPdgIdArray[6]
static int minuitLoop_
virtual int parNum() const
Definition: Functions.h:704
static std::vector< double > parScaleMin
static lorentzVector applyBias(const lorentzVector &muon, const int charge)
void rescale(std::vector< double > &parBgr, const double *ResMass, const double *massWindowHalfWidth, const std::vector< std::pair< reco::Particle::LorentzVector, reco::Particle::LorentzVector > > &muonPairs, const double &weight=1.)
T sqrt(T t)
Definition: SSEVec.h:18
static double GLZNorm[40][1001]
static std::vector< double > parBgr
static int SmearType
virtual void setParameters(double *Start, double *Step, double *Mini, double *Maxi, int *ind, TString *parname, const T &parScale, const std::vector< int > &parScaleOrder, const int muonType)=0
This method is used to differentiate parameters among the different functions.
static lorentzVector fromPtEtaPhiToPxPyPz(const double *ptEtaPhiE)
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
tuple results
Definition: mps_update.py:44
virtual double covPt1Pt2(const double &pt1, const double &eta1, const double &pt2, const double &eta2, const T &parval)
Definition: Functions.h:685
int j
Definition: DBlmapReader.cc:9
bool releaseParameters(TMinuit &rmin, const std::vector< int > &resfind, const std::vector< int > &parfix, const int *ind, const int iorder, const unsigned int shift)
Use the information in resfind, parorder and parfix to release the N-1 variables. ...
static double ResMaxSigma[6]
double f[11][100]
static double computeWeight(const double &mass, const int iev, const bool doUseBkgrWindow=false)
static std::vector< double > parScaleStep
static std::vector< std::pair< lorentzVector, lorentzVector > > SavedPair
static double invDimuonMass(const lorentzVector &mu1, const lorentzVector &mu2)
static lorentzVector applyScale(const lorentzVector &muon, const std::vector< double > &parval, const int charge)
static TH1D * signalProb_
static std::vector< int > parResolFix
static double GLZValue[40][1001][1001]
static TMinuit * rminPtr_
static std::vector< double > parSmear
virtual double scale(const double &pt, const double &eta, const double &phi, const int chg, const T &parScale) const =0
static std::vector< int > parResolOrder
double resMass(const bool doBackgroundFit, const int ires)
static bool sherpa_
static int BgrFitType
static TH1D * likelihoodInLoop_
T Max(T a, T b)
Definition: MathUtil.h:44
static std::vector< double > parScaleMax
Definition: adjgraph.h:12
double sigmaPhi(const U &track, const int i=0) const
The second, optional, parameter is the iteration number.
static std::vector< double > parScale
static double oldNormalization_
virtual double sigmaCotgTh(const double &pt, const double &eta, const T &parval)=0
std::vector< double > relativeCrossSections(const double *variables, const std::vector< int > &resfind)
Perform a variable transformation from N-1 to relative cross sections.
const HepMC::GenEvent * GetEvent() const
Definition: HepMCProduct.h:35
void setParameters(double *Start, double *Step, double *Mini, double *Maxi, int *ind, TString *parname, const std::vector< double > &parBgr, const std::vector< int > &parBgrOrder, const int muonType)
Sets initial parameters for all the functions.
static bool duringMinos_
part
Definition: HCALResponse.h:20
static double ResGamma[6]
static double deltaPhiMinCut_
Double_t lorentzianPeak(Double_t *x, Double_t *par)
int iorder
static bool rapidityBinsForZ_
double mzsum
static int ResolFitType
static int goodmuon
static bool separateRanges_
static double minMuonEtaSecondRange_
static int iev_
static std::vector< double > parCrossSection
static const double mMu2
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
static double GLNorm[6][1001]
static std::vector< TGraphErrors * > fitReso(TH2F *histo)
tuple muons
Definition: patZpeak.py:38
static lorentzVector applySmearing(const lorentzVector &muon)
std::pair< double, double > windowBorders(const bool doBackgroundFit, const int ires)
Returns the appropriate window borders depending on whether the background is being fitted and on the...
static bool normalizeLikelihoodByEventNumber_
bool unlockParameter(const std::vector< int > &resfind, const unsigned int ipar)
returns true if the parameter is to be unlocked
static unsigned int const shift
virtual void setParameters(double *Start, double *Step, double *Mini, double *Maxi, int *ind, TString *parname, const T &parResol, const std::vector< int > &parResolOrder, const int muonType)
This method is used to differentiate parameters among the different functions.
Definition: Functions.h:692
static int MuonType
tuple cout
Definition: gather_cfg.py:145
static double probability(const double &mass, const double &massResol, const double GLvalue[][1001][1001], const double GLnorm[][1001], const int iRes, const int iY)
Computes the probability given the mass, mass resolution and the arrays with the probabilities and th...
static double minMuonPt_
virtual double sigmaPhi(const double &pt, const double &eta, const T &parval)=0
static scaleFunctionBase< double * > * scaleFunction
static bool useProbsFile_
int weight
Definition: histoStyle.py:50
static std::vector< int > resfind
virtual void resetParameters(std::vector< double > *scaleVec) const
This method is used to reset the scale parameters to neutral values (useful for iterations &gt; 0) ...
Definition: Functions.h:49
static double ResHalfWidth[6]
static int counter_resprob
static resolutionFunctionBase< std::vector< double > > * resolutionFunctionForVec
static std::vector< int > parorder
virtual int parNum() const
Definition: Functions.h:66
static int FitStrategy
static double maxMuonEtaFirstRange_
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
static CrossSectionHandler * crossSectionHandler
static std::vector< double > parResolStep
static std::vector< int > parCrossSectionFix
static resolutionFunctionBase< double * > * resolutionFunction