66 ClassImp(RooAbsOptTestStatistic);
 
   73 RooAbsOptTestStatistic:: RooAbsOptTestStatistic()
 
  109 RooAbsOptTestStatistic::RooAbsOptTestStatistic(
const char *name, 
const char *title, RooAbsReal& real, RooAbsData& indata,
 
  110                       const RooArgSet& projDeps, 
const char* rangeName, 
const char* addCoefRangeName,
 
  111                       Int_t nCPU, RooFit::MPSplit interleave, Bool_t verbose, Bool_t splitCutRange, Bool_t ) : 
 
  112   RooAbsTestStatistic(name,title,real,indata,projDeps,rangeName, addCoefRangeName, nCPU, interleave, verbose, splitCutRange),
 
  119   if (operMode()!=Slave) {
 
  136   initSlave(real,indata,projDeps,rangeName,addCoefRangeName) ;
 
  142 RooAbsOptTestStatistic::RooAbsOptTestStatistic(
const RooAbsOptTestStatistic& other, 
const char* name) : 
 
  143   RooAbsTestStatistic(other,name), _sealed(other._sealed), _sealNotice(other._sealNotice), _optimized(kFALSE)
 
  146   if (operMode()!=Slave) {    
 
  151     _normSet = other._normSet ? ((RooArgSet*) other._normSet->snapshot()) : 0 ;   
 
  164   initSlave(*other._funcClone,*other._dataClone,other._projDeps?*other._projDeps:RooArgSet(),other._rangeName.c_str(),other._addCoefRangeName.c_str()) ;
 
  171 void RooAbsOptTestStatistic::initSlave(RooAbsReal& real, RooAbsData& indata, 
const RooArgSet& projDeps, 
const char* rangeName, 
 
  172                    const char* addCoefRangeName) 
 
  174   RooArgSet obs(*indata.get()) ;
 
  175   obs.remove(projDeps,kTRUE,kTRUE) ;
 
  183   _funcClone = (RooAbsReal*) real.cloneTree() ;
 
  187   _funcObsSet = _funcClone->getObservables(indata) ;
 
  189   if (_funcClone->getAttribute(
"BinnedLikelihood")) {
 
  190     _funcClone->setAttribute(
"BinnedLikelihoodActive") ;
 
  194   RooArgSet* origParams = (RooArgSet*) real.getParameters(indata) ;
 
  195   _funcClone->recursiveRedirectServers(*origParams) ;
 
  198   if (projDeps.getSize()>0) {
 
  199     RooArgSet *projDataDeps = (RooArgSet*) _funcObsSet->selectCommon(projDeps) ;
 
  200     projDataDeps->setAttribAll(
"projectedDependent") ;
 
  201     delete projDataDeps ;    
 
  208   RooProdPdf* pdfWithCons = 
dynamic_cast<RooProdPdf*
>(_funcClone) ;
 
  211     RooArgSet* connPars = pdfWithCons->getConnectedParameters(*indata.get()) ;
 
  213     _paramSet.removeAll() ;
 
  214     _paramSet.add(*connPars) ;
 
  219     _paramSet.add(*origParams) ;
 
  226   _normSet = (RooArgSet*) indata.get()->snapshot(kFALSE) ;
 
  230   for (std::size_t i = 0; i < _funcObsSet->size(); ++i) {
 
  231     auto realDepRLV = 
dynamic_cast<const RooAbsRealLValue*
>((*_funcObsSet)[i]);
 
  232     if (realDepRLV && realDepRLV->isDerived()) {
 
  234       realDepRLV->leafNodeServerList(&tmp2, 0, kTRUE);
 
  235       _funcObsSet->add(tmp2,kTRUE);
 
  246   const RooArgSet* dataDepSet = indata.get() ;
 
  247   for (
const auto arg : *_funcObsSet) {
 
  250     RooRealVar* realReal = 
dynamic_cast<RooRealVar*
>(arg) ;
 
  251     if (!realReal) continue ;
 
  252     RooRealVar* datReal = 
dynamic_cast<RooRealVar*
>(dataDepSet->find(realReal->GetName())) ;
 
  253     if (!datReal) continue ;
 
  257    if (!realReal->getBinning().lowBoundFunc() && realReal->getMin()<(datReal->getMin()-1e-6)) {
 
  258       coutE(InputArguments) << 
"RooAbsOptTestStatistic: ERROR minimum of FUNC observable " << arg->GetName() 
 
  259              << 
"(" << realReal->getMin() << 
") is smaller than that of "  
  260              << arg->GetName() << 
" in the dataset (" << datReal->getMin() << 
")" << endl ;
 
  261       RooErrorHandler::softAbort() ;
 
  265     if (!realReal->getBinning().highBoundFunc() && realReal->getMax()>(datReal->getMax()+1e-6)) {
 
  266       coutE(InputArguments) << 
"RooAbsOptTestStatistic: ERROR maximum of FUNC observable " << arg->GetName() 
 
  267              << 
" is larger than that of " << arg->GetName() << 
" in the dataset" << endl ;
 
  268       RooErrorHandler::softAbort() ;
 
  275   if (rangeName && strlen(rangeName)) {
 
  276     _dataClone = ((RooAbsData&)indata).reduce(RooFit::SelectVars(*_funcObsSet),RooFit::CutRange(rangeName)) ;  
 
  279     _dataClone = (RooAbsData*) indata.Clone() ;
 
  288   RooArgSet* origObsSet = real.getObservables(indata) ;
 
  289   RooArgSet* dataObsSet = (RooArgSet*) _dataClone->get() ;
 
  290   if (rangeName && strlen(rangeName)) {    
 
  291     cxcoutI(Fitting) << 
"RooAbsOptTestStatistic::ctor(" << GetName() << 
") constructing test statistic for sub-range named " << rangeName << endl ;    
 
  295     for (
const auto arg : *_funcObsSet) {
 
  297       RooRealVar* realObs = 
dynamic_cast<RooRealVar*
>(arg) ;
 
  301         if (!(addCoefRangeName && strlen(addCoefRangeName))) {
 
  302      realObs->setRange(Form(
"NormalizationRangeFor%s",rangeName),realObs->getMin(),realObs->getMax()) ;
 
  308    realObs->setRange(realObs->getMin(rangeName),realObs->getMax(rangeName)) ; 
 
  313    RooRealVar* dataObs = (RooRealVar*) dataObsSet->find(realObs->GetName()) ;
 
  314    dataObs->setRange(realObs->getMin(rangeName),realObs->getMax(rangeName)) ; 
 
  318      const char* origAttrib = real.getStringAttribute(
"fitrange") ;    
 
  320        real.setStringAttribute(
"fitrange",Form(
"%s,fit_%s",origAttrib,GetName())) ;
 
  322        real.setStringAttribute(
"fitrange",Form(
"fit_%s",GetName())) ;
 
  324      RooRealVar* origObs = (RooRealVar*) origObsSet->find(arg->GetName()) ;
 
  326        origObs->setRange(Form(
"fit_%s",GetName()),realObs->getMin(rangeName),realObs->getMax(rangeName)) ;
 
  337   RooDataHist* tmph = 
dynamic_cast<RooDataHist*
>(_dataClone) ;
 
  339     tmph->cacheValidEntries() ;
 
  343   if (rangeName && strlen(rangeName)) {
 
  346     _funcClone->fixAddCoefNormalization(*_dataClone->get(),kFALSE) ;
 
  348     if (addCoefRangeName && strlen(addCoefRangeName)) {
 
  349       cxcoutI(Fitting) << 
"RooAbsOptTestStatistic::ctor(" << GetName() 
 
  350              << 
") fixing interpretation of coefficients of any RooAddPdf component to range " << addCoefRangeName << endl ;
 
  351       _funcClone->fixAddCoefRange(addCoefRangeName,kFALSE) ;
 
  353    cxcoutI(Fitting) << 
"RooAbsOptTestStatistic::ctor(" << GetName() 
 
  354           << 
") fixing interpretation of coefficients of any RooAddPdf to full domain of observables " << endl ;
 
  355    _funcClone->fixAddCoefRange(Form(
"NormalizationRangeFor%s",rangeName),kFALSE) ;
 
  361   _dataClone->attachBuffers(*_funcObsSet) ;
 
  362   setEventCount(_dataClone->numEntries()) ;
 
  372   if (projDeps.getSize()>0) {
 
  374     _projDeps = (RooArgSet*) projDeps.snapshot(kFALSE) ;
 
  377     _normSet->remove(*_projDeps,kTRUE,kTRUE) ;
 
  380     RooArgSet *projDataDeps = (RooArgSet*) _funcObsSet->selectCommon(*_projDeps) ;
 
  381     projDataDeps->setAttribAll(
"projectedDependent") ;
 
  382     delete projDataDeps ;    
 
  386   coutI(Optimization) << 
"RooAbsOptTestStatistic::ctor(" << GetName() << 
") optimizing internal clone of p.d.f for likelihood evaluation."  
  387          << 
"Lazy evaluation and associated change tracking will disabled for all nodes that depend on observables" << endl ;
 
  401   _funcClone->getVal(_normSet) ;
 
  418 RooAbsOptTestStatistic::~RooAbsOptTestStatistic()
 
  420   if (operMode()==Slave) {
 
  440 Double_t RooAbsOptTestStatistic::combinedValue(RooAbsReal** array, Int_t n)
 const 
  443   Double_t sum(0), carry(0);
 
  444   for (Int_t i = 0; i < n; ++i) {
 
  445     Double_t y = array[i]->getValV();
 
  446     carry += 
reinterpret_cast<RooAbsOptTestStatistic*
>(array[i])->getCarry();
 
  448     const Double_t t = sum + y;
 
  449     carry = (t - sum) - y;
 
  461 Bool_t RooAbsOptTestStatistic::redirectServersHook(
const RooAbsCollection& newServerList, Bool_t mustReplaceAll, Bool_t nameChange, Bool_t isRecursive) 
 
  463   RooAbsTestStatistic::redirectServersHook(newServerList,mustReplaceAll,nameChange,isRecursive) ;
 
  464   if (operMode()!=Slave) 
return kFALSE ;  
 
  465   Bool_t ret = _funcClone->recursiveRedirectServers(newServerList,kFALSE,nameChange) ;
 
  474 void RooAbsOptTestStatistic::printCompactTreeHook(ostream& os, 
const char* indent) 
 
  476   RooAbsTestStatistic::printCompactTreeHook(os,indent) ;
 
  477   if (operMode()!=Slave) return ;
 
  478   TString indent2(indent) ;
 
  479   indent2 += 
"opt >>" ;
 
  480   _funcClone->printCompactTree(os,indent2.Data()) ;
 
  481   os << indent2 << 
" dataset clone = " << _dataClone << 
" first obs = " << _dataClone->get()->first() << endl ;
 
  493 void RooAbsOptTestStatistic::constOptimizeTestStatistic(ConstOpCode opcode, Bool_t doAlsoTrackingOpt) 
 
  498   RooAbsTestStatistic::constOptimizeTestStatistic(opcode,doAlsoTrackingOpt);
 
  499   if (operMode()!=Slave) return ;
 
  501   if (_dataClone->hasFilledCache() && _dataClone->store()->cacheOwner()!=
this) {
 
  502     if (opcode==Activate) {
 
  503       cxcoutW(Optimization) << 
"RooAbsOptTestStatistic::constOptimize(" << GetName() 
 
  504              << 
") dataset cache is owned by another object, no constant term optimization can be applied" << endl ;
 
  509   if (!allowFunctionCache()) {
 
  510     if (opcode==Activate) {
 
  511       cxcoutI(Optimization) << 
"RooAbsOptTestStatistic::constOptimize(" << GetName() 
 
  512              << 
") function caching prohibited by test statistic, no constant term optimization is applied" << endl ;
 
  517   if (_dataClone->hasFilledCache() && opcode==Activate) {
 
  523     cxcoutI(Optimization) << 
"RooAbsOptTestStatistic::constOptimize(" << GetName() 
 
  524            << 
") optimizing evaluation of test statistic by finding all nodes in p.d.f that depend exclusively" 
  525            << 
" on observables and constant parameters and precalculating their values" << endl ;
 
  526     optimizeConstantTerms(kTRUE,doAlsoTrackingOpt) ;
 
  530     cxcoutI(Optimization) << 
"RooAbsOptTestStatistic::constOptimize(" << GetName() 
 
  531            << 
") deactivating optimization of constant terms in test statistic" << endl ;
 
  532     optimizeConstantTerms(kFALSE) ;
 
  536     cxcoutI(Optimization) << 
"RooAbsOptTestStatistic::constOptimize(" << GetName() 
 
  537            << 
") one ore more parameter were changed from constant to floating or vice versa, " 
  538            << 
"re-evaluating constant term optimization" << endl ;
 
  539     optimizeConstantTerms(kFALSE) ;
 
  540     optimizeConstantTerms(kTRUE,doAlsoTrackingOpt) ;
 
  544     cxcoutI(Optimization) << 
"RooAbsOptTestStatistic::constOptimize(" << GetName() 
 
  545            << 
") the value of one ore more constant parameter were changed re-evaluating constant term optimization" << endl ;
 
  547     _dataClone->store()->forceCacheUpdate() ;
 
  567 void RooAbsOptTestStatistic::optimizeCaching() 
 
  573   _funcClone->getVal(_normSet) ;
 
  576   _funcClone->optimizeCacheMode(*_funcObsSet) ;
 
  579   _dataClone->setDirtyProp(kFALSE) ;  
 
  582   _dataClone->optimizeReadingWithCaching(*_funcClone, RooArgSet(),requiredExtraObservables()) ;
 
  596 void RooAbsOptTestStatistic::optimizeConstantTerms(Bool_t activate, Bool_t applyTrackingOpt)
 
  606     _funcClone->getVal(_normSet) ;
 
  612     RooArgSet trackNodes ;
 
  617     if (applyTrackingOpt) {
 
  618       if (!dynamic_cast<RooVectorDataStore*>(_dataClone->store())) {
 
  619         coutW(Optimization) << 
"RooAbsOptTestStatistic::optimizeConstantTerms(" << GetName()
 
  620                      << 
") WARNING Cache-and-track optimization (Optimize level 2) is only available for datasets" 
  621                      << 
" implement in terms of RooVectorDataStore - ignoring this option for current dataset" << endl ;
 
  622         applyTrackingOpt = kFALSE ;
 
  626     if (applyTrackingOpt) {
 
  628       _funcClone->branchNodeServerList(&branches) ;
 
  629       for (
auto arg : branches) {
 
  630         arg->setCacheAndTrackHints(trackNodes);
 
  633       RooArgSet* constNodes = (RooArgSet*) trackNodes.selectByAttrib(
"Constant",kTRUE) ;
 
  634       trackNodes.remove(*constNodes) ;
 
  638       trackNodes.setAttribAll(
"CacheAndTrack",kTRUE) ;
 
  642     _cachedNodes.removeAll() ;
 
  644     _funcClone->findConstantNodes(*_dataClone->get(),_cachedNodes) ;
 
  651     _dataClone->cacheArgs(
this,_cachedNodes,_normSet,!_funcClone->getAttribute(
"BinnedLikelihood")) ;  
 
  658     for (
auto cacheArg : _cachedNodes) {
 
  659       cacheArg->setOperMode(RooAbsArg::AClean) ;
 
  670     RooArgSet* constNodes = (RooArgSet*) _cachedNodes.selectByAttrib(
"ConstantExpressionCached",kTRUE) ;
 
  671     RooArgSet actualTrackNodes(_cachedNodes) ;
 
  672     actualTrackNodes.remove(*constNodes) ;
 
  673     if (constNodes->getSize()>0) {
 
  674       if (constNodes->getSize()<20) {
 
  675         coutI(Minimization) << 
" The following expressions have been identified as constant and will be precalculated and cached: " << *constNodes << endl ;
 
  677         coutI(Minimization) << 
" A total of " << constNodes->getSize() << 
" expressions have been identified as constant and will be precalculated and cached." << endl ;
 
  685     if (actualTrackNodes.getSize()>0) {
 
  686       if (actualTrackNodes.getSize()<20) {
 
  687         coutI(Minimization) << 
" The following expressions will be evaluated in cache-and-track mode: " << actualTrackNodes << endl ;
 
  689         coutI(Minimization) << 
" A total of " << constNodes->getSize() << 
" expressions will be evaluated in cache-and-track-mode." << endl ;
 
  695     _dataClone->optimizeReadingWithCaching(*_funcClone, _cachedNodes,requiredExtraObservables()) ;
 
  702     _dataClone->resetCache() ;
 
  705     _dataClone->setArgStatus(*_dataClone->get(),kTRUE) ;
 
  711     _dataClone->setDirtyProp(kFALSE) ;  
 
  713     _cachedNodes.removeAll() ;
 
  716     _optimized = kFALSE ;
 
  729 Bool_t RooAbsOptTestStatistic::setDataSlave(RooAbsData& indata, Bool_t cloneData, Bool_t ownNewData) 
 
  732   if (operMode()==SimMaster) {
 
  747   if (!cloneData && _rangeName.size()>0) {
 
  748     coutW(InputArguments) << 
"RooAbsOptTestStatistic::setData(" << GetName() << 
") WARNING: test statistic was constructed with range selection on data, " 
  749           << 
"ignoring request to _not_ clone the input dataset" << endl ; 
 
  755     if (_rangeName.size()==0) {
 
  756       _dataClone = (RooAbsData*) indata.reduce(*indata.get()) ;
 
  758       _dataClone = ((RooAbsData&)indata).reduce(RooFit::SelectVars(*indata.get()),RooFit::CutRange(_rangeName.c_str())) ;  
 
  765     _dataClone = &indata ;
 
  766     _ownData = ownNewData ;
 
  771   _dataClone->attachBuffers(*_funcObsSet) ;
 
  772   _dataClone->setDirtyProp(kFALSE) ;  
 
  776   if (_cachedNodes.getSize()>0) {
 
  777     _dataClone->cacheArgs(
this,_cachedNodes,_normSet) ;      
 
  781   setEventCount(indata.numEntries()) ;
 
  795 RooAbsData& RooAbsOptTestStatistic::data() 
 
  798     Bool_t notice = (sealNotice() && strlen(sealNotice())) ;
 
  799     coutW(ObjectHandling) << 
"RooAbsOptTestStatistic::data(" << GetName() 
 
  800            << 
") WARNING: object sealed by creator - access to data is not permitted: "  
  801            << (notice?sealNotice():
"<no user notice>") << endl ;
 
  802     static RooDataSet dummy (
"dummy",
"dummy",RooArgSet()) ;
 
  811 const RooAbsData& RooAbsOptTestStatistic::data()
 const  
  814     Bool_t notice = (sealNotice() && strlen(sealNotice())) ;
 
  815     coutW(ObjectHandling) << 
"RooAbsOptTestStatistic::data(" << GetName() 
 
  816            << 
") WARNING: object sealed by creator - access to data is not permitted: "  
  817            << (notice?sealNotice():
"<no user notice>") << endl ;
 
  818     static RooDataSet dummy (
"dummy",
"dummy",RooArgSet()) ;