/***************************************************************************** * Project: RooFit * * Package: RooFitCore * * @(#)root/roofitcore:$Id$ * Authors: * * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu * * DK, David Kirkby, UC Irvine, dkirkby@uci.edu * * * * Copyright (c) 2000-2005, Regents of the University of California * * and Stanford University. All rights reserved. * * * * Redistribution and use in source and binary forms, * * with or without modification, are permitted according to the terms * * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * *****************************************************************************/ ////////////////////////////////////////////////////////////////////////////// // // BEGIN_HTML // RooBinIntegrator implements an adaptive one-dimensional // numerical integration algorithm. // END_HTML // #include "RooFit.h" #include "Riostream.h" #include "TClass.h" #include "RooBinIntegrator.h" #include "RooArgSet.h" #include "RooRealVar.h" #include "RooNumber.h" #include "RooIntegratorBinding.h" #include "RooNumIntConfig.h" #include "RooNumIntFactory.h" #include "RooMsgService.h" #include using namespace std; ClassImp(RooBinIntegrator) ; // Register this class with RooNumIntConfig //_____________________________________________________________________________ void RooBinIntegrator::registerIntegrator(RooNumIntFactory& fact) { // Register RooBinIntegrator, is parameters and capabilities with RooNumIntFactory RooRealVar numBins("numBins","Number of bins in range",100) ; RooBinIntegrator* proto = new RooBinIntegrator() ; fact.storeProtoIntegrator(proto,RooArgSet(numBins)) ; RooNumIntConfig::defaultConfig().method1D().setLabel(proto->IsA()->GetName()) ; } //_____________________________________________________________________________ RooBinIntegrator::RooBinIntegrator() : _numBins(0), _useIntegrandLimits(kFALSE), _x(0) { // Default constructor } //_____________________________________________________________________________ RooBinIntegrator::RooBinIntegrator(const RooAbsFunc& function) : RooAbsIntegrator(function) { // Construct integrator on given function binding binding _useIntegrandLimits= kTRUE; assert(0 != integrand() && integrand()->isValid()); // Allocate coordinate buffer size after number of function dimensions _x = new Double_t[_function->getDimension()] ; _numBins = 100 ; _xmin.resize(_function->getDimension()) ; _xmax.resize(_function->getDimension()) ; for (UInt_t i=0 ; i<_function->getDimension() ; i++) { _xmin[i]= integrand()->getMinLimit(i); _xmax[i]= integrand()->getMaxLimit(i); // Retrieve bin configuration from integrand list* tmp = integrand()->binBoundaries(i) ; if (!tmp) { oocoutW((TObject*)0,Integration) << "RooBinIntegrator::RooBinIntegrator WARNING: integrand provide no binning definition observable #" << i << " substituting default binning of " << _numBins << " bins" << endl ; tmp = new list ; for (Int_t j=0 ; j<=_numBins ; j++) { tmp->push_back(_xmin[i]+j*(_xmax[i]-_xmin[i])/_numBins) ; } } _binb.push_back(tmp) ; } checkLimits(); } //_____________________________________________________________________________ RooBinIntegrator::RooBinIntegrator(const RooAbsFunc& function, const RooNumIntConfig& config) : RooAbsIntegrator(function), _binb(0) { // Construct integrator on given function binding binding const RooArgSet& configSet = config.getConfigSection(IsA()->GetName()) ; _useIntegrandLimits= kTRUE; _numBins = (Int_t) configSet.getRealValue("numBins") ; assert(0 != integrand() && integrand()->isValid()); // Allocate coordinate buffer size after number of function dimensions _x = new Double_t[_function->getDimension()] ; for (UInt_t i=0 ; i<_function->getDimension() ; i++) { _xmin.push_back(integrand()->getMinLimit(i)); _xmax.push_back(integrand()->getMaxLimit(i)); // Retrieve bin configuration from integrand list* tmp = integrand()->binBoundaries(i) ; if (!tmp) { oocoutW((TObject*)0,Integration) << "RooBinIntegrator::RooBinIntegrator WARNING: integrand provide no binning definition observable #" << i << " substituting default binning of " << _numBins << " bins" << endl ; tmp = new list ; for (Int_t j=0 ; j<=_numBins ; j++) { tmp->push_back(_xmin[i]+j*(_xmax[i]-_xmin[i])/_numBins) ; } } _binb.push_back(tmp) ; } checkLimits(); } //_____________________________________________________________________________ RooAbsIntegrator* RooBinIntegrator::clone(const RooAbsFunc& function, const RooNumIntConfig& config) const { // Clone integrator with new function binding and configuration. Needed by RooNumIntFactory return new RooBinIntegrator(function,config) ; } //_____________________________________________________________________________ RooBinIntegrator::~RooBinIntegrator() { // Destructor if(_x) delete[] _x; for (vector*>::iterator iter = _binb.begin() ; iter!=_binb.end() ; ++iter) { delete (*iter) ; } } //_____________________________________________________________________________ Bool_t RooBinIntegrator::setLimits(Double_t *xmin, Double_t *xmax) { // Change our integration limits. Return kTRUE if the new limits are // ok, or otherwise kFALSE. Always returns kFALSE and does nothing // if this object was constructed to always use our integrand's limits. if(_useIntegrandLimits) { oocoutE((TObject*)0,Integration) << "RooBinIntegrator::setLimits: cannot override integrand's limits" << endl; return kFALSE; } _xmin[0]= *xmin; _xmax[0]= *xmax; return checkLimits(); } //_____________________________________________________________________________ Bool_t RooBinIntegrator::checkLimits() const { // Check that our integration range is finite and otherwise return kFALSE. // Update the limits from the integrand if requested. if(_useIntegrandLimits) { assert(0 != integrand() && integrand()->isValid()); _xmin.resize(_function->getDimension()) ; _xmax.resize(_function->getDimension()) ; for (UInt_t i=0 ; i<_function->getDimension() ; i++) { _xmin[i]= integrand()->getMinLimit(i); _xmax[i]= integrand()->getMaxLimit(i); } } for (UInt_t i=0 ; i<_function->getDimension() ; i++) { if (_xmax[i]<=_xmin[i]) { oocoutE((TObject*)0,Integration) << "RooBinIntegrator::checkLimits: bad range with min >= max (_xmin = " << _xmin[i] << " _xmax = " << _xmax[i] << ")" << endl; return kFALSE; } if (RooNumber::isInfinite(_xmin[i]) || RooNumber::isInfinite(_xmax[i])) { return kFALSE ; } } return kTRUE; } //_____________________________________________________________________________ Double_t RooBinIntegrator::integral(const Double_t *) { // Calculate numeric integral at given set of function binding parameters assert(isValid()); double sum = 0. ; if (_function->getDimension()==1) { list::iterator iter = _binb[0]->begin() ; Double_t xlo = *iter ; iter++ ; for (; iter!=_binb[0]->end() ; ++iter) { Double_t xhi = *iter ; Double_t xcenter = (xhi+xlo)/2 ; Double_t binInt = integrand(xvec(xcenter))*(xhi-xlo) ; //cout << "RBI::integral 1D binInt[" << xcenter << "] = " << binInt << endl ; sum += binInt ; xlo=xhi ; } } if (_function->getDimension()==2) { list::iterator iter1 = _binb[0]->begin() ; Double_t x1lo = *iter1 ; iter1++ ; for (; iter1!=_binb[0]->end() ; ++iter1) { Double_t x1hi = *iter1 ; Double_t x1center = (x1hi+x1lo)/2 ; list::iterator iter2 = _binb[1]->begin() ; Double_t x2lo = *iter2 ; iter2++ ; for (; iter2!=_binb[1]->end() ; ++iter2) { Double_t x2hi = *iter2 ; Double_t x2center = (x2hi+x2lo)/2 ; Double_t binInt = integrand(xvec(x1center,x2center))*(x1hi-x1lo)*(x2hi-x2lo) ; //cout << "RBI::integral 2D binInt[" << x1center << "," << x2center << "] = " << binInt << " binv = " << (x1hi-x1lo) << "*" << (x2hi-x2lo) << endl ; sum += binInt ; x2lo=x2hi ; } x1lo=x1hi ; } } if (_function->getDimension()==3) { list::iterator iter1 = _binb[0]->begin() ; Double_t x1lo = *iter1 ; iter1++ ; for (; iter1!=_binb[0]->end() ; ++iter1) { Double_t x1hi = *iter1 ; Double_t x1center = (x1hi+x1lo)/2 ; list::iterator iter2 = _binb[1]->begin() ; Double_t x2lo = *iter2 ; iter2++ ; for (; iter2!=_binb[1]->end() ; ++iter2) { Double_t x2hi = *iter2 ; Double_t x2center = (x2hi+x2lo)/2 ; list::iterator iter3 = _binb[2]->begin() ; Double_t x3lo = *iter3 ; iter3++ ; for (; iter3!=_binb[2]->end() ; ++iter3) { Double_t x3hi = *iter3 ; Double_t x3center = (x3hi+x3lo)/2 ; Double_t binInt = integrand(xvec(x1center,x2center,x3center))*(x1hi-x1lo)*(x2hi-x2lo)*(x3hi-x3lo) ; //cout << "RBI::integral 3D binInt[" << x1center << "," << x2center << "," << x3center << "] = " << binInt << endl ; sum += binInt ; x3lo=x3hi ; } x2lo=x2hi ; } x1lo=x1hi ; } } return sum; }