CMS 3D CMS Logo

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