// RooAbsOptTestStatistic is the abstract base class for test
// statistics objects that evaluate a function or PDF at each point of a given
// dataset. This class provides generic optimizations, such as
// caching and precalculation of constant terms that can be made for
// all such quantities
//
// Implementations should define evaluatePartition(), which calculates the
// value of a (sub)range of the dataset and optionally combinedValue(),
// which combines the values calculated for each partition. If combinedValue()
// is not overloaded, the default implementation will add the partition results
// to obtain the combined result
//
// Support for calculation in partitions is needed to allow multi-core
// parallelized calculation of test statistics
// END_HTML
#include "RooFit.h"
#include "Riostream.h"
#include <string.h>
#include "RooAbsOptTestStatistic.h"
#include "RooMsgService.h"
#include "RooAbsPdf.h"
#include "RooAbsData.h"
#include "RooArgSet.h"
#include "RooRealVar.h"
#include "RooErrorHandler.h"
#include "RooGlobalFunc.h"
#include "RooBinning.h"
ClassImp(RooAbsOptTestStatistic)
;
RooAbsOptTestStatistic:: RooAbsOptTestStatistic()
{
_normSet = 0 ;
_funcCloneSet = 0 ;
_dataClone = 0 ;
_funcClone = 0 ;
_projDeps = 0 ;
}
RooAbsOptTestStatistic::RooAbsOptTestStatistic(const char *name, const char *title, RooAbsReal& real, RooAbsData& data,
const RooArgSet& projDeps, const char* rangeName, const char* addCoefRangeName,
Int_t nCPU, Bool_t interleave, Bool_t verbose, Bool_t splitCutRange) :
RooAbsTestStatistic(name,title,real,data,projDeps,rangeName, addCoefRangeName, nCPU, interleave, verbose, splitCutRange),
_projDeps(0)
{
if (operMode()!=Slave) {
_normSet = 0 ;
return ;
}
RooArgSet obs(*data.get()) ;
obs.remove(projDeps,kTRUE,kTRUE) ;
if (real.recursiveCheckObservables(&obs)) {
coutE(InputArguments) << "RooAbsOptTestStatistic: ERROR in FUNC dependents, abort" << endl ;
RooErrorHandler::softAbort() ;
return ;
}
RooArgSet* realDepSet = real.getObservables(&data) ;
TIterator* iter9 = realDepSet->createIterator() ;
RooAbsArg* realDep ;
while((realDep=(RooAbsArg*)iter9->Next())) {
RooAbsRealLValue* realDepRLV = dynamic_cast<RooAbsRealLValue*>(realDep) ;
if (realDepRLV && realDepRLV->isDerived()) {
RooArgSet tmp ;
realDepRLV->leafNodeServerList(&tmp, 0, kTRUE) ;
realDepSet->add(tmp,kTRUE) ;
}
}
delete iter9 ;
const RooArgSet* dataDepSet = data.get() ;
TIterator* iter = realDepSet->createIterator() ;
RooAbsArg* arg ;
while((arg=(RooAbsArg*)iter->Next())) {
RooRealVar* realReal = dynamic_cast<RooRealVar*>(arg) ;
if (!realReal) continue ;
RooRealVar* datReal = dynamic_cast<RooRealVar*>(dataDepSet->find(realReal->GetName())) ;
if (!datReal) continue ;
if (!realReal->getBinning().lowBoundFunc() && realReal->getMin()<(datReal->getMin()-1e-6)) {
coutE(InputArguments) << "RooAbsOptTestStatistic: ERROR minimum of FUNC observable " << arg->GetName()
<< "(" << realReal->getMin() << ") is smaller than that of "
<< arg->GetName() << " in the dataset (" << datReal->getMin() << ")" << endl ;
RooErrorHandler::softAbort() ;
return ;
}
if (!realReal->getBinning().highBoundFunc() && realReal->getMax()>(datReal->getMax()+1e-6)) {
coutE(InputArguments) << "RooAbsOptTestStatistic: ERROR maximum of FUNC observable " << arg->GetName()
<< " is larger than that of " << arg->GetName() << " in the dataset" << endl ;
RooErrorHandler::softAbort() ;
return ;
}
}
if (rangeName && strlen(rangeName)) {
_dataClone = ((RooAbsData&)data).reduce(RooFit::SelectVars(*realDepSet),RooFit::CutRange(rangeName)) ;
} else {
_dataClone = ((RooAbsData&)data).reduce(RooFit::SelectVars(*realDepSet)) ;
}
iter9 = realDepSet->createIterator() ;
while((realDep=(RooAbsRealLValue*)iter9->Next())) {
RooAbsRealLValue* realDepRLV = dynamic_cast<RooAbsRealLValue*>(realDep) ;
if (realDepRLV && !realDepRLV->getBinning().isShareable()) {
RooRealVar* datReal = dynamic_cast<RooRealVar*>(_dataClone->get()->find(realDepRLV->GetName())) ;
datReal->setBinning(realDepRLV->getBinning()) ;
datReal->attachDataSet(*_dataClone) ;
}
}
delete iter9 ;
if (rangeName && strlen(rangeName)) {
cxcoutI(Fitting) << "RooAbsOptTestStatistic::ctor(" << GetName() << ") constructing test statistic for sub-range named " << rangeName << endl ;
TIterator* iter2 = _dataClone->get()->createIterator() ;
while((arg=(RooAbsArg*)iter2->Next())) {
RooRealVar* realReal = dynamic_cast<RooRealVar*>(arg) ;
if (realReal) {
if (!(addCoefRangeName && strlen(addCoefRangeName))) {
realReal->setRange(Form("NormalizationRangeFor%s",rangeName),realReal->getMin(),realReal->getMax()) ;
}
realReal->setRange(realReal->getMin(rangeName),realReal->getMax(rangeName)) ;
}
}
RooDataHist* tmp = dynamic_cast<RooDataHist*>(_dataClone) ;
if (tmp) {
tmp->cacheValidEntries() ;
}
if (!_splitRange) {
iter->Reset() ;
while((arg=(RooAbsArg*)iter->Next())) {
RooRealVar* realReal = dynamic_cast<RooRealVar*>(arg) ;
if (realReal) {
realReal->setStringAttribute("fitrange",Form("fit_%s",GetName())) ;
realReal->setRange(Form("fit_%s",GetName()),realReal->getMin(rangeName),realReal->getMax(rangeName)) ;
const char* origAttrib = real.getStringAttribute("fitrange") ;
if (origAttrib) {
real.setStringAttribute("fitrange",Form("%s,fit_%s",origAttrib,GetName())) ;
} else {
real.setStringAttribute("fitrange",Form("fit_%s",GetName())) ;
}
}
}
}
delete iter2 ;
}
delete iter ;
setEventCount(_dataClone->numEntries()) ;
RooArgSet tmp("RealBranchNodeList") ;
real.branchNodeServerList(&tmp) ;
_funcCloneSet = (RooArgSet*) tmp.snapshot(kFALSE) ;
_funcClone = (RooAbsReal*) _funcCloneSet->find(real.GetName()) ;
if (rangeName && strlen(rangeName)) {
_funcClone->fixAddCoefNormalization(*_dataClone->get()) ;
if (addCoefRangeName && strlen(addCoefRangeName)) {
cxcoutI(Fitting) << "RooAbsOptTestStatistic::ctor(" << GetName()
<< ") fixing interpretation of coefficients of any RooAddPdf component to range " << addCoefRangeName << endl ;
_funcClone->fixAddCoefRange(addCoefRangeName,kFALSE) ;
} else {
cxcoutI(Fitting) << "RooAbsOptTestStatistic::ctor(" << GetName()
<< ") fixing interpretation of coefficients of any RooAddPdf to full domain of observables " << endl ;
_funcClone->fixAddCoefRange(Form("NormalizationRangeFor%s",rangeName),kFALSE) ;
}
}
_funcClone->attachDataSet(*_dataClone) ;
_normSet = (RooArgSet*) data.get()->snapshot(kFALSE) ;
if (projDeps.getSize()>0) {
_projDeps = (RooArgSet*) projDeps.snapshot(kFALSE) ;
RooArgSet* tobedel = (RooArgSet*) _normSet->selectCommon(*_projDeps) ;
_normSet->remove(*_projDeps,kTRUE,kTRUE) ;
TIterator* ii = tobedel->createIterator() ;
RooAbsArg* aa ;
while((aa=(RooAbsArg*)ii->Next())) {
delete aa ;
}
delete ii ;
delete tobedel ;
RooArgSet *projDataDeps = (RooArgSet*) _dataClone->get()->selectCommon(*_projDeps) ;
projDataDeps->setAttribAll("projectedDependent") ;
delete projDataDeps ;
}
RooArgSet* params = _funcClone->getParameters(_dataClone) ;
_paramSet.add(*params) ;
delete params ;
if (_projDeps) {
RooArgSet *projDataDeps = (RooArgSet*) _dataClone->get()->selectCommon(*_projDeps) ;
projDataDeps->setAttribAll("projectedDependent") ;
delete projDataDeps ;
}
coutI(Optimization) << "RooAbsOptTestStatistic::ctor(" << GetName() << ") optimizing internal clone of p.d.f for likelihood evaluation."
<< "Lazy evaluation and associated change tracking will disabled for all nodes that depend on observables" << endl ;
optimizeCaching() ;
delete realDepSet ;
}
RooAbsOptTestStatistic::RooAbsOptTestStatistic(const RooAbsOptTestStatistic& other, const char* name) :
RooAbsTestStatistic(other,name)
{
if (operMode()!=Slave) {
_projDeps = 0 ;
_normSet = other._normSet ? ((RooArgSet*) other._normSet->snapshot()) : 0 ;
return ;
}
_funcCloneSet = (RooArgSet*) other._funcCloneSet->snapshot(kFALSE) ;
_funcClone = (RooAbsReal*) _funcCloneSet->find(other._funcClone->GetName()) ;
TIterator* iter = _funcCloneSet->createIterator() ;
RooAbsArg* branch ;
while((branch=(RooAbsArg*)iter->Next())) {
branch->setOperMode(other._funcCloneSet->find(branch->GetName())->operMode()) ;
}
delete iter ;
_dataClone = (RooAbsData*) other._dataClone->cacheClone(_funcCloneSet) ;
_funcClone->attachDataSet(*_dataClone) ;
_funcClone->recursiveRedirectServers(_paramSet) ;
_normSet = (RooArgSet*) other._normSet->snapshot() ;
if (other._projDeps) {
_projDeps = (RooArgSet*) other._projDeps->snapshot() ;
} else {
_projDeps = 0 ;
}
}
RooAbsOptTestStatistic::~RooAbsOptTestStatistic()
{
if (operMode()==Slave) {
delete _funcCloneSet ;
delete _dataClone ;
delete _projDeps ;
}
delete _normSet ;
}
Double_t RooAbsOptTestStatistic::combinedValue(RooAbsReal** array, Int_t n) const
{
Double_t sum(0) ;
Int_t i ;
for (i=0 ; i<n ; i++) {
Double_t tmp = array[i]->getVal() ;
if (tmp==0) return 0 ;
sum += tmp ;
}
return sum ;
}
Bool_t RooAbsOptTestStatistic::redirectServersHook(const RooAbsCollection& newServerList, Bool_t mustReplaceAll, Bool_t nameChange, Bool_t isRecursive)
{
RooAbsTestStatistic::redirectServersHook(newServerList,mustReplaceAll,nameChange,isRecursive) ;
if (operMode()!=Slave) return kFALSE ;
Bool_t ret = _funcClone->recursiveRedirectServers(newServerList,kFALSE,nameChange) ;
return ret ;
}
void RooAbsOptTestStatistic::printCompactTreeHook(ostream& os, const char* indent)
{
RooAbsTestStatistic::printCompactTreeHook(os,indent) ;
if (operMode()!=Slave) return ;
TString indent2(indent) ;
indent2 += "opt >>" ;
_funcClone->printCompactTree(os,indent2) ;
os << "opt >> " ; _dataClone->get()->printStream(os,kName|kAddress,kStandard) ;
}
void RooAbsOptTestStatistic::constOptimizeTestStatistic(ConstOpCode opcode)
{
RooAbsTestStatistic::constOptimizeTestStatistic(opcode);
if (operMode()!=Slave) return ;
switch(opcode) {
case Activate:
cxcoutI(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
<< ") optimizing evaluation of test statistic by finding all nodes in p.d.f that depend exclusively"
<< " on observables and constant parameters and precalculating their values" << endl ;
optimizeConstantTerms(kTRUE) ;
break ;
case DeActivate:
cxcoutI(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
<< ") deactivating optimization of constant terms in test statistic" << endl ;
optimizeConstantTerms(kFALSE) ;
break ;
case ConfigChange:
cxcoutI(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
<< ") one ore more parameter were changed from constant to floating or vice versa, "
<< "re-evaluating constant term optimization" << endl ;
optimizeConstantTerms(kFALSE) ;
optimizeConstantTerms(kTRUE) ;
break ;
case ValueChange:
cxcoutI(Optimization) << "RooAbsOptTestStatistic::constOptimize(" << GetName()
<< ") the value of one ore more constant parameter were changed re-evaluating constant term optimization" << endl ;
optimizeConstantTerms(kFALSE) ;
optimizeConstantTerms(kTRUE) ;
break ;
}
}
void RooAbsOptTestStatistic::optimizeCaching()
{
_funcClone->getVal(_normSet) ;
_funcClone->optimizeCacheMode(*_dataClone->get()) ;
_dataClone->setDirtyProp(kFALSE) ;
_dataClone->optimizeReadingWithCaching(*_funcClone, RooArgSet()) ;
}
void RooAbsOptTestStatistic::optimizeConstantTerms(Bool_t activate)
{
if(activate) {
_funcClone->getVal(_normSet) ;
RooArgSet cacheableNodes ;
_funcClone->findConstantNodes(*_dataClone->get(),cacheableNodes) ;
_dataClone->cacheArgs(cacheableNodes,_normSet) ;
TIterator* cIter = cacheableNodes.createIterator() ;
RooAbsArg *cacheArg ;
while((cacheArg=(RooAbsArg*)cIter->Next())){
cacheArg->setOperMode(RooAbsArg::AClean) ;
}
delete cIter ;
_dataClone->optimizeReadingWithCaching(*_funcClone, cacheableNodes) ;
} else {
_dataClone->resetCache() ;
_dataClone->setArgStatus(*_dataClone->get(),kTRUE) ;
optimizeCaching() ;
}
}
Last change: Fri Dec 12 09:05:54 2008
Last generated: 2008-12-12 09:05
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.