CMS 3D CMS Logo

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