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