CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
VerticalInterpHistPdf.cc
Go to the documentation of this file.
1 #include "../interface/VerticalInterpHistPdf.h"
2 
3 #include <cassert>
4 #include <memory>
5 
6 #include "RooFit.h"
7 #include "Riostream.h"
8 
9 #include "TIterator.h"
10 #include "RooRealVar.h"
11 #include "RooMsgService.h"
12 
13 //#define TRACE_CALLS
14 #ifdef TRACE_CALLS
15 #include "../interface/ProfilingTools.h"
16 #define TRACEME() PerfCounter::add( __PRETTY_FUNCTION__ );
17 #else
18 #define TRACEME()
19 #endif
20 
21 ClassImp(VerticalInterpHistPdf)
22 
23 
24 //_____________________________________________________________________________
26  _cacheTotal(0),
27  _cacheSingle(0),
28  _cacheSingleGood(0)
29 {
30  // Default constructor
31  _funcIter = _funcList.createIterator() ;
32  _coefIter = _coefList.createIterator() ;
33 }
34 
35 
36 //_____________________________________________________________________________
37 VerticalInterpHistPdf::VerticalInterpHistPdf(const char *name, const char *title, const RooRealVar &x, const RooArgList& inFuncList, const RooArgList& inCoefList, Double_t smoothRegion, Int_t smoothAlgo) :
38  RooAbsPdf(name,title),
39  _x("x","Independent variable",this,const_cast<RooRealVar&>(x)),
40  _funcList("funcList","List of pdfs",this),
41  _coefList("coefList","List of coefficients",this), // we should get shapeDirty when coefficients change
42  _smoothRegion(smoothRegion),
43  _smoothAlgo(smoothAlgo),
44  _cacheTotal(0),
45  _cacheSingle(0),
46  _cacheSingleGood(0)
47 {
48 
49  if (inFuncList.getSize()!=2*inCoefList.getSize()+1) {
50  coutE(InputArguments) << "VerticalInterpHistPdf::VerticalInterpHistPdf(" << GetName()
51  << ") number of pdfs and coefficients inconsistent, must have Nfunc=1+2*Ncoef" << endl ;
52  assert(0);
53  }
54 
55  TIterator* funcIter = inFuncList.createIterator() ;
56  RooAbsArg* func;
57  while((func = (RooAbsArg*)funcIter->Next())) {
58  RooAbsPdf *pdf = dynamic_cast<RooAbsPdf*>(func);
59  if (!pdf) {
60  coutE(InputArguments) << "ERROR: VerticalInterpHistPdf::VerticalInterpHistPdf(" << GetName() << ") function " << func->GetName() << " is not of type RooAbsPdf" << endl;
61  assert(0);
62  }
63  RooArgSet *params = pdf->getParameters(RooArgSet(x));
64  if (params->getSize() > 0) {
65  coutE(InputArguments) << "ERROR: VerticalInterpHistPdf::VerticalInterpHistPdf(" << GetName() << ") pdf " << func->GetName() << " has some parameters." << endl;
66  assert(0);
67  }
68  delete params;
69  _funcList.add(*func) ;
70  }
71  delete funcIter;
72 
73  TIterator* coefIter = inCoefList.createIterator() ;
74  RooAbsArg* coef;
75  while((coef = (RooAbsArg*)coefIter->Next())) {
76  if (!dynamic_cast<RooAbsReal*>(coef)) {
77  coutE(InputArguments) << "ERROR: VerticalInterpHistPdf::VerticalInterpHistPdf(" << GetName() << ") coefficient " << coef->GetName() << " is not of type RooAbsReal" << endl;
78  assert(0);
79  }
80  _coefList.add(*coef) ;
81  }
82  delete coefIter;
83 
84  _funcIter = _funcList.createIterator() ;
85  _coefIter = _coefList.createIterator() ;
86 
87 }
88 
89 
90 
91 
92 //_____________________________________________________________________________
94  RooAbsPdf(other,name),
95  _x("x",this,other._x),
96  _funcList("funcList",this,other._funcList),
97  _coefList("coefList",this,other._coefList),
98  _smoothRegion(other._smoothRegion),
99  _smoothAlgo(other._smoothAlgo),
100  _cacheTotal(0),
101  _cacheSingle(0),
102  _cacheSingleGood(0)
103 {
104  // Copy constructor
105 
106  _funcIter = _funcList.createIterator() ;
107  _coefIter = _coefList.createIterator() ;
108 }
109 
110 
111 
112 //_____________________________________________________________________________
114 {
115  // Destructor
116  delete _funcIter ;
117  delete _coefIter ;
118  if (_cacheTotal) {
119  delete _cacheTotal;
120  for (int i = 0; i < _funcList.getSize(); ++i) delete _cacheSingle[i];
121  delete [] _cacheSingle;
122  delete [] _cacheSingleGood;
123  }
124 }
125 
126 //_____________________________________________________________________________
128 {
129  if (_cacheTotal == 0) setupCaches();
130 #if 0
131  printf("Evaluate called for x %f, cache status %d: ", _x.arg().getVal(), _sentry.good());
132  int ndim = _coefList.getSize();
133  for (int i = 0; i < ndim; ++i) {
134  RooAbsReal *rar = dynamic_cast<RooAbsReal *>(_coefList.at(i));
135  printf("%s = %+6.4f ", rar->GetName(), rar->getVal());
136  }
137  std::cout << std::endl;
138 #endif
139 
140  if (!_sentry.good()) syncTotal();
141  int nbin = _cacheTotal->GetNbinsX(), ibin = _cacheTotal->FindBin(_x);
142  if (ibin < 1) ibin = 1;
143  else if (ibin > nbin) ibin = nbin;
144  return _cacheTotal->GetBinContent(ibin);
145 }
146 
147 
149  RooAbsPdf *pdfi = dynamic_cast<RooAbsPdf *>(_funcList.at(i));
150  if (_cacheSingle[i] != 0) delete _cacheSingle[i];
151  _cacheSingle[i] = pdfi->createHistogram("",dynamic_cast<const RooRealVar &>(_x.arg()));
152  _cacheSingle[i]->SetDirectory(0);
153  if (_cacheSingle[i]->Integral("width")) { _cacheSingle[i]->Scale(1.0/_cacheSingle[i]->Integral("width")); }
154  if (i > 0) {
155  for (int b = 1, nb = _cacheSingle[i]->GetNbinsX(); b <= nb; ++b) {
156  double y = _cacheSingle[i]->GetBinContent(b);
157  double y0 = _cacheSingle[0]->GetBinContent(b);
158  if (_smoothAlgo < 0) {
159  if (y > 0 && y0 > 0) {
160  double logk = log(y/y0);
161  // odd numbers correspond to up variations, even numbers to down variations,
162  // and down variations need -log(kappa) instead of log(kappa)
163  _cacheSingle[i]->SetBinContent(b, logk);
164  } else {
165  _cacheSingle[i]->SetBinContent(b, 0);
166  }
167  } else {
168  _cacheSingle[i]->SetBinContent(b, y - y0);
169  }
170  }
171  }
172  _cacheSingleGood[i] = true;
173 }
174 
176  int ndim = _coefList.getSize();
177  for (int i = 0; i < 2*ndim+1; ++i) {
178  if (!_cacheSingleGood[i]) syncComponent(i);
179  }
180  for (int b = 1, nb = _cacheTotal->GetNbinsX(); b <= nb; ++b) {
181  double val = _cacheSingle[0]->GetBinContent(b);
182  _coefIter->Reset();
183  for (int i = 0; i < ndim; ++i) {
184  double dhi = _cacheSingle[2*i+1]->GetBinContent(b);
185  double dlo = _cacheSingle[2*i+2]->GetBinContent(b);
186  double x = (dynamic_cast<RooAbsReal *>(_coefIter->Next()))->getVal();
187  double alpha = x * 0.5 * ((dhi-dlo) + (dhi+dlo)*smoothStepFunc(x));
188  // alpha(0) = 0
189  // alpha(+1) = dhi
190  // alpha(-1) = dlo
191  // alpha(x >= +1) = |x|*dhi
192  // alpha(x <= -1) = |x|*dlo
193  // alpha is continuous and has continuous first and second derivative, as smoothStepFunc has them
194  if (_smoothAlgo < 0) {
195  val *= exp(alpha);
196  } else {
197  val += alpha;
198  }
199  }
200  if (val <= 0) val = 1e-9;
201  _cacheTotal->SetBinContent(b, val);
202  }
203  double norm = _cacheTotal->Integral("width");
204  if (norm > 0) _cacheTotal->Scale(1.0/norm);
205  _sentry.reset();
206 }
207 
208 void VerticalInterpHistPdf::setupCaches() const {
209  int ndim = _coefList.getSize();
210  _cacheTotal = (dynamic_cast<const RooRealVar &>(_x.arg())).createHistogram("total");
211  _cacheTotal->SetDirectory(0);
212  _cacheSingle = new TH1*[2*ndim+1]; assert(_cacheSingle);
213  _cacheSingleGood = new int[2*ndim+1]; assert(_cacheSingleGood);
214  for (int i = 0; i < 2*ndim+1; ++i) {
215  _cacheSingle[i] = 0;
216  _cacheSingleGood[i] = 0;
217  syncComponent(i);
218  }
220  syncTotal();
221 }
222 
223 //=============================================================================================
227 
228 
229 //_____________________________________________________________________________
231 {
232  // Default constructor
233  _funcIter = _funcList.createIterator() ;
234  _coefIter = _coefList.createIterator() ;
235 }
236 
237 
238 //_____________________________________________________________________________
239 FastVerticalInterpHistPdfBase::FastVerticalInterpHistPdfBase(const char *name, const char *title, const RooArgSet &obs, const RooArgList& inFuncList, const RooArgList& inCoefList, Double_t smoothRegion, Int_t smoothAlgo) :
240  RooAbsPdf(name,title),
241  _funcList("funcList","List of pdfs",this),
242  _coefList("coefList","List of coefficients",this), // we should get shapeDirty when coefficients change
243  _smoothRegion(smoothRegion),
244  _smoothAlgo(smoothAlgo),
245  _init(false),
246  _morphs(), _morphParams()
247 {
248  TRACEME()
249 
250  if (inFuncList.getSize()!=2*inCoefList.getSize()+1) {
251  coutE(InputArguments) << "VerticalInterpHistPdf::VerticalInterpHistPdf(" << GetName()
252  << ") number of pdfs and coefficients inconsistent, must have Nfunc=1+2*Ncoef" << endl ;
253  assert(0);
254  }
255 
256  TIterator* funcIter = inFuncList.createIterator() ;
257  RooAbsArg* func;
258  while((func = (RooAbsArg*)funcIter->Next())) {
259  RooAbsPdf *pdf = dynamic_cast<RooAbsPdf*>(func);
260  if (!pdf) {
261  coutE(InputArguments) << "ERROR: VerticalInterpHistPdf::VerticalInterpHistPdf(" << GetName() << ") function " << func->GetName() << " is not of type RooAbsPdf" << endl;
262  assert(0);
263  }
264  RooArgSet *params = pdf->getParameters(obs);
265  if (params->getSize() > 0) {
266  coutE(InputArguments) << "ERROR: VerticalInterpHistPdf::VerticalInterpHistPdf(" << GetName() << ") pdf " << func->GetName() << " has some parameters." << endl;
267  assert(0);
268  }
269  delete params;
270  _funcList.add(*func) ;
271  }
272  delete funcIter;
273 
274  TIterator* coefIter = inCoefList.createIterator() ;
275  RooAbsArg* coef;
276  while((coef = (RooAbsArg*)coefIter->Next())) {
277  if (!dynamic_cast<RooAbsReal*>(coef)) {
278  coutE(InputArguments) << "ERROR: VerticalInterpHistPdf::VerticalInterpHistPdf(" << GetName() << ") coefficient " << coef->GetName() << " is not of type RooAbsReal" << endl;
279  assert(0);
280  }
281  _coefList.add(*coef) ;
282  }
283  delete coefIter;
284 
285  _funcIter = _funcList.createIterator() ;
286  _coefIter = _coefList.createIterator() ;
287 
288 }
289 
290 //_____________________________________________________________________________
292  RooAbsPdf(other,name),
293  _funcList("funcList",this,other._funcList),
294  _coefList("coefList",this,other._coefList),
295  _smoothRegion(other._smoothRegion),
296  _smoothAlgo(other._smoothAlgo),
297  _init(false),
299  _morphs(other._morphs), _morphParams(other._morphParams)
300 #else
301  _morphs(), _morphParams()
302 #endif
303 {
304  // Copy constructor
305  _funcIter = _funcList.createIterator() ;
306  _coefIter = _coefList.createIterator() ;
307 #ifdef FastVerticalInterpHistPdf_CopyConstructor
309  _sentry.setValueDirty();
310 #endif
311 }
312 
313 
314 //_____________________________________________________________________________
316 {
317  // Destructor
318  delete _funcIter ;
319  delete _coefIter ;
320 }
321 
322 
323 //_____________________________________________________________________________
325 {
326  TRACEME()
327  if (_cache.size() == 0) setupCaches();
328  if (!_sentry.good() || !_init) syncTotal();
329  //return std::max<double>(1e-9, _cache.GetAt(_x));
330  return _cache.GetAt(_x);
331 }
332 
333 //_____________________________________________________________________________
335 {
336  TRACEME()
337  if (_cache.size() == 0) setupCaches();
338 
339  if (!_sentry.good() || !_init) syncTotal();
340  //return std::max<double>(1e-9, _cache.GetAt(_x, _y));
341  return _cache.GetAt(_x, _y);
342 }
343 
344 
345 
347  TRACEME()
348  RooAbsPdf *pdf = dynamic_cast<RooAbsPdf *>(_funcList.at(0));
349  const RooRealVar &x = dynamic_cast<const RooRealVar &>(_x.arg());
350  std::auto_ptr<TH1> hist(pdf->createHistogram("",x));
351  hist->SetDirectory(0);
354  if (_smoothAlgo < 0) {
357  }
358 }
359 
361  TRACEME()
362  RooAbsPdf *pdf = dynamic_cast<RooAbsPdf *>(_funcList.at(0));
363  const RooRealVar &x = dynamic_cast<const RooRealVar &>(_x.arg());
364  const RooRealVar &y = dynamic_cast<const RooRealVar &>(_y.arg());
365  const RooCmdArg &cond = _conditional ? RooFit::ConditionalObservables(RooArgSet(x)) : RooCmdArg::none();
366  std::auto_ptr<TH1> hist(pdf->createHistogram("", x, RooFit::YVar(y), cond));
367  hist->SetDirectory(0);
368  _cacheNominal = FastHisto2D(dynamic_cast<TH2F&>(*hist), _conditional);
370  else _cacheNominal.Normalize();
371 
372  if (_smoothAlgo < 0) {
375  }
376 }
377 
378 
379 
381  if (_smoothAlgo < 0) {
382  hi.LogRatio(nominal); lo.LogRatio(nominal);
383  //printf("Log-ratios for dimension %d: \n", dim); hi.Dump(); lo.Dump();
384  } else {
385  hi.Subtract(nominal); lo.Subtract(nominal);
386  //printf("Differences for dimension %d: \n", dim); hi.Dump(); lo.Dump();
387  }
388  FastTemplate::SumDiff(hi, lo, out.sum, out.diff);
389  //printf("Sum and diff for dimension %d: \n", dim); out.sum.Dump(); out.diff.Dump();
390 }
391 
393  TRACEME()
394  RooAbsPdf *pdfHi = dynamic_cast<RooAbsPdf *>(_funcList.at(2*dim+1));
395  RooAbsPdf *pdfLo = dynamic_cast<RooAbsPdf *>(_funcList.at(2*dim+2));
396  const RooRealVar &x = dynamic_cast<const RooRealVar &>(_x.arg());
397  std::auto_ptr<TH1> histHi(pdfHi->createHistogram("",x)); histHi->SetDirectory(0);
398  std::auto_ptr<TH1> histLo(pdfLo->createHistogram("",x)); histLo->SetDirectory(0);
399 
400  FastHisto hi(*histHi), lo(*histLo);
401  //printf("Un-normalized templates for dimension %d: \n", dim); hi.Dump(); lo.Dump();
402  hi.Normalize(); lo.Normalize();
403  //printf("Normalized templates for dimension %d: \n", dim); hi.Dump(); lo.Dump();
404  syncMorph(_morphs[dim], _cacheNominal, lo, hi);
405 }
407  RooAbsPdf *pdfHi = dynamic_cast<RooAbsPdf *>(_funcList.at(2*dim+1));
408  RooAbsPdf *pdfLo = dynamic_cast<RooAbsPdf *>(_funcList.at(2*dim+2));
409  const RooRealVar &x = dynamic_cast<const RooRealVar &>(_x.arg());
410  const RooRealVar &y = dynamic_cast<const RooRealVar &>(_y.arg());
411  const RooCmdArg &cond = _conditional ? RooFit::ConditionalObservables(RooArgSet(x)) : RooCmdArg::none();
412  std::auto_ptr<TH1> histHi(pdfHi->createHistogram("", x, RooFit::YVar(y), cond)); histHi->SetDirectory(0);
413  std::auto_ptr<TH1> histLo(pdfLo->createHistogram("", x, RooFit::YVar(y), cond)); histLo->SetDirectory(0);
414 
415  FastHisto2D hi(dynamic_cast<TH2&>(*histHi), _conditional), lo(dynamic_cast<TH2&>(*histLo), _conditional);
416  //printf("Un-normalized templates for dimension %d: \n", dim); hi.Dump(); lo.Dump();
417  if (_conditional) {
418  hi.NormalizeXSlices(); lo.NormalizeXSlices();
419  } else {
420  hi.Normalize(); lo.Normalize();
421  }
422  //printf("Normalized templates for dimension %d: \n", dim); hi.Dump(); lo.Dump();
423  syncMorph(_morphs[dim], _cacheNominal, lo, hi);
424 }
425 
426 
427 void FastVerticalInterpHistPdfBase::syncTotal(FastTemplate &cache, const FastTemplate &cacheNominal, const FastTemplate &cacheNominalLog) const {
428  TRACEME()
429  /* === how the algorithm works, in theory ===
430  * let dhi = h_hi - h_nominal
431  * dlo = h_lo - h_nominal
432  * and x be the morphing parameter
433  * we define alpha = x * 0.5 * ((dhi-dlo) + (dhi+dlo)*smoothStepFunc(x));
434  * which satisfies:
435  * alpha(0) = 0
436  * alpha(+1) = dhi
437  * alpha(-1) = dlo
438  * alpha(x >= +1) = |x|*dhi
439  * alpha(x <= -1) = |x|*dlo
440  * alpha is continuous and has continuous first and second derivative, as smoothStepFunc has them
441  * === and in practice ===
442  * we already have computed the histogram for diff=(dhi-dlo) and sum=(dhi+dlo)
443  * so we just do template += (0.5 * x) * (diff + smoothStepFunc(x) * sum)
444  * ========================================== */
445 
446  // start from nominal
447  cache.CopyValues(_smoothAlgo < 0 ? cacheNominalLog : cacheNominal);
448  //printf("Cache initialized to nominal template: \n"); cacheNominal.Dump();
449 
450  // apply all morphs one by one
451  for (int i = 0, ndim = _coefList.getSize(); i < ndim; ++i) {
452  double x = _morphParams[i]->getVal();
453  double a = 0.5*x, b = smoothStepFunc(x);
454  cache.Meld(_morphs[i].diff, _morphs[i].sum, a, b);
455  //printf("Merged transformation for dimension %d, x = %+5.3f, step = %.3f: \n", i, x, b); cache.Dump();
456  }
457 
458  // if necessary go back to linear scale
459  if (_smoothAlgo < 0) {
460  cache.Exp();
461  //printf("Done exponential tranformation\n"); cache.Dump();
462  } else {
463  cache.CropUnderflows();
464  }
465 
466  // mark as done
467  _sentry.reset();
468  _init = true;
469 }
470 
473 
474  // normalize the result
475  _cache.Normalize();
476  //printf("Normalized result\n"); _cache.Dump();
477 }
478 
481  // normalize the result
483  else _cache.Normalize();
484  //printf("Normalized result\n"); _cache.Dump();
485 }
486 
487 
488 
490  TRACEME()
491  int ndim = _coefList.getSize();
492 
493  _morphs.resize(ndim);
494  _morphParams.resize(ndim);
495  syncNominal();
496  //printf("Nominal template has been set up: \n"); _cacheNominal.Dump();
497  _coefIter->Reset();
498  for (int i = 0; i < ndim; ++i) {
499  _morphParams[i] = dynamic_cast<RooAbsReal *>(_coefIter->Next());
500  _morphs[i].sum.Resize(_cacheNominal.size());
501  _morphs[i].diff.Resize(_cacheNominal.size());
502  syncComponents(i);
503  }
505 
507  syncTotal();
508 }
509 
511  TRACEME()
512  int ndim = _coefList.getSize();
513 
514  _morphs.resize(ndim);
515  _morphParams.resize(ndim);
516  syncNominal();
517  //printf("Nominal template has been set up: \n"); _cacheNominal.Dump();
518  _coefIter->Reset();
519  for (int i = 0; i < ndim; ++i) {
520  _morphParams[i] = dynamic_cast<RooAbsReal *>(_coefIter->Next());
521  _morphs[i].sum.Resize(_cacheNominal.size());
522  _morphs[i].diff.Resize(_cacheNominal.size());
523  syncComponents(i);
524  }
526 
528  syncTotal();
529 }
530 
531 
int i
Definition: DBlmapReader.cc:9
float alpha
Definition: AMPTWrapper.h:95
const unsigned int size() const
Definition: FastTemplate.h:42
void Subtract(const FastTemplate &reference)
*this = *this - reference
FastHisto _cache
Cache of the result.
void Normalize()
Definition: FastTemplate.h:92
FastHisto2D _cacheNominal
Cache of nominal pdf (additive morphing) and its bin-by-bin logarithm (multiplicative) ...
#define FastVerticalInterpHistPdf_CopyConstructor
#define TRACEME()
ClassDef(VerticalInterpHistPdf, 1) protected void syncTotal() const
not to be serialized
void setupCaches() const
not to be serialized
void CropUnderflows(T minimum=1e-9)
protect from underflows (*this = max(*this, minimum));
void syncTotal(FastTemplate &cache, const FastTemplate &cacheNominal, const FastTemplate &cacheNominalLog) const
const RooRealProxy & x() const
TIterator * _coefIter
Iterator over FUNC list.
int * _cacheSingleGood
not to be serialized
bool good() const
T GetAt(const T &x) const
Definition: FastTemplate.cc:68
void syncComponents(int dimension) const
void Log()
*this = log(*this)
bool _init
Iterator over coefficient list.
FastHisto _cacheNominal
Cache of nominal pdf (additive morphing) and its bin-by-bin logarithm (multiplicative) ...
Must be public, for serialization.
TIterator * _coefIter
Iterator over FUNC list.
void setupCaches() const
not to be serialized
double smoothStepFunc(double x) const
void syncComponent(int which) const
SimpleCacheSentry _sentry
Iterator over coefficient list.
T GetAt(const T &x, const T &y) const
void NormalizeXSlices()
For each X, normalize along Y.
tuple out
Definition: dbtoconf.py:99
void CopyValues(const FastTemplate &other)
Definition: FastTemplate.cc:22
std::vector< RooAbsReal * > _morphParams
not to be serialized
std::vector< Morph > _morphs
not to be serialized
void Exp()
*this = exp(*this)
void syncComponents(int dimension) const
void Normalize()
Definition: FastTemplate.h:127
void addVars(const RooAbsCollection &vars)
double b
Definition: hdecay.h:120
bool empty() const
double smoothStepFunc(double x) const
SimpleCacheSentry _sentry
not to be serialized
TH1 ** _cacheSingle
not to be serialized
FastHisto2D _cacheNominalLog
not to be serialized
double a
Definition: hdecay.h:121
static void SumDiff(const FastTemplate &h1, const FastTemplate &h2, FastTemplate &sum, FastTemplate &diff)
assigns sum and diff
tuple cout
Definition: gather_cfg.py:121
void LogRatio(const FastTemplate &reference)
*this = log(*this)/(reference)
x
Definition: VDTMath.h:216
void syncMorph(Morph &out, const FastTemplate &nominal, FastTemplate &lo, FastTemplate &hi) const
not to be serialized
FastHisto2D _cache
Cache of the result.
void Meld(const FastTemplate &diff, const FastTemplate &sum, T x, T y)
Does this += x * (diff + (sum)*y)
FastHisto _cacheNominalLog
not to be serialized