Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooXYChi2Var.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/// \class RooXYChi2Var
19/// RooXYChi2Var implements a simple chi^2 calculation from an unbinned
20/// dataset with values x,y with errors on y (and optionally on x) and a function.
21/// The function can be either a RooAbsReal, or an extended RooAbsPdf where
22/// the function value is calculated as the probability density times the
23/// expected number of events.
24/// The chi^2 is calculated as
25/// ```
26///
27/// / (Data[y]-) - func \+2
28/// Sum[point] | ------------------ |
29/// \ Data[ErrY] /
30/// ```
31///
32
33#include "RooFit.h"
34
35#include "RooXYChi2Var.h"
36#include "RooDataSet.h"
37#include "RooAbsReal.h"
38
39#include "Riostream.h"
40
41#include "RooRealVar.h"
42
43#include "RooAbsDataStore.h"
44#include "RooRealBinding.h"
45#include "RooNumIntFactory.h"
46
47#include <stdexcept>
48
49using namespace std;
50
52;
53
54namespace {
55 RooAbsTestStatistic::Configuration makeRooAbsTestStatisticCfg() {
57 cfg.verbose = false;
58 return cfg;
59 }
60}
61
62
63////////////////////////////////////////////////////////////////////////////////
64/// coverity[UNINIT_CTOR]
65
67{
68 _funcInt = 0 ;
70}
71
72
73////////////////////////////////////////////////////////////////////////////////
74///
75/// RooXYChi2Var constructor with function and X-Y values dataset
76///
77/// An X-Y dataset is a weighted dataset with one or more observables X where the weight is interpreted
78/// as the Y value and the weight error is interpreted as the Y value error. The weight must have an
79/// non-zero error defined at each point for the chi^2 calculation to be meaningful.
80///
81/// To store errors associated with the x and y values in a RooDataSet, call RooRealVar::setAttribute("StoreError")
82/// on each X-type observable for which the error should be stored and add datapoints to the dataset as follows
83///
84/// RooDataSet::add(xset,yval,yerr) where xset is the RooArgSet of x observables (with or without errors) and yval and yerr
85/// are the Double_t values that correspond to the Y and its error
86///
87
88RooXYChi2Var::RooXYChi2Var(const char *name, const char* title, RooAbsReal& func, RooDataSet& xydata, Bool_t integrate) :
89 RooAbsOptTestStatistic(name,title,func,xydata,RooArgSet(),makeRooAbsTestStatisticCfg()),
90 _extended(kFALSE),
91 _integrate(integrate),
92 _intConfig(*defaultIntegratorConfig()),
93 _funcInt(0)
94{
96 _yvar = 0 ;
97
98 initialize() ;
99}
100
101
102////////////////////////////////////////////////////////////////////////////////
103///
104/// RooXYChi2Var constructor with function and X-Y values dataset
105///
106/// An X-Y dataset is a weighted dataset with one or more observables X where given yvar is interpreted
107/// as the Y value. The Y variable must have a non-zero error defined at each point for the chi^2 calculation to be meaningful.
108///
109/// To store errors associated with the x and y values in a RooDataSet, call RooRealVar::setAttribute("StoreError")
110/// on each X-type observable for which the error should be stored and add datapoints to the dataset as follows
111///
112/// RooDataSet::add(xset,yval,yerr) where xset is the RooArgSet of x observables (with or without errors) and yval and yerr
113/// are the Double_t values that correspond to the Y and its error
114///
115
116RooXYChi2Var::RooXYChi2Var(const char *name, const char* title, RooAbsReal& func, RooDataSet& xydata, RooRealVar& yvar, Bool_t integrate) :
117 RooAbsOptTestStatistic(name,title,func,xydata,RooArgSet(),makeRooAbsTestStatisticCfg()),
118 _extended(kFALSE),
119 _integrate(integrate),
120 _intConfig(*defaultIntegratorConfig()),
121 _funcInt(0)
122{
123 _extended = kFALSE ;
124 _yvar = (RooRealVar*) _dataClone->get()->find(yvar.GetName()) ;
125
126 initialize() ;
127}
128
129
130////////////////////////////////////////////////////////////////////////////////
131///
132/// RooXYChi2Var constructor with an extended p.d.f. and X-Y values dataset
133/// The value of the function that defines the chi^2 in this form is takes as
134/// the p.d.f. times the expected number of events
135///
136/// An X-Y dataset is a weighted dataset with one or more observables X where the weight is interpreted
137/// as the Y value and the weight error is interpreted as the Y value error. The weight must have an
138/// non-zero error defined at each point for the chi^2 calculation to be meaningful.
139///
140/// To store errors associated with the x and y values in a RooDataSet, call RooRealVar::setAttribute("StoreError")
141/// on each X-type observable for which the error should be stored and add datapoints to the dataset as follows
142///
143/// RooDataSet::add(xset,yval,yerr) where xset is the RooArgSet of x observables (with or without errors) and yval and yerr
144/// are the Double_t values that correspond to the Y and its error
145///
146
147RooXYChi2Var::RooXYChi2Var(const char *name, const char* title, RooAbsPdf& extPdf, RooDataSet& xydata, Bool_t integrate) :
148 RooAbsOptTestStatistic(name,title,extPdf,xydata,RooArgSet(),makeRooAbsTestStatisticCfg()),
149 _extended(kTRUE),
150 _integrate(integrate),
151 _intConfig(*defaultIntegratorConfig()),
152 _funcInt(0)
153{
154 if (!extPdf.canBeExtended()) {
155 throw std::runtime_error(Form("RooXYChi2Var::RooXYChi2Var(%s) ERROR: Input p.d.f. must be extendible",GetName()));
156 }
157 _yvar = 0 ;
158 initialize() ;
159}
160
161
162
163
164////////////////////////////////////////////////////////////////////////////////
165///
166/// RooXYChi2Var constructor with an extended p.d.f. and X-Y values dataset
167/// The value of the function that defines the chi^2 in this form is takes as
168/// the p.d.f. times the expected number of events
169///
170/// An X-Y dataset is a weighted dataset with one or more observables X where the weight is interpreted
171/// as the Y value and the weight error is interpreted as the Y value error. The weight must have an
172/// non-zero error defined at each point for the chi^2 calculation to be meaningful.
173///
174/// To store errors associated with the x and y values in a RooDataSet, call RooRealVar::setAttribute("StoreError")
175/// on each X-type observable for which the error should be stored and add datapoints to the dataset as follows
176///
177/// RooDataSet::add(xset,yval,yerr) where xset is the RooArgSet of x observables (with or without errors) and yval and yerr
178/// are the Double_t values that correspond to the Y and its error
179///
180
181RooXYChi2Var::RooXYChi2Var(const char *name, const char* title, RooAbsPdf& extPdf, RooDataSet& xydata, RooRealVar& yvar, Bool_t integrate) :
182 RooAbsOptTestStatistic(name,title,extPdf,xydata,RooArgSet(),makeRooAbsTestStatisticCfg()),
183 _extended(kTRUE),
184 _integrate(integrate),
185 _intConfig(*defaultIntegratorConfig()),
186 _funcInt(0)
187{
188 if (!extPdf.canBeExtended()) {
189 throw std::runtime_error(Form("RooXYChi2Var::ctor(%s) ERROR: Input p.d.f. must be an extendible",GetName()));
190 }
191 _yvar = (RooRealVar*) _dataClone->get()->find(yvar.GetName()) ;
192 initialize() ;
193}
194
195
196
197
198////////////////////////////////////////////////////////////////////////////////
199/// Copy constructor
200
201RooXYChi2Var::RooXYChi2Var(const RooXYChi2Var& other, const char* name) :
203 _extended(other._extended),
204 _integrate(other._integrate),
205 _intConfig(other._intConfig),
206 _funcInt(0)
207{
208 _yvar = other._yvar ? (RooRealVar*) _dataClone->get()->find(other._yvar->GetName()) : 0 ;
209 initialize() ;
210
211}
212
213
214
215
216////////////////////////////////////////////////////////////////////////////////
217/// Common constructor initialization
218
220{
222 RooAbsArg* arg ;
223 while((arg=(RooAbsArg*)iter->Next())) {
224 RooRealVar* var = dynamic_cast<RooRealVar*>(arg) ;
225 if (var) {
226 _rrvArgs.add(*var) ;
227 }
228 }
229 if (_yvar) {
230 _rrvArgs.add(*_yvar) ;
231 }
232 delete iter ;
234
235 // Define alternate numeric integrator configuration for bin integration
236 // We expect bin contents to very only very slowly so a non-adaptive
237 // Gauss-Kronrod integrator is expected to perform well (if RooFitMore is available)
240#ifdef R__HAS_MATHMORE
241 _intConfig.method1D().setLabel("RooGaussKronrodIntegrator1D") ;
242#endif
243 _intConfig.methodND().setLabel("RooAdaptiveIntegratorND") ;
244
246
247}
248
249
250
251////////////////////////////////////////////////////////////////////////////////
252/// Initialize bin content integrator
253
255{
256 if (!_funcInt) {
258 _rrvIter->Reset() ;
259 RooRealVar* x ;
260 while((x=(RooRealVar*)_rrvIter->Next())) {
261 _binList.push_back(&x->getBinning("bin",kFALSE,kTRUE)) ;
262 }
263 }
264
265}
266
267
268
269////////////////////////////////////////////////////////////////////////////////
270/// Destructor
271
273{
274 delete _rrvIter ;
275 if (_funcInt) delete _funcInt ;
276}
277
278
279
280
281////////////////////////////////////////////////////////////////////////////////
282/// Calculate contribution to internal error due to error on 'x' coordinates
283/// at point i
284
286{
287 RooRealVar* var ;
288 Double_t ret(0) ;
289
290 _rrvIter->Reset() ;
291 while((var=(RooRealVar*)_rrvIter->Next())) {
292
293 if (var->hasAsymError()) {
294
295 // Get value at central X
296 Double_t cxval = var->getVal() ;
297 Double_t xerrLo = -var->getAsymErrorLo() ;
298 Double_t xerrHi = var->getAsymErrorHi() ;
299 Double_t xerr = (xerrLo+xerrHi)/2 ;
300
301 // Get value at X-eps
302 var->setVal(cxval - xerr/100) ;
303 Double_t fxmin = fy() ;
304
305 // Get value at X+eps
306 var->setVal(cxval + xerr/100) ;
307 Double_t fxmax = fy() ;
308
309 // Calculate slope
310 Double_t slope = (fxmax-fxmin)/(2*xerr/100.) ;
311
312// cout << "xerrHi = " << xerrHi << " xerrLo = " << xerrLo << " slope = " << slope << endl ;
313
314 // Asymmetric X error, decide which one to use
315 if ((ydata>cxval && fxmax>fxmin) || (ydata<=cxval && fxmax<=fxmin)) {
316 // Use right X error
317 ret += pow(xerrHi*slope,2) ;
318 } else {
319 // Use left X error
320 ret += pow(xerrLo*slope,2) ;
321 }
322
323 } else if (var->hasError()) {
324
325 // Get value at central X
326 Double_t cxval = var->getVal() ;
327 Double_t xerr = var->getError() ;
328
329 // Get value at X-eps
330 var->setVal(cxval - xerr/100) ;
331 Double_t fxmin = fy() ;
332
333 // Get value at X+eps
334 var->setVal(cxval + xerr/100) ;
335 Double_t fxmax = fy() ;
336
337 // Calculate slope
338 Double_t slope = (fxmax-fxmin)/(2*xerr/100.) ;
339
340// cout << var << " " ;
341// var->Print() ;
342
343// cout << var->GetName() << " xerr = " << xerr << " slope = " << slope << endl ;
344
345 // Symmetric X error
346 ret += pow(xerr*slope,2) ;
347 }
348 }
349 return ret ;
350}
351
352
353
354
355////////////////////////////////////////////////////////////////////////////////
356/// Return function value requested bu present configuration
357///
358/// If integration is required, the function value integrated
359/// over the bin volume divided by the bin volume is returned,
360/// otherwise the value at the bin center is returned.
361/// The bin volume is defined by the error on the 'X' coordinates
362///
363/// If an extended p.d.f. is used as function, its value is
364/// also multiplied by the expected number of events here
365
367{
368 // Get function value
369 Double_t yfunc ;
370 if (!_integrate) {
371 yfunc = _funcClone->getVal(_dataClone->get()) ;
372 } else {
373 Double_t volume(1) ;
374 _rrvIter->Reset() ;
375 for (list<RooAbsBinning*>::const_iterator iter = _binList.begin() ; iter != _binList.end() ; ++iter) {
377 Double_t xmin = x->getVal() + x->getErrorLo() ;
378 Double_t xmax = x->getVal() + x->getErrorHi() ;
379 (*iter)->setRange(xmin,xmax) ;
380 x->setShapeDirty() ;
381 volume *= (xmax - xmin) ;
382 }
383 Double_t ret = _funcInt->getVal() ;
384 return ret / volume ;
385 }
386 if (_extended) {
387 RooAbsPdf* pdf = (RooAbsPdf*) _funcClone ;
388 // Multiply with expected number of events
389 yfunc *= pdf->expectedEvents(_dataClone->get()) ;
390 }
391 return yfunc ;
392}
393
394
395
396////////////////////////////////////////////////////////////////////////////////
397/// Calculate chi^2 in partition from firstEvent to lastEvent using given stepSize
398
399Double_t RooXYChi2Var::evaluatePartition(std::size_t firstEvent, std::size_t lastEvent, std::size_t stepSize) const
400{
401 Double_t result(0), carry(0);
402
403 // Loop over bins of dataset
404 RooDataSet* xydata = (RooDataSet*) _dataClone ;
405
406 _dataClone->store()->recalculateCache( _projDeps, firstEvent, lastEvent, stepSize,kFALSE ) ;
407
408 for (auto i=firstEvent ; i<lastEvent ; i+=stepSize) {
409
410 // get the data values for this event
411 xydata->get(i);
412
413 if (!xydata->valid()) {
414 continue ;
415 }
416
417// cout << "xydata = " << endl ;
418// xydata->get()->Print("v") ;
419 //xydata->store()->dump() ;
420
421 // Get function value
422 Double_t yfunc = fy() ;
423
424 // Get data value and error
425 Double_t ydata ;
426 Double_t eylo,eyhi ;
427 if (_yvar) {
428 ydata = _yvar->getVal() ;
429 eylo = -1*_yvar->getErrorLo() ;
430 eyhi = _yvar->getErrorHi() ;
431 } else {
432 ydata = xydata->weight() ;
433 xydata->weightError(eylo,eyhi) ;
434 }
435
436 // Calculate external error
437 Double_t eExt = yfunc-ydata ;
438
439 // Pick upper or lower error bar depending on sign of external error
440 Double_t eInt = (eExt>0) ? eyhi : eylo ;
441
442 // Add contributions due to error in x coordinates
443 Double_t eIntX2 = _integrate ? 0 : xErrorContribution(ydata) ;
444
445// cout << "fy = " << yfunc << " eExt = " << eExt << " eInt = " << eInt << " eIntX2 = " << eIntX2 << endl ;
446
447 // Return 0 if eInt=0, special handling in MINUIT will follow
448 if (eInt==0.) {
449 coutE(Eval) << "RooXYChi2Var::RooXYChi2Var(" << GetName() << ") INFINITY ERROR: data point " << i
450 << " has zero error, but function is not zero (f=" << yfunc << ")" << endl ;
451 return 0 ;
452 }
453
454 // Add chi2 term
455 Double_t term = eExt*eExt/(eInt*eInt+ eIntX2);
456 Double_t y = term - carry;
457 Double_t t = result + y;
458 carry = (t - result) - y;
459 result = t;
460 }
461
462 _evalCarry = carry;
463 return result ;
464}
465
466
467
469{
470 // Inform base class that observable yvar cannot be optimized away from the dataset
471 if (_yvar) return RooArgSet(*_yvar) ;
472 return RooArgSet() ;
473}
#define e(i)
Definition RSha256.hxx:103
#define coutE(a)
const Bool_t kFALSE
Definition RtypesCore.h:101
const Bool_t kTRUE
Definition RtypesCore.h:100
#define ClassImp(name)
Definition Rtypes.h:364
char name[80]
Definition TGX11.cxx:110
float xmin
float xmax
char * Form(const char *fmt,...)
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Definition RooAbsArg.h:69
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
TIterator * createIterator(Bool_t dir=kIterForward) const
TIterator-style iteration over contained elements.
RooAbsArg * find(const char *name) const
Find object with given name in list.
virtual void recalculateCache(const RooArgSet *, Int_t, Int_t, Int_t, Bool_t)
virtual const RooArgSet * get() const
Definition RooAbsData.h:128
RooAbsDataStore * store()
Definition RooAbsData.h:104
virtual Bool_t valid() const
Definition RooAbsData.h:134
RooAbsOptTestStatistic is the abstract base class for test statistics objects that evaluate a functio...
Bool_t canBeExtended() const
If true, PDF can provide extended likelihood term.
Definition RooAbsPdf.h:262
virtual Double_t expectedEvents(const RooArgSet *nset) const
Return expected number of events to be used in calculation of extended likelihood.
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition RooAbsReal.h:64
RooAbsReal * createIntegral(const RooArgSet &iset, const RooCmdArg &arg1, const RooCmdArg &arg2=RooCmdArg::none(), const RooCmdArg &arg3=RooCmdArg::none(), const RooCmdArg &arg4=RooCmdArg::none(), const RooCmdArg &arg5=RooCmdArg::none(), const RooCmdArg &arg6=RooCmdArg::none(), const RooCmdArg &arg7=RooCmdArg::none(), const RooCmdArg &arg8=RooCmdArg::none()) const
Create an object that represents the integral of the function over one or more observables listed in ...
Double_t getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:94
Double_t _evalCarry
Offset as KahanSum to avoid loss of precision.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:35
virtual Bool_t setLabel(const char *label, bool printError=true) override
Set value by specifying the name of the desired state.
RooDataSet is a container class to hold unbinned data.
Definition RooDataSet.h:36
virtual const RooArgSet * get(Int_t index) const override
Return RooArgSet with coordinates of event 'index'.
virtual void weightError(double &lo, double &hi, ErrorType etype=SumW2) const override
Return the asymmetric errors on the current weight.
virtual Double_t weight() const override
Return event weight of current event.
void setEpsAbs(Double_t newEpsAbs)
Set absolute convergence criteria (convergence if abs(Err)<newEpsAbs)
RooCategory & methodND()
void setEpsRel(Double_t newEpsRel)
Set relative convergence criteria (convergence if abs(Err)/abs(Int)<newEpsRel)
RooCategory & method1D()
RooRealVar represents a variable that can be changed from the outside.
Definition RooRealVar.h:39
Double_t getAsymErrorLo() const
Definition RooRealVar.h:66
Double_t getErrorHi() const
Definition RooRealVar.h:72
Bool_t hasAsymError(Bool_t allowZero=kTRUE) const
Definition RooRealVar.h:68
Double_t getErrorLo() const
Definition RooRealVar.h:71
Double_t getAsymErrorHi() const
Definition RooRealVar.h:67
Bool_t hasError(Bool_t allowZero=kTRUE) const
Definition RooRealVar.h:63
Double_t getError() const
Definition RooRealVar.h:62
virtual void setVal(Double_t value)
Set value of variable to 'value'.
RooXYChi2Var implements a simple chi^2 calculation from an unbinned dataset with values x,...
RooAbsReal * _funcInt
RooArgSet requiredExtraObservables() const
std::list< RooAbsBinning * > _binList
Function integral.
Bool_t _extended
void initIntegrator()
Initialize bin content integrator.
RooRealVar * _yvar
RooXYChi2Var()
coverity[UNINIT_CTOR]
virtual ~RooXYChi2Var()
Destructor.
TIterator * _rrvIter
RooArgSet _rrvArgs
virtual Double_t evaluatePartition(std::size_t firstEvent, std::size_t lastEvent, std::size_t stepSize) const
Calculate chi^2 in partition from firstEvent to lastEvent using given stepSize.
Double_t fy() const
Return function value requested bu present configuration.
void initialize()
Iterator over set of real-valued observables.
Bool_t _integrate
RooNumIntConfig _intConfig
Double_t xErrorContribution(Double_t ydata) const
Calculate contribution to internal error due to error on 'x' coordinates at point i.
Iterator abstract base class.
Definition TIterator.h:30
virtual void Reset()=0
virtual TObject * Next()=0
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17