ROOT  6.06/09
Reference Guide
RooNumConvolution.cxx
Go to the documentation of this file.
1 /*****************************************************************************
2  * Project: RooFit *
3  * Package: RooFitCore *
4  * @(#)root/roofitcore:$Id$
5  * Authors: *
6  * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7  * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8  * *
9  * Copyright (c) 2000-2005, Regents of the University of California *
10  * and Stanford University. All rights reserved. *
11  * *
12  * Redistribution and use in source and binary forms, *
13  * with or without modification, are permitted according to the terms *
14  * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15  *****************************************************************************/
16 
17 //////////////////////////////////////////////////////////////////////////////
18 //
19 // BEGIN_HTML
20 // Numeric 1-dimensional convolution operator PDF. This class can convolve any PDF
21 // with any other PDF
22 // <p>
23 // This class should not be used blindly as numeric convolution is computing
24 // intensive and prone to stability fitting problems. If an analytic convolution
25 // can be calculated, you should use that or implement it if not available.
26 // RooNumConvolution implements reasonable defaults that should convolve most
27 // functions reasonably well, but results strongly depend on the shape of your
28 // input PDFS so always check your result.
29 //
30 // The default integration engine for the numeric convolution is the
31 // adaptive Gauss-Kronrod method, which empirically seems the most robust
32 // for this task. You can override the convolution integration settings via
33 // the RooNumIntConfig object reference returned by the convIntConfig() member
34 // function
35 // <p>
36 // By default the numeric convolution is integrated from -infinity to
37 // +infinity through a <pre>x -> 1/x</pre> coordinate transformation of the
38 // tails. For convolution with a very small bandwidth it may be
39 // advantageous (for both CPU consumption and stability) if the
40 // integration domain is limited to a finite range. The function
41 // setConvolutionWindow(mean,width,scale) allows to set a sliding
42 // window around the x value to be calculated taking a RooAbsReal
43 // expression for an offset and a width to be taken around the x
44 // value. These input expression can be RooFormulaVars or other
45 // function objects although the 3d 'scale' argument 'scale'
46 // multiplies the width RooAbsReal expression given in the 2nd
47 // argument, allowing for an appropriate window definition for most
48 // cases without need for a RooFormulaVar object: e.g. a Gaussian
49 // resolution PDF do setConvolutionWindow(gaussMean,gaussSigma,5)
50 // Note that for a 'wide' Gaussian the -inf to +inf integration
51 // may converge more quickly than that over a finite range!
52 // <p>
53 // The default numeric precision is 1e-7, i.e. the global default for
54 // numeric integration but you should experiment with this value to
55 // see if it is sufficient for example by studying the number of function
56 // calls that MINUIT needs to fit your function as function of the
57 // convolution precision.
58 // END_HTML
59 //
60 
61 #include "RooFit.h"
62 
63 #include "Riostream.h"
64 #include "Riostream.h"
65 #include "TH2F.h"
66 #include "RooNumConvolution.h"
67 #include "RooArgList.h"
68 #include "RooRealVar.h"
69 #include "RooFormulaVar.h"
70 #include "RooCustomizer.h"
72 #include "RooNumIntFactory.h"
73 #include "RooGenContext.h"
74 #include "RooConvGenContext.h"
75 #include "RooMsgService.h"
76 
77 
78 using namespace std;
79 
81 ;
82 
83 
84 ////////////////////////////////////////////////////////////////////////////////
85 
87  _init(kFALSE),
88  _integrand(0),
89  _integrator(0),
90  _cloneVar(0),
91  _clonePdf(0),
92  _cloneModel(0),
93  _useWindow(kFALSE),
94  _windowScale(1),
95  _verboseThresh(2000),
96  _doProf(kFALSE),
97  _callHist(0)
98 {
99 }
100 
101 
102 
103 ////////////////////////////////////////////////////////////////////////////////
104 /// Constructor of convolution operator PDF
105 ///
106 /// convVar : convolution variable (on which both pdf and resmodel should depend)
107 /// pdf : input 'physics' pdf
108 /// resmodel : input 'resultion' pdf
109 ///
110 /// output is pdf(x) (X) resmodel(x) = Int [ pdf(x') resmodel (x-x') ] dx'
111 ///
112 
113 RooNumConvolution::RooNumConvolution(const char *name, const char *title, RooRealVar& convVar, RooAbsReal& inPdf, RooAbsReal& resmodel, const RooNumConvolution* proto) :
114  RooAbsReal(name,title),
115  _init(kFALSE),
116  _convIntConfig(RooNumIntConfig::defaultConfig()),
117  _integrand(0),
118  _integrator(0),
119  _origVar("origVar","Original Convolution variable",this,convVar),
120  _origPdf("origPdf","Original Input PDF",this,inPdf),
121  _origModel("origModel","Original Resolution model",this,resmodel),
122  _ownedClonedPdfSet("ownedClonePdfSet"),
123  _ownedClonedModelSet("ownedCloneModelSet"),
124  _cloneVar(0),
125  _clonePdf(0),
126  _cloneModel(0),
127  _useWindow(kFALSE),
128  _windowScale(1),
129  _windowParam("windowParam","Convolution window parameter",this,kFALSE),
130  _verboseThresh(2000),
131  _doProf(kFALSE),
132  _callHist(0)
133 {
134  // Use Adaptive Gauss-Kronrod integration by default for the convolution integral
135  _convIntConfig.method1D().setLabel("RooAdaptiveGaussKronrodIntegrator1D") ;
136  _convIntConfig.method1DOpen().setLabel("RooAdaptiveGaussKronrodIntegrator1D") ;
137 
138  if (proto) {
139  convIntConfig() = proto->convIntConfig() ;
140  if (proto->_useWindow) {
142  }
143  }
144 }
145 
146 
147 
148 ////////////////////////////////////////////////////////////////////////////////
149 /// Copy constructor
150 
152  RooAbsReal(other,name),
153  _init(kFALSE),
154  _convIntConfig(other._convIntConfig),
155  _integrand(0),
156  _integrator(0),
157  _origVar("origVar",this,other._origVar),
158  _origPdf("origPdf",this,other._origPdf),
159  _origModel("origModel",this,other._origModel),
160  _ownedClonedPdfSet("ownedClonePdfSet"),
161  _ownedClonedModelSet("ownedCloneModelSet"),
162  _cloneVar(0),
163  _clonePdf(0),
164  _cloneModel(0),
165  _useWindow(other._useWindow),
166  _windowScale(other._windowScale),
167  _windowParam("windowParam",this,other._windowParam),
168  _verboseThresh(other._verboseThresh),
169  _doProf(other._doProf),
170  _callHist(other._callHist)
171 {
172 }
173 
174 
175 
176 ////////////////////////////////////////////////////////////////////////////////
177 /// One-time initialization of object
178 
180 {
181  // Initialization function -- create clone of convVar (x') and deep-copy clones of pdf and
182  // model that are connected to x' rather than x (convVar)
183 
184  // Start out clean
187 
188  if (_cloneVar) delete _cloneVar ;
189 
190  // Customize a copy of origPdf that is connected to x' rather than x
191  // store all cloned components in _clonePdfSet as well as x' itself
192  _cloneVar = new RooRealVar(Form("%s_prime",_origVar.arg().GetName()),"Convolution Variable",0) ;
193 
194  RooCustomizer mgr1(pdf(),"NumConv_PdfClone") ;
196  mgr1.replaceArg(var(),*_cloneVar) ;
197  _clonePdf = (RooAbsReal*) mgr1.build() ;
198 
199  RooCustomizer mgr2(model(),"NumConv_ModelClone") ;
201  mgr2.replaceArg(var(),*_cloneVar) ;
202  _cloneModel = (RooAbsReal*) mgr2.build() ;
203 
204  // Change name back to original name
205  _cloneVar->SetName(var().GetName()) ;
206 
207  // Create Convolution integrand
209 
210  // Instantiate integrator for convolution integrand
213 
214  _init = kTRUE ;
215 }
216 
217 
218 
219 
220 ////////////////////////////////////////////////////////////////////////////////
221 /// Destructor
222 
224 {
225 }
226 
227 
228 
229 ////////////////////////////////////////////////////////////////////////////////
230 /// Calculate convolution integral
231 
233 {
234  // Check if deferred initialization has occurred
235  if (!_init) initialize() ;
236 
237  // Retrieve current value of convolution variable
238  Double_t x = _origVar ;
239 
240  // Propagate current normalization set to integrand
242 
243  // Adjust convolution integration window
244  if (_useWindow) {
245  Double_t center = ((RooAbsReal*)_windowParam.at(0))->getVal() ;
246  Double_t width = _windowScale * ((RooAbsReal*)_windowParam.at(1))->getVal() ;
247  _integrator->setLimits(x-center-width,x-center+width) ;
248  } else {
250  }
251 
252  // Calculate convolution for present x
254  Double_t ret = _integrator->integral(&x) ;
255  if (_doProf) {
258  coutW(Integration) << "RooNumConvolution::eveluate(" << GetName() << ") WARNING convolution integral at x=" << x
259  << " required " << _integrand->numCall() << " function evaluations" << endl ;
260  }
261  }
262 
263  return ret ;
264 }
265 
266 
267 
268 ////////////////////////////////////////////////////////////////////////////////
269 /// Intercept server redirects. Throw away cache, as figuring out redirections on the cache is an unsolvable problem.
270 
271 Bool_t RooNumConvolution::redirectServersHook(const RooAbsCollection& /*newServerList*/, Bool_t /*mustReplaceAll*/,
272  Bool_t /*nameChange*/, Bool_t /*isRecursive*/)
273 {
274  _init = kFALSE ;
275  return kFALSE ;
276 }
277 
278 
279 
280 ////////////////////////////////////////////////////////////////////////////////
281 /// Removes previously defined convolution window, reverting to convolution from -inf to +inf
282 
284 {
285  _useWindow = kFALSE ;
287 }
288 
289 
290 
291 ////////////////////////////////////////////////////////////////////////////////
292 /// Restrict convolution integral to finite range [ x - C - S*W, x - C + S*W ]
293 /// where x is current value of convolution variablem, C = centerParam, W=widthParam and S = widthScaleFactor
294 /// Inputs centerParam and withParam can be function expressions (RooAbsReal, RooFormulaVar) etc.
295 
296 void RooNumConvolution::setConvolutionWindow(RooAbsReal& centerParam, RooAbsReal& widthParam, Double_t widthScaleFactor)
297 {
298  _useWindow = kTRUE ;
300  _windowParam.add(centerParam) ;
301  _windowParam.add(widthParam) ;
302  _windowScale = widthScaleFactor ;
303 }
304 
305 
306 
307 ////////////////////////////////////////////////////////////////////////////////
308 /// Activate warning messages if number of function calls needed for evaluation of convolution integral
309 /// exceeds given threshold
310 
312 {
313  if (threshold<0) {
314  coutE(InputArguments) << "RooNumConvolution::setCallWarning(" << GetName() << ") ERROR: threshold must be positive, value unchanged" << endl ;
315  return ;
316  }
317  _verboseThresh = threshold ;
318 }
319 
320 
321 ////////////////////////////////////////////////////////////////////////////////
322 /// Activate call profile if flag is set to true. A 2-D histogram is kept that stores the required number
323 /// of function calls versus the value of x, the convolution variable
324 ///
325 /// All clones of RooNumConvolution objects will keep logging to the histogram of the original class
326 /// so that performance of temporary object clones, such as used in e.g. fitting, plotting and generating
327 /// are all logged in a single place.
328 ///
329 /// Function caller should take ownership of profiling histogram as it is not deleted at the RooNumConvolution dtor
330 ///
331 /// Calling this function with flag set to false will deactivate call profiling and delete the profiling histogram
332 
333 void RooNumConvolution::setCallProfiling(Bool_t flag, Int_t nbinX, Int_t nbinCall, Int_t nCallHigh)
334 {
335  if (flag) {
336  if (_doProf) {
337  delete _callHist ;
338  }
339  _callHist = new TH2F(Form("callHist_%s",GetName()),Form("Call Profiling of RooNumConvolution %s",GetTitle()),
340  nbinX,_origVar.min(),_origVar.max(),
341  nbinCall,0,nCallHigh) ;
342  _doProf=kTRUE ;
343 
344  } else if (_doProf) {
345 
346  delete _callHist ;
347  _callHist = 0 ;
348  _doProf = kFALSE ;
349  }
350 
351 }
352 
353 
354 
355 ////////////////////////////////////////////////////////////////////////////////
356 /// Hook function to intercept printCompactTree() calls so that it can print out
357 /// the content of its private cache in the print sequence
358 
359 void RooNumConvolution::printCompactTreeHook(ostream& os, const char* indent)
360 {
361  os << indent << "RooNumConvolution begin cache" << endl ;
362 
363  if (_init) {
364  _cloneVar->printCompactTree(os,Form("%s[Var]",indent)) ;
365  _clonePdf->printCompactTree(os,Form("%s[Pdf]",indent)) ;
366  _cloneModel->printCompactTree(os,Form("%s[Mod]",indent)) ;
367  }
368 
369  os << indent << "RooNumConvolution end cache" << endl ;
370 }
371 
372 
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:52
RooListProxy _windowParam
const RooArgSet * nset() const
Definition: RooAbsProxy.h:47
Double_t evaluate() const
Calculate convolution integral.
#define coutE(a)
Definition: RooMsgService.h:35
RooNumIntConfig & convIntConfig()
RooAbsReal * _cloneModel
void setCallProfiling(Bool_t flag, Int_t nbinX=40, Int_t nbinCall=40, Int_t nCallHigh=1000)
Activate call profile if flag is set to true.
virtual ~RooNumConvolution()
Destructor.
static RooNumIntFactory & instance()
Static method returning reference to singleton instance of factory.
THist< 2, float > TH2F
Definition: THist.h:321
RooAbsReal * _cloneVar
RooRealProxy _origVar
Numeric integrator of convolution integrand.
RooRealVar & var() const
RooNumIntConfig _convIntConfig
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
RooAbsReal & model() const
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual Bool_t setLimits(Double_t *, Double_t *)
STL namespace.
#define coutW(a)
Definition: RooMsgService.h:34
const RooAbsReal & arg() const
Definition: RooRealProxy.h:43
virtual Bool_t setLabel(const char *label, Bool_t printError=kTRUE)
Set value by specifying the name of the desired state If printError is set, a message will be printed...
void setNormalizationSet(const RooArgSet *nset)
RooCategory & method1D()
Double_t x[n]
Definition: legend1.C:17
RooAbsIntegrator * createIntegrator(RooAbsFunc &func, const RooNumIntConfig &config, Int_t ndim=0, Bool_t isBinned=kFALSE)
Construct a numeric integrator instance that operates on function 'func' and is configured with 'conf...
void printCompactTree(const char *indent="", const char *fileName=0, const char *namePat=0, RooAbsArg *client=0)
Print tree structure of expression tree on stdout, or to file if filename is specified.
Definition: RooAbsArg.cxx:1782
RooAbsReal & pdf() const
virtual Double_t integral(const Double_t *yvec=0)=0
RooAbsReal * _clonePdf
virtual void removeAll()
Remove all arguments from our set, deleting them if we own them.
void setCallWarning(Int_t threshold=2000)
Activate warning messages if number of function calls needed for evaluation of convolution integral e...
Double_t getVal(const RooArgSet *set=0) const
Definition: RooAbsReal.h:64
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Reimplementation of standard RooArgList::add()
Int_t numCall() const
Definition: RooAbsFunc.h:42
ClassImp(RooNumConvolution)
return
Definition: TBase64.cxx:62
RooConvIntegrandBinding * _integrand
void initialize() const
One-time initialization of object.
void SetName(const char *name)
Change (i.e.
Definition: RooAbsArg.cxx:2389
char * Form(const char *fmt,...)
static Double_t infinity()
Return internal infinity representation.
Definition: RooNumber.cxx:48
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
RooArgSet _ownedClonedModelSet
static void indent(ostringstream &buf, int indent_level)
void replaceArg(const RooAbsArg &orig, const RooAbsArg &subst)
Replace any occurence of arg 'orig' with arg 'subst'.
RooAbsArg * at(Int_t idx) const
Definition: RooArgList.h:84
void resetNumCall() const
Definition: RooAbsFunc.h:46
double Double_t
Definition: RtypesCore.h:55
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition: RooAbsReal.h:53
virtual Bool_t setUseIntegrandLimits(Bool_t flag)
Interface function that allows to defer limit definition to integrand definition. ...
RooCategory & method1DOpen()
Bool_t redirectServersHook(const RooAbsCollection &newServerList, Bool_t mustReplaceAll, Bool_t nameChange, Bool_t isRecursive)
Intercept server redirects. Throw away cache, as figuring out redirections on the cache is an unsolva...
#define name(a, b)
Definition: linkTestLib0.cpp:5
void setCloneBranchSet(RooArgSet &cloneBranchSet)
Install the input RooArgSet as container in which all cloned branches will be stored.
void clearConvolutionWindow()
Removes previously defined convolution window, reverting to convolution from -inf to +inf...
void setConvolutionWindow(RooAbsReal &centerParam, RooAbsReal &widthParam, Double_t widthScaleFactor=1)
Restrict convolution integral to finite range [ x - C - S*W, x - C + S*W ] where x is current value o...
virtual void removeAll()
Reimplementation of standard RooArgList::removeAll()
RooAbsArg * build(const char *masterCatState, Bool_t verbose=kFALSE)
Build a clone of the prototype executing all registered 'replace' rules and 'split' rules for the mas...
Double_t min(const char *rname=0) const
Definition: RooRealProxy.h:56
RooAbsIntegrator * _integrator
Binding of Convolution Integrand function.
const Bool_t kTRUE
Definition: Rtypes.h:91
Int_t Fill(Double_t)
Invalid Fill method.
Definition: TH2.cxx:285
RooArgSet _ownedClonedPdfSet
virtual void printCompactTreeHook(std::ostream &os, const char *indent="")
Hook function to intercept printCompactTree() calls so that it can print out the content of its priva...
Double_t max(const char *rname=0) const
Definition: RooRealProxy.h:57