CMS 3D CMS Logo

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 
109 TH1D* MuScleFitUtils::likelihoodInLoop_ = nullptr;
110 TH1D* MuScleFitUtils::signalProb_ = nullptr;
111 TH1D* MuScleFitUtils::backgroundProb_ = nullptr;
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_ = nullptr;
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 = std::abs(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 && std::abs(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  // && std::abs(rapidity)<2.4
984  ) {
985 
986  int iY = (int)(std::abs(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 
1063  if( MuScleFitUtils::signalProb_ != nullptr && MuScleFitUtils::backgroundProb_ != nullptr ) {
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_ = nullptr;
1524  signalProb_ = nullptr;
1525  backgroundProb_ = nullptr;
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)>(std::abs(errl)))?(errh):(std::abs(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_ == nullptr ) {
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 ) {
1880  if( MuScleFitUtils::likelihoodInLoop_ != nullptr ) {
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,
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 (std::abs((*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 != nullptr ) {
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 (std::abs((*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 (std::abs(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]
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.
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
virtual double scale(const double &pt, const double &eta, const double &phi, const int chg, const T &parScale) const =0
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_
Definition: weight.py:1
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
static std::vector< int > parScaleFix
static bool computeMinosErrors_
reco::Particle::LorentzVector lorentzVector
Definition: GenMuonPair.h:9
static scaleFunctionBase< std::vector< double > > * scaleFunctionForVec
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_
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
simTrack
per collection params
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
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
virtual double covPt1Pt2(const double &pt1, const double &eta1, const double &pt2, const double &eta2, const T &parval)
Definition: Functions.h:685
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. ...
double g[11][100]
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
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
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:38
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
std::pair< OmniClusterRef, TrackingParticleRef > P
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)
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
def canvas(sub, attr)
Definition: svgfig.py:481
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
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_
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 > 0) ...
Definition: Functions.h:49
static double ResHalfWidth[6]
def check(config)
Definition: trackerTree.py:14
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