CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
VerticalInterpPdf.cc
Go to the documentation of this file.
1 #include "../interface/VerticalInterpPdf.h"
2 
3 #include "RooFit.h"
4 #include "Riostream.h"
5 
6 #include "TIterator.h"
7 #include "TList.h"
8 #include "RooRealProxy.h"
9 #include "RooPlot.h"
10 #include "RooRealVar.h"
11 #include "RooAddGenContext.h"
12 #include "RooRealConstant.h"
13 #include "RooRealIntegral.h"
14 #include "RooMsgService.h"
15 
16 
17 
18 ClassImp(VerticalInterpPdf)
19 
20 
21 //_____________________________________________________________________________
23 {
24  // Default constructor
25  // coverity[UNINIT_CTOR]
26  _funcIter = _funcList.createIterator() ;
27  _coefIter = _coefList.createIterator() ;
28  _quadraticRegion = 0;
29 }
30 
31 
32 //_____________________________________________________________________________
33 VerticalInterpPdf::VerticalInterpPdf(const char *name, const char *title, const RooArgList& inFuncList, const RooArgList& inCoefList, Double_t quadraticRegion, Int_t quadraticAlgo) :
34  RooAbsPdf(name,title),
35  _normIntMgr(this,10),
36  _funcList("!funcList","List of functions",this),
37  _coefList("!coefList","List of coefficients",this),
38  _quadraticRegion(quadraticRegion),
39  _quadraticAlgo(quadraticAlgo)
40 {
41 
42  if (inFuncList.getSize()!=2*inCoefList.getSize()+1) {
43  coutE(InputArguments) << "VerticalInterpPdf::VerticalInterpPdf(" << GetName()
44  << ") number of pdfs and coefficients inconsistent, must have Nfunc=1+2*Ncoef" << endl ;
45  assert(0);
46  }
47 
48  TIterator* funcIter = inFuncList.createIterator() ;
49  RooAbsArg* func;
50  while((func = (RooAbsArg*)funcIter->Next())) {
51  if (!dynamic_cast<RooAbsReal*>(func)) {
52  coutE(InputArguments) << "ERROR: VerticalInterpPdf::VerticalInterpPdf(" << GetName() << ") function " << func->GetName() << " is not of type RooAbsReal" << endl;
53  assert(0);
54  }
55  _funcList.add(*func) ;
56  }
57  delete funcIter;
58 
59  TIterator* coefIter = inCoefList.createIterator() ;
60  RooAbsArg* coef;
61  while((coef = (RooAbsArg*)coefIter->Next())) {
62  if (!dynamic_cast<RooAbsReal*>(coef)) {
63  coutE(InputArguments) << "ERROR: VerticalInterpPdf::VerticalInterpPdf(" << GetName() << ") coefficient " << coef->GetName() << " is not of type RooAbsReal" << endl;
64  assert(0);
65  }
66  _coefList.add(*coef) ;
67  }
68  delete coefIter;
69 
70  _funcIter = _funcList.createIterator() ;
71  _coefIter = _coefList.createIterator() ;
72 
73  if (_quadraticAlgo == -1) {
74  // multiplicative morphing: no way to do analytical integrals.
75  _forceNumInt = kTRUE;
76  } else if (_quadraticAlgo >= 100) {
77  _quadraticAlgo -= 100;
78  _forceNumInt = kTRUE;
79  }
80 }
81 
82 
83 
84 
85 //_____________________________________________________________________________
87  RooAbsPdf(other,name),
88  _normIntMgr(other._normIntMgr,this),
89  _funcList("!funcList",this,other._funcList),
90  _coefList("!coefList",this,other._coefList),
91  _quadraticRegion(other._quadraticRegion),
92  _quadraticAlgo(other._quadraticAlgo)
93 {
94  // Copy constructor
95 
96  _funcIter = _funcList.createIterator() ;
97  _coefIter = _coefList.createIterator() ;
98 }
99 
100 
101 
102 //_____________________________________________________________________________
104 {
105  // Destructor
106  delete _funcIter ;
107  delete _coefIter ;
108 }
109 
110 //_____________________________________________________________________________
112 {
113  // Calculate the current value
114  Double_t value(0) ;
115 
116  // Do running sum of coef/func pairs, calculate lastCoef.
117  _funcIter->Reset() ;
118  _coefIter->Reset() ;
119  RooAbsReal* coef ;
120  RooAbsReal* func = (RooAbsReal*)_funcIter->Next();
121 
122  Double_t central = func->getVal();
123  value = central;
124 
125  if (_quadraticAlgo >= 0) {
126  // additive interpolation
127  while((coef=(RooAbsReal*)_coefIter->Next())) {
128  Double_t coefVal = coef->getVal() ;
129  RooAbsReal* funcUp = (RooAbsReal*)_funcIter->Next() ;
130  RooAbsReal* funcDn = (RooAbsReal*)_funcIter->Next() ;
131  value += interpolate(coefVal, central, funcUp, funcDn);
132  }
133  } else {
134  // multiplicative interpolation
135  while((coef=(RooAbsReal*)_coefIter->Next())) {
136  Double_t coefVal = coef->getVal() ;
137  RooAbsReal* funcUp = (RooAbsReal*)_funcIter->Next() ;
138  RooAbsReal* funcDn = (RooAbsReal*)_funcIter->Next() ;
139  value *= interpolate(coefVal, central, funcUp, funcDn);
140  }
141  }
142 
143  return value > 0 ? value : 1E-9 ;
144 }
145 
146 
147 
148 
149 //_____________________________________________________________________________
150 Bool_t VerticalInterpPdf::checkObservables(const RooArgSet* nset) const
151 {
152  // Check if FUNC is valid for given normalization set.
153  // Coeffient and FUNC must be non-overlapping, but func-coefficient
154  // pairs may overlap each other
155  //
156  // In the present implementation, coefficients may not be observables or derive
157  // from observables
158  if (_quadraticAlgo == -1) return false; // multiplicative morphing. we don't care.
159 
160 
161  _coefIter->Reset() ;
162  RooAbsReal* coef ;
163  while((coef=(RooAbsReal*)_coefIter->Next())) {
164  if (coef->dependsOn(*nset)) {
165  coutE(InputArguments) << "RooRealPdf::checkObservables(" << GetName() << "): ERROR coefficient " << coef->GetName()
166  << " depends on one or more of the following observables" ; nset->Print("1") ;
167  return true;
168  }
169  }
170 
171  _funcIter->Reset() ;
172  RooAbsReal* func ;
173  while((func = (RooAbsReal*)_funcIter->Next())) {
174  if (func->observableOverlaps(nset,*coef)) {
175  coutE(InputArguments) << "VerticalInterpPdf::checkObservables(" << GetName() << "): ERROR: coefficient " << coef->GetName()
176  << " and FUNC " << func->GetName() << " have one or more observables in common" << endl ;
177  return true;
178  }
179  }
180 
181  return false;
182 }
183 
184 
185 
186 
187 //_____________________________________________________________________________
188 Int_t VerticalInterpPdf::getAnalyticalIntegralWN(RooArgSet& allVars, RooArgSet& analVars,
189  const RooArgSet* normSet2, const char* /*rangeName*/) const
190 {
191  // Advertise that all integrals can be handled internally.
192 
193  // Handle trivial no-integration scenario
194  if (allVars.getSize()==0) return 0 ;
195  if (_forceNumInt) return 0 ;
196 
197  // Select subset of allVars that are actual dependents
198  analVars.add(allVars) ;
199  RooArgSet* normSet = normSet2 ? getObservables(normSet2) : 0 ;
200 
201 
202  // Check if this configuration was created before
203  Int_t sterileIdx(-1) ;
204  CacheElem* cache = (CacheElem*) _normIntMgr.getObj(normSet,&analVars,&sterileIdx,(const char *)0);
205  if (cache) {
206  return _normIntMgr.lastIndex()+1 ;
207  }
208 
209  // Create new cache element
210  cache = new CacheElem ;
211 
212  // Make list of function projection and normalization integrals
213  _funcIter->Reset() ;
214  RooAbsReal *func ;
215  while((func=(RooAbsReal*)_funcIter->Next())) {
216  RooAbsReal* funcInt = func->createIntegral(analVars) ;
217  cache->_funcIntList.addOwned(*funcInt) ;
218  if (normSet && normSet->getSize()>0) {
219  RooAbsReal* funcNorm = func->createIntegral(*normSet) ;
220  cache->_funcNormList.addOwned(*funcNorm) ;
221  }
222  }
223 
224  // Store cache element
225  Int_t code = _normIntMgr.setObj(normSet,&analVars,(RooAbsCacheElement*)cache,0) ;
226 
227  if (normSet) {
228  delete normSet ;
229  }
230 
231  return code+1 ;
232 }
233 
234 
235 
236 
237 //_____________________________________________________________________________
238 Double_t VerticalInterpPdf::analyticalIntegralWN(Int_t code, const RooArgSet* normSet2, const char* /*rangeName*/) const
239 {
240  // Implement analytical integrations by deferring integration of component
241  // functions to integrators of components
242 
243  // Handle trivial passthrough scenario
244  if (code==0) return getVal(normSet2) ;
245 
246  RooAbsReal *coef;
247  Double_t value = 0;
248 
249  // WVE needs adaptation for rangeName feature
250  CacheElem* cache = (CacheElem*) _normIntMgr.getObjByIndex(code-1) ;
251 
252  TIterator* funcIntIter = cache->_funcIntList.createIterator() ;
253  RooAbsReal *funcInt = (RooAbsReal *) funcIntIter->Next();
254  Double_t central = funcInt->getVal();
255  value += central;
256 
257  _coefIter->Reset() ;
258  while((coef=(RooAbsReal*)_coefIter->Next())) {
259  Double_t coefVal = coef->getVal(normSet2) ;
260  RooAbsReal * funcIntUp = (RooAbsReal*)funcIntIter->Next() ;
261  RooAbsReal * funcIntDn = (RooAbsReal*)funcIntIter->Next() ;
262  value += interpolate(coefVal, central, funcIntUp, funcIntDn);
263  }
264 
265  delete funcIntIter ;
266 
267  Double_t normVal(1) ;
268  if (normSet2) {
269  normVal = 0 ;
270 
271  TIterator* funcNormIter = cache->_funcNormList.createIterator() ;
272 
273  RooAbsReal* funcNorm = (RooAbsReal*) funcNormIter->Next();
274  central = funcNorm->getVal(normSet2) ;
275 
276  _coefIter->Reset() ;
277  while((coef=(RooAbsReal*)_coefIter->Next())) {
278  RooAbsReal *funcNormUp = (RooAbsReal*)funcNormIter->Next() ;
279  RooAbsReal *funcNormDn = (RooAbsReal*)funcNormIter->Next() ;
280  Double_t coefVal = coef->getVal(normSet2) ;
281  normVal += interpolate(coefVal, central, funcNormUp, funcNormDn);
282  }
283 
284  delete funcNormIter ;
285  }
286 
287  return ( value > 0 ? value : 1E-9 ) / normVal;
288 }
289 
290 Double_t VerticalInterpPdf::interpolate(Double_t coeff, Double_t central, RooAbsReal *fUp, RooAbsReal *fDn) const
291 {
292  if (_quadraticAlgo == -1) {
293  Double_t kappa = (coeff > 0 ? fUp->getVal()/central : central/fDn->getVal());
294  return pow(kappa,fabs(coeff));
295  }
296 
297  if (fabs(coeff) >= _quadraticRegion) {
298  return coeff * (coeff > 0 ? fUp->getVal() - central : central - fDn->getVal());
299  } else {
300  // quadratic interpolation coefficients between the three
301  if (_quadraticAlgo != 1) {
302  // quadratic interpolation null in zero and continuos at boundaries, but not differentiable at boundaries
303  // conditions:
304  // c_up (+_quadraticRegion) = +_quadraticRegion
305  // c_cen(+_quadraticRegion) = -_quadraticRegion
306  // c_dn (+_quadraticRegion) = 0
307  // c_up (-_quadraticRegion) = 0
308  // c_cen(-_quadraticRegion) = -_quadraticRegion
309  // c_dn (-_quadraticRegion) = +_quadraticRegion
310  // c_up(0) = c_dn(0) = c_cen(0) = 0
311  Double_t c_up = + coeff * (_quadraticRegion + coeff) / (2 * _quadraticRegion);
312  Double_t c_dn = - coeff * (_quadraticRegion - coeff) / (2 * _quadraticRegion);
313  Double_t c_cen = - coeff * coeff / _quadraticRegion;
314  return c_up * fUp->getVal() + c_dn * fDn->getVal() + c_cen * central;
315  } else { //if (_quadraticAlgo == 1) {
316  // quadratic interpolation that is everywhere differentiable, but it's not null in zero
317  // conditions on the function
318  // c_up (+_quadraticRegion) = +_quadraticRegion
319  // c_cen(+_quadraticRegion) = -_quadraticRegion
320  // c_dn (+_quadraticRegion) = 0
321  // c_up (-_quadraticRegion) = 0
322  // c_cen(-_quadraticRegion) = -_quadraticRegion
323  // c_dn (-_quadraticRegion) = +_quadraticRegion
324  // conditions on the derivatives
325  // c_up '(+_quadraticRegion) = +1
326  // c_cen'(+_quadraticRegion) = -1
327  // c_dn '(+_quadraticRegion) = 0
328  // c_up '(-_quadraticRegion) = 0
329  // c_cen'(-_quadraticRegion) = +1
330  // c_dn '(-_quadraticRegion) = -1
331  Double_t c_up = (_quadraticRegion + coeff) * (_quadraticRegion + coeff) / (4 * _quadraticRegion);
332  Double_t c_dn = (_quadraticRegion - coeff) * (_quadraticRegion - coeff) / (4 * _quadraticRegion);
333  Double_t c_cen = - c_up - c_dn;
334  return c_up * fUp->getVal() + c_dn * fDn->getVal() + c_cen * central;
335  }
336  }
337 
338 }
Double_t interpolate(Double_t coeff, Double_t central, RooAbsReal *fUp, RooAbsReal *fDown) const
Iterator over coefficient list.
RooListProxy _funcList
RooListProxy _coefList
RooObjCacheManager _normIntMgr
TIterator * _coefIter
Iterator over FUNC list.
virtual Bool_t checkObservables(const RooArgSet *nset) const
Double_t analyticalIntegralWN(Int_t code, const RooArgSet *normSet, const char *rangeName=0) const
Int_t getAnalyticalIntegralWN(RooArgSet &allVars, RooArgSet &numVars, const RooArgSet *normSet, const char *rangeName=0) const
Double_t evaluate() const
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40