RooXYChi2Var.cxx

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooXYChi2Var.cxx 36209 2010-10-08 21:37:36Z wouter $
00005  * Authors:                                                                  *
00006  *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
00007  *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
00008  *                                                                           *
00009  * Copyright (c) 2000-2005, Regents of the University of California          *
00010  *                          and Stanford University. All rights reserved.    *
00011  *                                                                           *
00012  * Redistribution and use in source and binary forms,                        *
00013  * with or without modification, are permitted according to the terms        *
00014  * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
00015  *****************************************************************************/
00016 
00017 //////////////////////////////////////////////////////////////////////////////
00018 // 
00019 // Class RooXYChi2Var implements a simple chi^2 calculation from a unbinned
00020 // dataset with values x,y with errors on y (and optionally on x) and a function.
00021 // The function can be either a RooAbsReal, or an extended RooAbsPdf where
00022 // the function value is calculated as the probability density times the
00023 // expected number of events
00024 // The chi^2 is calculated as 
00025 //
00026 //              / (Data[y]-) - func \+2
00027 //  Sum[point] |  ------------------ |
00028 //              \     Data[ErrY]    /
00029 //
00030 //
00031 
00032 #include "RooFit.h"
00033 
00034 #include "RooXYChi2Var.h"
00035 #include "RooDataSet.h"
00036 #include "RooAbsReal.h"
00037 
00038 #include "Riostream.h"
00039 
00040 #include "RooRealVar.h"
00041 
00042 #include "RooGaussKronrodIntegrator1D.h"
00043 #include "RooRealBinding.h"
00044 #include "RooNumIntFactory.h"
00045 
00046 ClassImp(RooXYChi2Var)
00047 ;
00048 
00049 
00050 //_____________________________________________________________________________
00051 RooXYChi2Var::RooXYChi2Var() 
00052 {
00053   // coverity[UNINIT_CTOR]
00054   _funcInt = 0 ;
00055   _rrvIter = _rrvArgs.createIterator() ;
00056 }
00057 
00058 
00059 //_____________________________________________________________________________
00060 RooXYChi2Var::RooXYChi2Var(const char *name, const char* title, RooAbsReal& func, RooDataSet& xydata, Bool_t integrate) :
00061   RooAbsOptTestStatistic(name,title,func,xydata,RooArgSet(),0,0,1,1,0,0), 
00062   _extended(kFALSE),
00063   _integrate(integrate),
00064   _intConfig(*defaultIntegratorConfig()),
00065   _funcInt(0)
00066 {
00067   //
00068   //  RooXYChi2Var constructor with function and X-Y values dataset
00069   //
00070   // An X-Y dataset is a weighted dataset with one or more observables X where the weight is interpreted
00071   // as the Y value and the weight error is interpreted as the Y value error. The weight must have an
00072   // non-zero error defined at each point for the chi^2 calculation to be meaningful.
00073   //
00074   // To store errors associated with the x and y values in a RooDataSet, call RooRealVar::setAttribute("StoreError")
00075   // on each X-type observable for which the error should be stored and add datapoints to the dataset as follows
00076   //
00077   // RooDataSet::add(xset,yval,yerr) where xset is the RooArgSet of x observables (with or without errors) and yval and yerr
00078   //                                 are the Double_t values that correspond to the Y and its error
00079   //
00080   _extended = kFALSE ;
00081   _yvar = 0 ;
00082 
00083   initialize() ;
00084 }
00085 
00086 
00087 //_____________________________________________________________________________
00088 RooXYChi2Var::RooXYChi2Var(const char *name, const char* title, RooAbsReal& func, RooDataSet& xydata, RooRealVar& yvar, Bool_t integrate) :
00089   RooAbsOptTestStatistic(name,title,func,xydata,RooArgSet(),0,0,1,1,0,0), 
00090   _extended(kFALSE),
00091   _integrate(integrate),
00092   _intConfig(*defaultIntegratorConfig()),
00093   _funcInt(0)  
00094 {
00095   //
00096   //  RooXYChi2Var constructor with function and X-Y values dataset
00097   //
00098   // An X-Y dataset is a weighted dataset with one or more observables X where given yvar is interpreted
00099   // 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.
00100   //
00101   // To store errors associated with the x and y values in a RooDataSet, call RooRealVar::setAttribute("StoreError")
00102   // on each X-type observable for which the error should be stored and add datapoints to the dataset as follows
00103   //
00104   // RooDataSet::add(xset,yval,yerr) where xset is the RooArgSet of x observables (with or without errors) and yval and yerr
00105   //                                 are the Double_t values that correspond to the Y and its error
00106   //
00107   _extended = kFALSE ;
00108   _yvar = (RooRealVar*) _dataClone->get()->find(yvar.GetName()) ;
00109 
00110   initialize() ;
00111 }
00112 
00113 
00114 //_____________________________________________________________________________
00115 RooXYChi2Var::RooXYChi2Var(const char *name, const char* title, RooAbsPdf& extPdf, RooDataSet& xydata, Bool_t integrate) :
00116   RooAbsOptTestStatistic(name,title,extPdf,xydata,RooArgSet(),0,0,1,1,0,0), 
00117   _extended(kTRUE),
00118   _integrate(integrate),
00119   _intConfig(*defaultIntegratorConfig()),
00120   _funcInt(0)
00121 {
00122   //
00123   // RooXYChi2Var constructor with an extended p.d.f. and X-Y values dataset
00124   // The value of the function that defines the chi^2 in this form is takes as
00125   // the p.d.f. times the expected number of events
00126   //
00127   // An X-Y dataset is a weighted dataset with one or more observables X where the weight is interpreted
00128   // as the Y value and the weight error is interpreted as the Y value error. The weight must have an
00129   // non-zero error defined at each point for the chi^2 calculation to be meaningful.
00130   //
00131   // To store errors associated with the x and y values in a RooDataSet, call RooRealVar::setAttribute("StoreError")
00132   // on each X-type observable for which the error should be stored and add datapoints to the dataset as follows
00133   //
00134   // RooDataSet::add(xset,yval,yerr) where xset is the RooArgSet of x observables (with or without errors) and yval and yerr
00135   //                                 are the Double_t values that correspond to the Y and its error
00136   //
00137   if (!extPdf.canBeExtended()) {
00138     throw(string(Form("RooXYChi2Var::ctor(%s) ERROR: Input p.d.f. must be an extendible",GetName()))) ;
00139   }
00140   _yvar = 0 ;
00141   initialize() ;
00142 }
00143 
00144 
00145 
00146 
00147 //_____________________________________________________________________________
00148 RooXYChi2Var::RooXYChi2Var(const char *name, const char* title, RooAbsPdf& extPdf, RooDataSet& xydata, RooRealVar& yvar, Bool_t integrate) :
00149   RooAbsOptTestStatistic(name,title,extPdf,xydata,RooArgSet(),0,0,1,1,0,0), 
00150   _extended(kTRUE),
00151   _integrate(integrate),
00152   _intConfig(*defaultIntegratorConfig()),
00153   _funcInt(0)
00154 {
00155   //
00156   // RooXYChi2Var constructor with an extended p.d.f. and X-Y values dataset
00157   // The value of the function that defines the chi^2 in this form is takes as
00158   // the p.d.f. times the expected number of events
00159   //
00160   // An X-Y dataset is a weighted dataset with one or more observables X where the weight is interpreted
00161   // as the Y value and the weight error is interpreted as the Y value error. The weight must have an
00162   // non-zero error defined at each point for the chi^2 calculation to be meaningful.
00163   //
00164   // To store errors associated with the x and y values in a RooDataSet, call RooRealVar::setAttribute("StoreError")
00165   // on each X-type observable for which the error should be stored and add datapoints to the dataset as follows
00166   //
00167   // RooDataSet::add(xset,yval,yerr) where xset is the RooArgSet of x observables (with or without errors) and yval and yerr
00168   //                                 are the Double_t values that correspond to the Y and its error
00169   //
00170   if (!extPdf.canBeExtended()) {
00171     throw(string(Form("RooXYChi2Var::ctor(%s) ERROR: Input p.d.f. must be an extendible",GetName()))) ;
00172   }
00173   _yvar = (RooRealVar*) _dataClone->get()->find(yvar.GetName()) ;
00174   initialize() ;
00175 }
00176 
00177 
00178 
00179 
00180 //_____________________________________________________________________________
00181 RooXYChi2Var::RooXYChi2Var(const RooXYChi2Var& other, const char* name) : 
00182   RooAbsOptTestStatistic(other,name),
00183   _extended(other._extended),
00184   _integrate(other._integrate),
00185   _intConfig(other._intConfig),
00186   _funcInt(0)
00187 {
00188   // Copy constructor
00189 
00190   _yvar = other._yvar ? (RooRealVar*) _dataClone->get()->find(other._yvar->GetName()) : 0 ;
00191   initialize() ;
00192   
00193 }
00194 
00195 
00196 
00197 
00198 //_____________________________________________________________________________
00199 void RooXYChi2Var::initialize()
00200 {
00201   // Common constructor initialization
00202 
00203   TIterator* iter = _dataClone->get()->createIterator() ;
00204   RooAbsArg* arg ;
00205   while((arg=(RooAbsArg*)iter->Next())) {
00206     RooRealVar* var = dynamic_cast<RooRealVar*>(arg) ;
00207     if (var) {
00208       _rrvArgs.add(*var) ;
00209     }
00210   }
00211   delete iter ;
00212   _rrvIter = _rrvArgs.createIterator() ;
00213 
00214   // Define alternate numeric integrator configuration for bin integration
00215   // We expect bin contents to very only very slowly so a non-adaptive
00216   // Gauss-Kronrod integrator is expected to perform well.
00217   _intConfig.setEpsRel(1e-7) ;
00218   _intConfig.setEpsAbs(1e-7) ;
00219   _intConfig.method1D().setLabel("RooGaussKronrodIntegrator1D") ;
00220   _intConfig.methodND().setLabel("RooAdaptiveIntegratorND") ;
00221 
00222   initIntegrator() ;
00223   
00224 }
00225 
00226 
00227 
00228 //_____________________________________________________________________________
00229 void RooXYChi2Var::initIntegrator()
00230 {
00231   // Initialize bin content integrator
00232 
00233   if (!_funcInt) {
00234     _funcInt = _funcClone->createIntegral(_rrvArgs,_rrvArgs,_intConfig,"bin") ;
00235     _rrvIter->Reset() ;
00236     RooRealVar* x ;
00237     while((x=(RooRealVar*)_rrvIter->Next())) {
00238       _binList.push_back(&x->getBinning("bin",kFALSE,kTRUE)) ;
00239     }
00240   }
00241   
00242 }
00243 
00244 
00245 
00246 //_____________________________________________________________________________
00247 RooXYChi2Var::~RooXYChi2Var()
00248 {
00249   // Destructor
00250 
00251   delete _rrvIter ;
00252   if (_funcInt) delete _funcInt ;
00253 }
00254 
00255 
00256 
00257 
00258 //_____________________________________________________________________________
00259 Double_t RooXYChi2Var::xErrorContribution(Double_t ydata) const
00260 {
00261   // Calculate contribution to internal error due to error on 'x' coordinates
00262   // at point i
00263 
00264   RooRealVar* var ;
00265   Double_t ret(0) ;
00266   _rrvIter->Reset() ;
00267   while((var=(RooRealVar*)_rrvIter->Next())) {
00268 
00269     if (var->hasAsymError()) {
00270       
00271       // Get value at central X
00272       Double_t cxval = var->getVal() ;
00273       Double_t xerrLo = -var->getAsymErrorLo() ;
00274       Double_t xerrHi = var->getAsymErrorHi() ;
00275       Double_t xerr = (xerrLo+xerrHi)/2 ;
00276       
00277       // Get value at X-eps
00278       var->setVal(cxval - xerr/100) ;
00279       Double_t fxmin = fy() ;
00280 
00281       // Get value at X+eps
00282       var->setVal(cxval + xerr/100) ;
00283       Double_t fxmax = fy() ;
00284       
00285       // Calculate slope
00286       Double_t slope = (fxmax-fxmin)/(2*xerr/100.) ;
00287       
00288       // Asymmetric X error, decide which one to use
00289       if ((ydata>cxval && fxmax>fxmin) || (ydata<=cxval && fxmax<=fxmin)) {
00290         // Use right X error
00291         ret += pow(xerrHi*slope,2) ;
00292       } else {
00293         // Use left X error
00294         ret += pow(xerrLo*slope,2) ;
00295       }
00296       
00297     } else if (var->hasError()) {
00298 
00299       // Get value at central X
00300       Double_t cxval = var->getVal() ;
00301       Double_t xerr = var->getError() ;
00302 
00303       // Get value at X-eps
00304       var->setVal(cxval - xerr/100) ;
00305       Double_t fxmin = fy() ;
00306 
00307       // Get value at X+eps
00308       var->setVal(cxval + xerr/100) ;
00309       Double_t fxmax = fy() ;
00310       
00311       // Calculate slope
00312       Double_t slope = (fxmax-fxmin)/(2*xerr/100.) ;
00313             
00314       // Symmetric X error
00315       ret += pow(xerr*slope,2) ;
00316     }    
00317   }
00318   return ret ;
00319 }
00320 
00321 
00322 
00323 
00324 //_____________________________________________________________________________
00325 Double_t RooXYChi2Var::fy() const
00326 {
00327   // Return function value requested bu present configuration
00328   //
00329   // If integration is required, the function value integrated
00330   // over the bin volume divided by the bin volume is returned,
00331   // otherwise the value at the bin center is returned. 
00332   // The bin volume is defined by the error on the 'X' coordinates
00333   //
00334   // If an extended p.d.f. is used as function, its value is
00335   // also multiplied by the expected number of events here
00336 
00337   // Get function value
00338   Double_t yfunc ;
00339   if (!_integrate) {
00340     yfunc = _funcClone->getVal(_dataClone->get()) ;
00341   } else {
00342     Double_t volume(1) ;
00343     _rrvIter->Reset() ;
00344     for (list<RooAbsBinning*>::const_iterator iter = _binList.begin() ; iter != _binList.end() ; iter++) {
00345       RooRealVar* x = (RooRealVar*) _rrvIter->Next() ;
00346       Double_t xmin = x->getVal() + x->getErrorLo() ;
00347       Double_t xmax = x->getVal() + x->getErrorHi() ;
00348       (*iter)->setRange(xmin,xmax) ;
00349       x->setShapeDirty() ;
00350       volume *= (xmax - xmin) ;
00351     }
00352     Double_t ret = _funcInt->getVal() ;
00353     return ret / volume ;
00354   }
00355   if (_extended) {      
00356     RooAbsPdf* pdf = (RooAbsPdf*) _funcClone ;
00357     // Multiply with expected number of events
00358     yfunc *= pdf->expectedEvents(_dataClone->get()) ;
00359   }      
00360   return yfunc ;
00361 }
00362 
00363 
00364 
00365 //_____________________________________________________________________________
00366 Double_t RooXYChi2Var::evaluatePartition(Int_t firstEvent, Int_t lastEvent, Int_t stepSize) const 
00367 {
00368   // Calculate chi^2 in partition from firstEvent to lastEvent using given stepSize
00369 
00370   Double_t result(0) ;
00371 
00372   // Loop over bins of dataset
00373   RooDataSet* xydata = (RooDataSet*) _dataClone ;
00374 
00375   for (Int_t i=firstEvent ; i<lastEvent ; i+=stepSize) {
00376     
00377     // get the data values for this event
00378     xydata->get(i);
00379     
00380     if (!xydata->valid()) {
00381       continue ;
00382     }
00383 
00384     // Get function value
00385     Double_t yfunc = fy() ;
00386 
00387     // Get data value and error
00388     Double_t ydata ;
00389     Double_t eylo,eyhi ;
00390     if (_yvar) {
00391       ydata = _yvar->getVal() ;
00392       eylo = -1*_yvar->getErrorLo() ;
00393       eyhi = _yvar->getErrorHi() ;
00394     } else {
00395       ydata = xydata->weight() ;
00396       xydata->weightError(eylo,eyhi) ;
00397     }
00398 
00399     // Calculate external error
00400     Double_t eExt = yfunc-ydata ;
00401 
00402     // Pick upper or lower error bar depending on sign of external error
00403     Double_t eInt = (eExt>0) ? eyhi : eylo ;
00404 
00405     // Add contributions due to error in x coordinates    
00406     Double_t eIntX2 = _integrate ? 0 : xErrorContribution(ydata) ;
00407 
00408     // Return 0 if eInt=0, special handling in MINUIT will follow
00409     if (eInt==0.) {
00410       coutE(Eval) << "RooXYChi2Var::RooXYChi2Var(" << GetName() << ") INFINITY ERROR: data point " << i 
00411                   << " has zero error, but function is not zero (f=" << yfunc << ")" << endl ;
00412       return 0 ;
00413     }
00414 
00415     // Add chi2 term
00416     result += eExt*eExt/(eInt*eInt+ eIntX2) ;
00417   }
00418 
00419   return result ;
00420 }
00421 
00422 
00423 
00424 RooArgSet RooXYChi2Var::requiredExtraObservables() const 
00425 {
00426   // Inform base class that observable yvar cannot be optimized away from the dataset
00427   if (_yvar) return RooArgSet(*_yvar) ;
00428   return RooArgSet() ;
00429 }
00430 
00431 
00432 

Generated on Tue Jul 5 15:07:45 2011 for ROOT_528-00b_version by  doxygen 1.5.1