196 ClassImp(RooAbsPdf::GenSpec);
199 Int_t RooAbsPdf::_verboseEval = 0;
200 TString RooAbsPdf::_normRangeOverride ;
205 RooAbsPdf::RooAbsPdf() : _norm(0), _normSet(0), _specGeneratorConfig(0)
210 _selectComp = kFALSE ;
219 RooAbsPdf::RooAbsPdf(
const char *name,
const char *title) :
220 RooAbsReal(name,title), _norm(0), _normSet(0), _normMgr(this,10), _selectComp(kTRUE), _specGeneratorConfig(0)
222 resetErrorCounters() ;
231 RooAbsPdf::RooAbsPdf(
const char *name,
const char *title,
232 Double_t plotMin, Double_t plotMax) :
233 RooAbsReal(name,title,plotMin,plotMax), _norm(0), _normSet(0), _normMgr(this,10), _selectComp(kTRUE), _specGeneratorConfig(0)
235 resetErrorCounters() ;
244 RooAbsPdf::RooAbsPdf(
const RooAbsPdf& other,
const char* name) :
245 RooAbsReal(other,name), _norm(0), _normSet(0),
246 _normMgr(other._normMgr,this), _selectComp(other._selectComp), _normRange(other._normRange)
248 resetErrorCounters() ;
249 setTraceCounter(other._traceCount) ;
251 if (other._specGeneratorConfig) {
252 _specGeneratorConfig =
new RooNumGenConfig(*other._specGeneratorConfig) ;
254 _specGeneratorConfig = 0 ;
263 RooAbsPdf::~RooAbsPdf()
265 if (_specGeneratorConfig)
delete _specGeneratorConfig ;
281 Double_t RooAbsPdf::getValV(
const RooArgSet* nset)
const
286 RooArgSet* tmp = _normSet ;
288 Double_t val = evaluate() ;
290 Bool_t error = traceEvalPdf(val) ;
300 Bool_t nsetChanged(kFALSE) ;
301 if (nset!=_normSet || _norm==0) {
302 nsetChanged = syncNormalization(nset) ;
306 if (isValueDirty() || nsetChanged || _norm->isValueDirty()) {
309 Double_t rawVal = evaluate() ;
310 Bool_t error = traceEvalPdf(rawVal) ;
313 Double_t normVal(_norm->getVal()) ;
315 if (normVal < 0. || (normVal == 0. && rawVal != 0)) {
318 std::stringstream msg;
319 msg <<
"p.d.f normalization integral is zero or negative: " << normVal;
320 logEvalError(msg.str().c_str());
324 if (error || (rawVal == 0. && normVal == 0.)) {
327 _value = rawVal / normVal ;
330 clearValueAndShapeDirty();
348 RooSpan<const double> RooAbsPdf::getValBatch(std::size_t begin, std::size_t maxSize,
349 const RooArgSet* normSet)
const
354 if (_allBatchesDirty || _operMode == ADirty) {
355 _batchData.markDirty();
356 _allBatchesDirty =
false;
361 RooArgSet* tmp = _normSet ;
363 auto outputs = evaluateBatch(begin, maxSize);
364 maxSize = outputs.size();
367 _batchData.setStatus(begin, maxSize, BatchHelpers::BatchData::kReady);
374 Bool_t nsetChanged(kFALSE) ;
375 if (normSet != _normSet || _norm ==
nullptr) {
376 nsetChanged = syncNormalization(normSet) ;
380 if (_batchData.status(begin, maxSize) <= BatchHelpers::BatchData::kDirty
381 || nsetChanged || _norm->isValueDirty()) {
383 auto outputs = evaluateBatch(begin, maxSize);
384 maxSize = outputs.size();
387 const double normVal = _norm->getVal();
390 || (normVal == 0. && std::any_of(outputs.begin(), outputs.end(), [](
double val){
return val != 0;}))) {
391 logEvalError(Form(
"p.d.f normalization integral is zero or negative."
392 "\n\tInt(%s) = %f", GetName(), normVal));
395 if (normVal != 1. && normVal > 0.) {
396 const double invNorm = 1./normVal;
397 for (
double& val : outputs) {
402 _batchData.setStatus(begin, maxSize, BatchHelpers::BatchData::kReady);
405 const auto ret = _batchData.getBatch(begin, maxSize);
417 Double_t RooAbsPdf::analyticalIntegralWN(Int_t code,
const RooArgSet* normSet,
const char* rangeName)
const
419 cxcoutD(Eval) <<
"RooAbsPdf::analyticalIntegralWN(" << GetName() <<
") code = " << code <<
" normset = " << (normSet?*normSet:RooArgSet()) << endl ;
422 if (code==0)
return getVal(normSet) ;
424 return analyticalIntegral(code,rangeName) / getNorm(normSet) ;
426 return analyticalIntegral(code,rangeName) ;
437 Bool_t RooAbsPdf::traceEvalPdf(Double_t value)
const
440 Bool_t error(kFALSE) ;
441 if (TMath::IsNaN(value)) {
442 logEvalError(Form(
"p.d.f value is Not-a-Number (%f), forcing value to zero",value)) ;
446 logEvalError(Form(
"p.d.f value is less than zero (%f), forcing value to zero",value)) ;
451 if(!error)
return error ;
454 if(++_errorCount <= 10) {
455 cxcoutD(Tracing) <<
"*** Evaluation Error " << _errorCount <<
" ";
456 if(_errorCount == 10) cxcoutD(Tracing) <<
"(no more will be printed) ";
471 Double_t RooAbsPdf::getNorm(
const RooArgSet* nset)
const
473 if (!nset)
return 1 ;
475 syncNormalization(nset,kTRUE) ;
476 if (_verboseEval>1) cxcoutD(Tracing) << IsA()->GetName() <<
"::getNorm(" << GetName() <<
"): norm(" << _norm <<
") = " << _norm->getVal() << endl ;
478 Double_t ret = _norm->getVal() ;
480 if(++_errorCount <= 10) {
481 coutW(Eval) <<
"RooAbsPdf::getNorm(" << GetName() <<
":: WARNING normalization is zero, nset = " ; nset->Print(
"1") ;
482 if(_errorCount == 10) coutW(Eval) <<
"RooAbsPdf::getNorm(" << GetName() <<
") INFO: no more messages will be printed " << endl ;
495 const RooAbsReal* RooAbsPdf::getNormObj(
const RooArgSet* nset,
const RooArgSet* iset,
const TNamed* rangeName)
const
499 CacheElem* cache = (CacheElem*) _normMgr.getObj(nset,iset,0,rangeName) ;
501 return cache->_norm ;
505 RooArgSet* depList = getObservables(iset) ;
506 RooAbsReal* norm = createIntegral(*depList,*nset, *getIntegratorConfig(), RooNameReg::str(rangeName)) ;
510 cache =
new CacheElem(*norm) ;
511 _normMgr.setObj(nset,iset,cache,rangeName) ;
530 Bool_t RooAbsPdf::syncNormalization(
const RooArgSet* nset, Bool_t adjustProxies)
const
535 _normSet = (RooArgSet*) nset ;
538 CacheElem* cache = (CacheElem*) _normMgr.getObj(nset) ;
541 Bool_t nsetChanged = (_norm!=cache->_norm) ;
542 _norm = cache->_norm ;
547 if (nsetChanged && adjustProxies) {
549 ((RooAbsPdf*)
this)->setProxyNormSet(nset) ;
557 ((RooAbsPdf*)
this)->setProxyNormSet(nset) ;
560 std::unique_ptr<RooArgSet> depList(getObservables(nset));
562 if (_verboseEval>0) {
563 if (!selfNormalized()) {
564 cxcoutD(Tracing) << IsA()->GetName() <<
"::syncNormalization(" << GetName()
565 <<
") recreating normalization integral " << endl ;
566 if (depList) depList->printStream(ccoutD(Tracing),kName|kValue|kArgs,kSingleLine) ;
else ccoutD(Tracing) <<
"<none>" << endl ;
568 cxcoutD(Tracing) << IsA()->GetName() <<
"::syncNormalization(" << GetName() <<
") selfNormalized, creating unit norm" << endl;
573 if (selfNormalized() || !dependsOn(*depList)) {
574 TString ntitle(GetTitle()) ; ntitle.Append(
" Unit Normalization") ;
575 TString nname(GetName()) ; nname.Append(
"_UnitNorm") ;
576 _norm =
new RooRealVar(nname.Data(),ntitle.Data(),1) ;
578 const char* nr = (_normRangeOverride.Length()>0 ? _normRangeOverride.Data() : (_normRange.Length()>0 ? _normRange.Data() : 0)) ;
581 RooAbsReal* normInt = createIntegral(*depList,*getIntegratorConfig(),nr) ;
585 const char* cacheParamsStr = getStringAttribute(
"CACHEPARAMINT") ;
586 if (cacheParamsStr && strlen(cacheParamsStr)) {
588 RooArgSet* intParams = normInt->getVariables() ;
590 RooNameSet cacheParamNames ;
591 cacheParamNames.setNameList(cacheParamsStr) ;
592 RooArgSet* cacheParams = cacheParamNames.select(*intParams) ;
594 if (cacheParams->getSize()>0) {
595 cxcoutD(Caching) <<
"RooAbsReal::createIntObj(" << GetName() <<
") INFO: constructing " << cacheParams->getSize()
596 <<
"-dim value cache for integral over " << *depList <<
" as a function of " << *cacheParams <<
" in range " << (nr?nr:
"<default>") << endl ;
597 string name = Form(
"%s_CACHE_[%s]",normInt->GetName(),cacheParams->contentsString().c_str()) ;
598 RooCachedReal* cachedIntegral =
new RooCachedReal(name.c_str(),name.c_str(),*normInt,*cacheParams) ;
599 cachedIntegral->setInterpolationOrder(2) ;
600 cachedIntegral->addOwnedComponents(*normInt) ;
601 cachedIntegral->setCacheSource(kTRUE) ;
602 if (normInt->operMode()==ADirty) {
603 cachedIntegral->setOperMode(ADirty) ;
605 normInt= cachedIntegral ;
615 cache =
new CacheElem(*_norm) ;
616 _normMgr.setObj(nset,cache) ;
628 Bool_t RooAbsPdf::traceEvalHook(Double_t value)
const
633 Bool_t error= TMath::IsNaN(value) || (value < 0);
636 if(!error && _traceCount <= 0)
return error ;
639 if(error && ++_errorCount <= 10) {
640 cxcoutD(Tracing) <<
"*** Evaluation Error " << _errorCount <<
" ";
641 if(_errorCount == 10) ccoutD(Tracing) <<
"(no more will be printed) ";
643 else if(_traceCount > 0) {
644 ccoutD(Tracing) <<
'[' << _traceCount-- <<
"] ";
662 void RooAbsPdf::resetErrorCounters(Int_t resetValue)
664 _errorCount = resetValue ;
665 _negCount = resetValue ;
674 void RooAbsPdf::setTraceCounter(Int_t value, Bool_t allNodes)
677 _traceCount = value ;
680 RooArgList branchList ;
681 branchNodeServerList(&branchList) ;
682 TIterator* iter = branchList.createIterator() ;
684 while((arg=(RooAbsArg*)iter->Next())) {
685 RooAbsPdf* pdf =
dynamic_cast<RooAbsPdf*
>(arg) ;
686 if (pdf) pdf->setTraceCounter(value,kFALSE) ;
700 Double_t RooAbsPdf::getLogVal(
const RooArgSet* nset)
const
702 Double_t prob = getVal(nset) ;
704 if (fabs(prob)>1e6) {
705 coutW(Eval) <<
"RooAbsPdf::getLogVal(" << GetName() <<
") WARNING: large likelihood value: " << prob << endl ;
709 logEvalError(
"getLogVal() top-level p.d.f evaluates to a negative number") ;
711 return std::numeric_limits<double>::quiet_NaN();
715 logEvalError(
"getLogVal() top-level p.d.f evaluates to zero") ;
717 return -std::numeric_limits<double>::infinity();
720 if (TMath::IsNaN(prob)) {
721 logEvalError(
"getLogVal() top-level p.d.f evaluates to NaN") ;
723 return -std::numeric_limits<double>::infinity();
736 bool checkInfNaNNeg(
const T& inputs) {
742 for (
double val : inputs) {
743 inf |= !std::isfinite(val);
744 nan |= TMath::IsNaN(val);
748 return inf || nan || neg;
758 void RooAbsPdf::logBatchComputationErrors(RooSpan<const double>& outputs, std::size_t begin)
const {
759 for (
unsigned int i=0; i<outputs.size(); ++i) {
760 const double value = outputs[i];
761 if (TMath::IsNaN(outputs[i])) {
762 logEvalError(Form(
"p.d.f value of (%s) is Not-a-Number (%f) for entry %zu",
763 GetName(), value, begin+i));
764 }
else if (!std::isfinite(outputs[i])){
765 logEvalError(Form(
"p.d.f value of (%s) is (%f) for entry %zu",
766 GetName(), value, begin+i));
767 }
else if (outputs[i] < 0.) {
768 logEvalError(Form(
"p.d.f value of (%s) is less than zero (%f) for entry %zu",
769 GetName(), value, begin+i));
781 RooSpan<const double> RooAbsPdf::getLogValBatch(std::size_t begin, std::size_t maxSize,
782 const RooArgSet* normSet)
const
784 auto pdfValues = getValBatch(begin, maxSize, normSet);
786 if (checkInfNaNNeg(pdfValues)) {
787 logBatchComputationErrors(pdfValues, begin);
790 auto output = _batchData.makeWritableBatchUnInit(begin, pdfValues.size());
792 for (std::size_t i = 0; i < pdfValues.size(); ++i) {
793 const double prob = pdfValues[i];
795 double theLog = _rf_fast_log(prob);
798 theLog = std::numeric_limits<double>::quiet_NaN();
799 }
else if (prob == 0 || TMath::IsNaN(prob)) {
800 theLog = -std::numeric_limits<double>::infinity();
817 Double_t RooAbsPdf::extendedTerm(Double_t observed,
const RooArgSet* nset)
const
820 if(!canBeExtended()) {
821 coutE(InputArguments) << fName <<
": this PDF does not support extended maximum likelihood"
826 Double_t expected= expectedEvents(nset);
828 coutE(InputArguments) << fName <<
": calculated negative expected events: " << expected
835 if (fabs(expected)<1e-10 && fabs(observed)<1e-10) {
840 if (expected<0 || TMath::IsNaN(expected)) {
841 logEvalError(
"extendedTerm #expected events is <0 or NaN") ;
865 Double_t extra= expected - observed*log(expected);
869 Bool_t trace(kFALSE) ;
871 cxcoutD(Tracing) << fName <<
"::extendedTerm: expected " << expected <<
" events, got "
872 << observed <<
" events. extendedTerm = " << extra << endl;
935 RooAbsReal* RooAbsPdf::createNLL(RooAbsData& data,
const RooCmdArg& arg1,
const RooCmdArg& arg2,
const RooCmdArg& arg3,
const RooCmdArg& arg4,
936 const RooCmdArg& arg5,
const RooCmdArg& arg6,
const RooCmdArg& arg7,
const RooCmdArg& arg8)
939 l.Add((TObject*)&arg1) ; l.Add((TObject*)&arg2) ;
940 l.Add((TObject*)&arg3) ; l.Add((TObject*)&arg4) ;
941 l.Add((TObject*)&arg5) ; l.Add((TObject*)&arg6) ;
942 l.Add((TObject*)&arg7) ; l.Add((TObject*)&arg8) ;
943 return createNLL(data,l) ;
957 RooAbsReal* RooAbsPdf::createNLL(RooAbsData& data,
const RooLinkedList& cmdList)
961 RooCmdConfig pc(Form(
"RooAbsPdf::createNLL(%s)",GetName())) ;
963 pc.defineString(
"rangeName",
"RangeWithName",0,
"",kTRUE) ;
964 pc.defineString(
"addCoefRange",
"SumCoefRange",0,
"") ;
965 pc.defineString(
"globstag",
"GlobalObservablesTag",0,
"") ;
966 pc.defineDouble(
"rangeLo",
"Range",0,-999.) ;
967 pc.defineDouble(
"rangeHi",
"Range",1,-999.) ;
968 pc.defineInt(
"splitRange",
"SplitRange",0,0) ;
969 pc.defineInt(
"ext",
"Extended",0,2) ;
970 pc.defineInt(
"numcpu",
"NumCPU",0,1) ;
971 pc.defineInt(
"interleave",
"NumCPU",1,0) ;
972 pc.defineInt(
"verbose",
"Verbose",0,0) ;
973 pc.defineInt(
"optConst",
"Optimize",0,0) ;
974 pc.defineInt(
"cloneData",
"CloneData", 0, 2);
975 pc.defineSet(
"projDepSet",
"ProjectedObservables",0,0) ;
976 pc.defineSet(
"cPars",
"Constrain",0,0) ;
977 pc.defineSet(
"glObs",
"GlobalObservables",0,0) ;
979 pc.defineInt(
"doOffset",
"OffsetLikelihood",0,0) ;
980 pc.defineSet(
"extCons",
"ExternalConstraints",0,0) ;
981 pc.defineInt(
"BatchMode",
"BatchMode", 0, 0);
982 pc.defineMutex(
"Range",
"RangeWithName") ;
984 pc.defineMutex(
"GlobalObservables",
"GlobalObservablesTag") ;
987 pc.process(cmdList) ;
993 const char* rangeName = pc.getString(
"rangeName",0,kTRUE) ;
994 const char* addCoefRangeName = pc.getString(
"addCoefRange",0,kTRUE) ;
995 const char* globsTag = pc.getString(
"globstag",0,kTRUE) ;
996 Int_t ext = pc.getInt(
"ext") ;
997 Int_t numcpu = pc.getInt(
"numcpu") ;
998 RooFit::MPSplit interl = (RooFit::MPSplit) pc.getInt(
"interleave") ;
1000 Int_t splitr = pc.getInt(
"splitRange") ;
1001 Bool_t verbose = pc.getInt(
"verbose") ;
1002 Int_t optConst = pc.getInt(
"optConst") ;
1003 Int_t cloneData = pc.getInt(
"cloneData") ;
1004 Int_t doOffset = pc.getInt(
"doOffset") ;
1008 cloneData = optConst ;
1012 RooArgSet* cPars = pc.getSet(
"cPars") ;
1013 RooArgSet* glObs = pc.getSet(
"glObs") ;
1014 if (pc.hasProcessed(
"GlobalObservablesTag")) {
1015 if (glObs)
delete glObs ;
1016 RooArgSet* allVars = getVariables() ;
1017 glObs = (RooArgSet*) allVars->selectByAttrib(globsTag,kTRUE) ;
1018 coutI(Minimization) <<
"User-defined specification of global observables definition with tag named '" << globsTag <<
"'" << endl ;
1020 }
else if (!pc.hasProcessed(
"GlobalObservables")) {
1024 const char* defGlobObsTag = getStringAttribute(
"DefaultGlobalObservablesTag") ;
1025 if (defGlobObsTag) {
1026 coutI(Minimization) <<
"p.d.f. provides built-in specification of global observables definition with tag named '" << defGlobObsTag <<
"'" << endl ;
1027 if (glObs)
delete glObs ;
1028 RooArgSet* allVars = getVariables() ;
1029 glObs = (RooArgSet*) allVars->selectByAttrib(defGlobObsTag,kTRUE) ;
1034 Bool_t doStripDisconnected=kFALSE ;
1040 cPars = getParameters(data,kFALSE) ;
1041 doStripDisconnected=kTRUE ;
1043 const RooArgSet* extCons = pc.getSet(
"extCons") ;
1047 ext = ((extendMode()==CanBeExtended || extendMode()==MustBeExtended)) ? 1 : 0 ;
1049 coutI(Minimization) <<
"p.d.f. provides expected number of events, including extended term in likelihood." << endl ;
1053 if (pc.hasProcessed(
"Range")) {
1054 Double_t rangeLo = pc.getDouble(
"rangeLo") ;
1055 Double_t rangeHi = pc.getDouble(
"rangeHi") ;
1058 RooArgSet* obs = getObservables(&data) ;
1059 for (
auto arg : *obs) {
1060 RooRealVar* rrv =
dynamic_cast<RooRealVar*
>(arg) ;
1061 if (rrv) rrv->setRange(
"fit",rangeLo,rangeHi) ;
1067 RooArgSet projDeps ;
1068 RooArgSet* tmp = pc.getSet(
"projDepSet") ;
1070 projDeps.add(*tmp) ;
1074 RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ;
1076 string baseName = Form(
"nll_%s_%s",GetName(),data.GetName()) ;
1077 if (!rangeName || strchr(rangeName,
',')==0) {
1081 auto theNLL =
new RooNLLVar(baseName.c_str(),
"-log(likelihood)",
1082 *
this,data,projDeps,ext,rangeName,addCoefRangeName,numcpu,interl,
1083 verbose,splitr,cloneData);
1084 theNLL->batchMode(pc.getInt(
"BatchMode"));
1088 RooArgList nllList ;
1089 auto tokens = RooHelpers::tokenise(rangeName,
",");
1090 for (
const auto& token : tokens) {
1091 auto nllComp =
new RooNLLVar(Form(
"%s_%s",baseName.c_str(),token.c_str()),
"-log(likelihood)",
1092 *
this,data,projDeps,ext,token.c_str(),addCoefRangeName,numcpu,interl,
1093 verbose,splitr,cloneData);
1094 nllComp->batchMode(pc.getInt(
"BatchMode"));
1095 nllList.add(*nllComp) ;
1097 nll =
new RooAddition(baseName.c_str(),
"-log(likelihood)",nllList,kTRUE) ;
1099 RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ;
1102 RooArgSet allConstraints ;
1104 if (_myws && _myws->set(Form(
"CACHE_CONSTR_OF_PDF_%s_FOR_OBS_%s", GetName(), RooNameSet(*data.get()).content()))) {
1107 const RooArgSet *constr =
1108 _myws->set(Form(
"CACHE_CONSTR_OF_PDF_%s_FOR_OBS_%s", GetName(), RooNameSet(*data.get()).content()));
1109 coutI(Minimization) <<
"createNLL picked up cached consraints from workspace with " << constr->getSize()
1110 <<
" entries" << endl;
1111 allConstraints.add(*constr);
1115 if (cPars && cPars->getSize() > 0) {
1116 RooArgSet *constraints = getAllConstraints(*data.get(), *cPars, doStripDisconnected);
1117 allConstraints.add(*constraints);
1121 allConstraints.add(*extCons);
1127 coutI(Minimization) <<
"createNLL: caching constraint set under name "
1128 << Form(
"CONSTR_OF_PDF_%s_FOR_OBS_%s", GetName(), RooNameSet(*data.get()).content())
1129 <<
" with " << allConstraints.getSize() <<
" entries" << endl;
1130 _myws->defineSetInternal(
1131 Form(
"CACHE_CONSTR_OF_PDF_%s_FOR_OBS_%s", GetName(), RooNameSet(*data.get()).content()), allConstraints);
1136 RooAbsReal* nllCons(0) ;
1137 if (allConstraints.getSize()>0 && cPars) {
1139 coutI(Minimization) <<
" Including the following constraint terms in minimization: " << allConstraints << endl ;
1141 coutI(Minimization) <<
"The following global observables have been defined: " << *glObs << endl ;
1143 nllCons =
new RooConstraintSum(Form(
"%s_constr",baseName.c_str()),
"nllCons",allConstraints,glObs ? *glObs : *cPars) ;
1144 nllCons->setOperMode(ADirty) ;
1145 RooAbsReal* orignll = nll ;
1147 nll =
new RooAddition(Form(
"%s_with_constr",baseName.c_str()),
"nllWithCons",RooArgSet(*nll,*nllCons)) ;
1148 nll->addOwnedComponents(RooArgSet(*orignll,*nllCons)) ;
1153 nll->constOptimizeTestStatistic(RooAbsArg::Activate,optConst>1) ;
1156 if (doStripDisconnected) {
1161 nll->enableOffsetting(kTRUE) ;
1286 RooFitResult* RooAbsPdf::fitTo(RooAbsData& data,
const RooCmdArg& arg1,
const RooCmdArg& arg2,
const RooCmdArg& arg3,
const RooCmdArg& arg4,
1287 const RooCmdArg& arg5,
const RooCmdArg& arg6,
const RooCmdArg& arg7,
const RooCmdArg& arg8)
1290 l.Add((TObject*)&arg1) ; l.Add((TObject*)&arg2) ;
1291 l.Add((TObject*)&arg3) ; l.Add((TObject*)&arg4) ;
1292 l.Add((TObject*)&arg5) ; l.Add((TObject*)&arg6) ;
1293 l.Add((TObject*)&arg7) ; l.Add((TObject*)&arg8) ;
1294 return fitTo(data,l) ;
1308 RooFitResult* RooAbsPdf::fitTo(RooAbsData& data,
const RooLinkedList& cmdList)
1311 RooCmdConfig pc(Form(
"RooAbsPdf::fitTo(%s)",GetName())) ;
1313 RooLinkedList fitCmdList(cmdList) ;
1314 RooLinkedList nllCmdList = pc.filterCmdList(fitCmdList,
"ProjectedObservables,Extended,Range,"
1315 "RangeWithName,SumCoefRange,NumCPU,SplitRange,Constrained,Constrain,ExternalConstraints,"
1316 "CloneData,GlobalObservables,GlobalObservablesTag,OffsetLikelihood,BatchMode");
1318 pc.defineDouble(
"prefit",
"Prefit",0,0);
1319 pc.defineString(
"fitOpt",
"FitOptions",0,
"") ;
1320 pc.defineInt(
"optConst",
"Optimize",0,2) ;
1321 pc.defineInt(
"verbose",
"Verbose",0,0) ;
1322 pc.defineInt(
"doSave",
"Save",0,0) ;
1323 pc.defineInt(
"doTimer",
"Timer",0,0) ;
1324 pc.defineInt(
"plevel",
"PrintLevel",0,1) ;
1325 pc.defineInt(
"strat",
"Strategy",0,1) ;
1326 pc.defineInt(
"initHesse",
"InitialHesse",0,0) ;
1327 pc.defineInt(
"hesse",
"Hesse",0,1) ;
1328 pc.defineInt(
"minos",
"Minos",0,0) ;
1329 pc.defineInt(
"ext",
"Extended",0,2) ;
1330 pc.defineInt(
"numcpu",
"NumCPU",0,1) ;
1331 pc.defineInt(
"numee",
"PrintEvalErrors",0,10) ;
1332 pc.defineInt(
"doEEWall",
"EvalErrorWall",0,1) ;
1333 pc.defineInt(
"doWarn",
"Warnings",0,1) ;
1334 pc.defineInt(
"doSumW2",
"SumW2Error",0,-1) ;
1335 pc.defineInt(
"doAsymptoticError",
"AsymptoticError",0,-1) ;
1336 pc.defineInt(
"doOffset",
"OffsetLikelihood",0,0) ;
1337 pc.defineString(
"mintype",
"Minimizer",0,
"Minuit") ;
1338 pc.defineString(
"minalg",
"Minimizer",1,
"minuit") ;
1339 pc.defineObject(
"minosSet",
"Minos",0,0) ;
1340 pc.defineSet(
"cPars",
"Constrain",0,0) ;
1341 pc.defineSet(
"extCons",
"ExternalConstraints",0,0) ;
1342 pc.defineMutex(
"FitOptions",
"Verbose") ;
1343 pc.defineMutex(
"FitOptions",
"Save") ;
1344 pc.defineMutex(
"FitOptions",
"Timer") ;
1345 pc.defineMutex(
"FitOptions",
"Strategy") ;
1346 pc.defineMutex(
"FitOptions",
"InitialHesse") ;
1347 pc.defineMutex(
"FitOptions",
"Hesse") ;
1348 pc.defineMutex(
"FitOptions",
"Minos") ;
1349 pc.defineMutex(
"Range",
"RangeWithName") ;
1350 pc.defineMutex(
"InitialHesse",
"Minimizer") ;
1353 pc.process(fitCmdList) ;
1354 if (!pc.ok(kTRUE)) {
1359 Double_t prefit = pc.getDouble(
"prefit");
1360 const char* fitOpt = pc.getString(
"fitOpt",0,kTRUE) ;
1361 Int_t optConst = pc.getInt(
"optConst") ;
1362 Int_t verbose = pc.getInt(
"verbose") ;
1363 Int_t doSave = pc.getInt(
"doSave") ;
1364 Int_t doTimer = pc.getInt(
"doTimer") ;
1365 Int_t plevel = pc.getInt(
"plevel") ;
1366 Int_t strat = pc.getInt(
"strat") ;
1367 Int_t initHesse= pc.getInt(
"initHesse") ;
1368 Int_t hesse = pc.getInt(
"hesse") ;
1369 Int_t minos = pc.getInt(
"minos") ;
1370 Int_t numee = pc.getInt(
"numee") ;
1371 Int_t doEEWall = pc.getInt(
"doEEWall") ;
1372 Int_t doWarn = pc.getInt(
"doWarn") ;
1373 Int_t doSumW2 = pc.getInt(
"doSumW2") ;
1374 Int_t doAsymptotic = pc.getInt(
"doAsymptoticError");
1375 const RooArgSet* minosSet =
static_cast<RooArgSet*
>(pc.getObject(
"minosSet")) ;
1376 #ifdef __ROOFIT_NOROOMINIMIZER
1377 const char* minType =0 ;
1379 const char* minType = pc.getString(
"mintype",
"Minuit") ;
1380 const char* minAlg = pc.getString(
"minalg",
"minuit") ;
1384 Bool_t weightedData = data.isNonPoissonWeighted() ;
1387 if (weightedData && doSumW2==-1 && doAsymptotic==-1) {
1388 coutW(InputArguments) <<
"RooAbsPdf::fitTo(" << GetName() <<
") WARNING: a likelihood fit is requested of what appears to be weighted data.\n"
1389 <<
" While the estimated values of the parameters will always be calculated taking the weights into account,\n"
1390 <<
" there are multiple ways to estimate the errors of the parameters. You are advised to make an'n"
1391 <<
" explicit choice for the error calculation:\n"
1392 <<
" - Either provide SumW2Error(true), to calculate a sum-of-weights-corrected HESSE error matrix\n"
1393 <<
" (error will be proportional to the number of events in MC).\n"
1394 <<
" - Or provide SumW2Error(false), to return errors from original HESSE error matrix\n"
1395 <<
" (which will be proportional to the sum of the weights, i.e., a dataset with <sum of weights> events).\n"
1396 <<
" - Or provide AsymptoticError(true), to use the asymptotically correct expression\n"
1397 <<
" (for details see https://arxiv.org/abs/1911.01303)."
1403 if (doSumW2==1 && minos) {
1404 coutW(InputArguments) <<
"RooAbsPdf::fitTo(" << GetName() <<
") WARNING: sum-of-weights correction does not apply to MINOS errors" << endl ;
1406 if (doAsymptotic==1 && minos) {
1407 coutW(InputArguments) <<
"RooAbsPdf::fitTo(" << GetName() <<
") WARNING: asymptotic correction does not apply to MINOS errors" << endl ;
1411 size_t nEvents =
static_cast<size_t>(prefit*data.numEntries());
1412 if (prefit > 0.5 || nEvents < 100) {
1413 oocoutW(
this,InputArguments) <<
"PrefitDataFraction should be in suitable range."
1414 <<
"With the current PrefitDataFraction=" << prefit
1415 <<
", the number of events would be " << nEvents<<
" out of "
1416 << data.numEntries() <<
". Skipping prefit..." << endl;
1419 size_t step = data.numEntries()/nEvents;
1420 RooArgSet tinyVars(*data.get());
1421 RooRealVar weight(
"weight",
"weight",1);
1423 if (data.isWeighted()) tinyVars.add(weight);
1425 RooDataSet tiny(
"tiny",
"tiny", tinyVars,
1426 data.isWeighted() ? RooFit::WeightVar(weight) : RooCmdArg());
1428 for (
int i=0; i<data.numEntries(); i+=step)
1430 const RooArgSet *
event = data.get(i);
1431 tiny.add(*event, data.weight());
1433 RooLinkedList tinyCmdList(cmdList) ;
1434 pc.filterCmdList(tinyCmdList,
"Prefit,Hesse,Minos,Verbose,Save,Timer");
1435 RooCmdArg hesse_option = RooFit::Hesse(
false);
1436 RooCmdArg print_option = RooFit::PrintLevel(-1);
1438 tinyCmdList.Add(&hesse_option);
1439 tinyCmdList.Add(&print_option);
1441 fitTo(tiny,tinyCmdList);
1445 RooAbsReal* nll = createNLL(data,nllCmdList) ;
1446 RooFitResult *ret = 0 ;
1449 if (doSumW2==1 && doAsymptotic==1) {
1450 coutE(InputArguments) <<
"RooAbsPdf::fitTo(" << GetName() <<
") ERROR: Cannot compute both asymptotically correct and SumW2 errors." << endl ;
1456 if (
string(minType)!=
"OldMinuit") {
1458 #ifndef __ROOFIT_NOROOMINIMIZER
1459 RooMinimizer m(*nll) ;
1461 m.setMinimizerType(minType) ;
1463 m.setEvalErrorWall(doEEWall) ;
1468 m.setPrintEvalErrors(numee) ;
1470 m.setPrintLevel(plevel) ;
1475 m.optimizeConst(optConst) ;
1481 ret = m.fit(fitOpt) ;
1496 m.setStrategy(strat) ;
1505 m.minimize(minType,minAlg) ;
1513 if (doAsymptotic==1 && m.getNPar()>0) {
1515 std::unique_ptr<RooFitResult> rw(m.save());
1517 const TMatrixDSym& matV = rw->covarianceMatrix();
1518 coutI(Fitting) <<
"RooAbsPdf::fitTo(" << GetName() <<
") Calculating covariance matrix according to the asymptotically correct approach. If you find this method useful please consider citing https://arxiv.org/abs/1911.01303." << endl;
1521 TMatrixDSym num(rw->floatParsFinal().getSize());
1522 for (
int k=0; k<rw->floatParsFinal().getSize(); k++)
1523 for (
int l=0; l<rw->floatParsFinal().getSize(); l++)
1525 RooArgSet* obs = getObservables(data);
1527 std::vector<std::unique_ptr<RooDerivative> > derivatives;
1528 const RooArgList& floated = rw->floatParsFinal();
1529 std::unique_ptr<RooArgSet> floatingparams( (RooArgSet*)getParameters(data)->selectByAttrib(
"Constant",
false) );
1530 for (
int k=0; k<floated.getSize(); k++) {
1531 RooRealVar* paramresult = (RooRealVar*)floated.at(k);
1532 RooRealVar* paraminternal = (RooRealVar*)floatingparams->find(paramresult->getTitle());
1533 std::unique_ptr<RooDerivative> deriv( derivative(*paraminternal, *obs, 1) );
1534 derivatives.push_back(std::move(deriv));
1538 for (
int j=0; j<data.numEntries(); j++) {
1540 *obs = *data.get(j);
1542 std::vector<Double_t> diffs(floated.getSize(), 0.0);
1543 for (
int k=0; k<floated.getSize(); k++) {
1544 RooRealVar* paramresult = (RooRealVar*)floated.at(k);
1545 RooRealVar* paraminternal = (RooRealVar*)floatingparams->find(paramresult->getTitle());
1547 Double_t diff = derivatives.at(k)->getVal();
1549 *paraminternal = paramresult->getVal();
1553 Double_t prob = getVal(obs);
1554 for (
int k=0; k<floated.getSize(); k++) {
1555 for (
int l=0; l<floated.getSize(); l++) {
1556 num(k,l) += data.weight()*data.weight()*diffs.at(k)*diffs.at(l)/(prob*prob);
1560 num.Similarity(matV);
1563 m.applyCovarianceMatrix(num);
1566 if (doSumW2==1 && m.getNPar()>0) {
1568 RooArgSet* comps = nll->getComponents();
1569 vector<RooNLLVar*> nllComponents;
1570 nllComponents.reserve(comps->getSize());
1571 TIterator* citer = comps->createIterator();
1573 while ((arg=(RooAbsArg*)citer->Next())) {
1574 RooNLLVar* nllComp =
dynamic_cast<RooNLLVar*
>(arg);
1575 if (!nllComp)
continue;
1576 nllComponents.push_back(nllComp);
1582 RooFitResult* rw = m.save();
1583 for (vector<RooNLLVar*>::iterator it = nllComponents.begin(); nllComponents.end() != it; ++it) {
1584 (*it)->applyWeightSquared(kTRUE);
1586 coutI(Fitting) <<
"RooAbsPdf::fitTo(" << GetName() <<
") Calculating sum-of-weights-squared correction matrix for covariance matrix" << endl ;
1588 RooFitResult* rw2 = m.save();
1589 for (vector<RooNLLVar*>::iterator it = nllComponents.begin(); nllComponents.end() != it; ++it) {
1590 (*it)->applyWeightSquared(kFALSE);
1594 const TMatrixDSym& matV = rw->covarianceMatrix();
1595 TMatrixDSym matC = rw2->covarianceMatrix();
1596 using ROOT::Math::CholeskyDecompGenDim;
1597 CholeskyDecompGenDim<Double_t> decomp(matC.GetNrows(), matC);
1599 coutE(Fitting) <<
"RooAbsPdf::fitTo(" << GetName()
1600 <<
") ERROR: Cannot apply sum-of-weights correction to covariance matrix: correction matrix calculated with weight-squared is singular" <<endl ;
1603 decomp.Invert(matC);
1606 for (
int i = 0; i < matC.GetNrows(); ++i)
1607 for (
int j = 0; j < i; ++j) matC(j, i) = matC(i, j);
1608 matC.Similarity(matV);
1611 m.applyCovarianceMatrix(matC);
1621 m.minos(*minosSet) ;
1629 string name = Form(
"fitresult_%s_%s",GetName(),data.GetName()) ;
1630 string title = Form(
"Result of fit of p.d.f. %s to dataset %s",GetName(),data.GetName()) ;
1631 ret = m.save(name.c_str(),title.c_str()) ;
1636 m.optimizeConst(0) ;
1645 m.setEvalErrorWall(doEEWall) ;
1650 m.setPrintEvalErrors(numee) ;
1652 m.setPrintLevel(plevel) ;
1657 m.optimizeConst(optConst) ;
1663 ret = m.fit(fitOpt) ;
1678 m.setStrategy(strat) ;
1695 if (doAsymptotic==1 && m.getNPar()>0) {
1697 std::unique_ptr<RooFitResult> rw(m.save());
1699 const TMatrixDSym& matV = rw->covarianceMatrix();
1700 coutI(Fitting) <<
"RooAbsPdf::fitTo(" << GetName() <<
") Calculating covariance matrix according to the asymptotically correct approach. If you find this method useful please consider citing https://arxiv.org/abs/1911.01303." << endl;
1703 TMatrixDSym num(rw->floatParsFinal().getSize());
1704 for (
int k=0; k<rw->floatParsFinal().getSize(); k++)
1705 for (
int l=0; l<rw->floatParsFinal().getSize(); l++)
1707 RooArgSet* obs = getObservables(data);
1709 std::vector<std::unique_ptr<RooDerivative> > derivatives;
1710 const RooArgList& floated = rw->floatParsFinal();
1711 std::unique_ptr<RooArgSet> floatingparams( (RooArgSet*)getParameters(data)->selectByAttrib(
"Constant",
false) );
1712 for (
int k=0; k<floated.getSize(); k++) {
1713 RooRealVar* paramresult = (RooRealVar*)floated.at(k);
1714 RooRealVar* paraminternal = (RooRealVar*)floatingparams->find(paramresult->getTitle());
1715 std::unique_ptr<RooDerivative> deriv( derivative(*paraminternal, *obs, 1) );
1716 derivatives.push_back(std::move(deriv));
1720 for (
int j=0; j<data.numEntries(); j++) {
1722 *obs = *data.get(j);
1724 std::vector<Double_t> diffs(floated.getSize(), 0.0);
1725 for (
int k=0; k<floated.getSize(); k++) {
1726 RooRealVar* paramresult = (RooRealVar*)floated.at(k);
1727 RooRealVar* paraminternal = (RooRealVar*)floatingparams->find(paramresult->getTitle());
1729 Double_t diff = derivatives.at(k)->getVal();
1731 *paraminternal = paramresult->getVal();
1735 Double_t prob = getVal(obs);
1736 for (
int k=0; k<floated.getSize(); k++) {
1737 for (
int l=0; l<floated.getSize(); l++) {
1738 num(k,l) += data.weight()*data.weight()*diffs.at(k)*diffs.at(l)/(prob*prob);
1742 num.Similarity(matV);
1745 m.applyCovarianceMatrix(num);
1748 if (doSumW2==1 && m.getNPar()>0) {
1751 list<RooNLLVar*> nllComponents ;
1752 RooArgSet* comps = nll->getComponents() ;
1754 TIterator* citer = comps->createIterator() ;
1755 while((arg=(RooAbsArg*)citer->Next())) {
1756 RooNLLVar* nllComp =
dynamic_cast<RooNLLVar*
>(arg) ;
1758 nllComponents.push_back(nllComp) ;
1765 RooFitResult* rw = m.save() ;
1766 for (list<RooNLLVar*>::iterator iter1=nllComponents.begin() ; iter1!=nllComponents.end() ; ++iter1) {
1767 (*iter1)->applyWeightSquared(kTRUE) ;
1769 coutI(Fitting) <<
"RooAbsPdf::fitTo(" << GetName() <<
") Calculating sum-of-weights-squared correction matrix for covariance matrix" << endl ;
1771 RooFitResult* rw2 = m.save() ;
1772 for (list<RooNLLVar*>::iterator iter2=nllComponents.begin() ; iter2!=nllComponents.end() ; ++iter2) {
1773 (*iter2)->applyWeightSquared(kFALSE) ;
1777 const TMatrixDSym& matV = rw->covarianceMatrix();
1778 TMatrixDSym matC = rw2->covarianceMatrix();
1779 using ROOT::Math::CholeskyDecompGenDim;
1780 CholeskyDecompGenDim<Double_t> decomp(matC.GetNrows(), matC);
1782 coutE(Fitting) <<
"RooAbsPdf::fitTo(" << GetName()
1783 <<
") ERROR: Cannot apply sum-of-weights correction to covariance matrix: correction matrix calculated with weight-squared is singular" <<endl ;
1786 decomp.Invert(matC);
1789 for (
int i = 0; i < matC.GetNrows(); ++i)
1790 for (
int j = 0; j < i; ++j) matC(j, i) = matC(i, j);
1791 matC.Similarity(matV);
1794 m.applyCovarianceMatrix(matC);
1804 m.minos(*minosSet) ;
1812 string name = Form(
"fitresult_%s_%s",GetName(),data.GetName()) ;
1813 string title = Form(
"Result of fit of p.d.f. %s to dataset %s",GetName(),data.GetName()) ;
1814 ret = m.save(name.c_str(),title.c_str()) ;
1820 m.optimizeConst(0) ;
1837 RooFitResult* RooAbsPdf::chi2FitTo(RooDataHist& data,
const RooLinkedList& cmdList)
1840 RooCmdConfig pc(Form(
"RooAbsPdf::chi2FitTo(%s)",GetName())) ;
1843 RooLinkedList fitCmdList(cmdList) ;
1844 RooLinkedList chi2CmdList = pc.filterCmdList(fitCmdList,
"Range,RangeWithName,NumCPU,Optimize,ProjectedObservables,AddCoefRange,SplitRange,DataError,Extended") ;
1846 RooAbsReal* chi2 = createChi2(data,chi2CmdList) ;
1847 RooFitResult* ret = chi2FitDriver(*chi2,fitCmdList) ;
1882 RooAbsReal* RooAbsPdf::createChi2(RooDataHist& data,
const RooCmdArg& arg1,
const RooCmdArg& arg2,
1883 const RooCmdArg& arg3,
const RooCmdArg& arg4,
const RooCmdArg& arg5,
1884 const RooCmdArg& arg6,
const RooCmdArg& arg7,
const RooCmdArg& arg8)
1886 RooLinkedList cmdList ;
1887 cmdList.Add((TObject*)&arg1) ; cmdList.Add((TObject*)&arg2) ;
1888 cmdList.Add((TObject*)&arg3) ; cmdList.Add((TObject*)&arg4) ;
1889 cmdList.Add((TObject*)&arg5) ; cmdList.Add((TObject*)&arg6) ;
1890 cmdList.Add((TObject*)&arg7) ; cmdList.Add((TObject*)&arg8) ;
1892 RooCmdConfig pc(Form(
"RooAbsPdf::createChi2(%s)",GetName())) ;
1893 pc.defineString(
"rangeName",
"RangeWithName",0,
"",kTRUE) ;
1894 pc.allowUndefined(kTRUE) ;
1895 pc.process(cmdList) ;
1896 if (!pc.ok(kTRUE)) {
1899 const char* rangeName = pc.getString(
"rangeName",0,kTRUE) ;
1902 RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ;
1904 string baseName = Form(
"chi2_%s_%s",GetName(),data.GetName()) ;
1906 if (!rangeName || strchr(rangeName,
',')==0) {
1909 chi2 =
new RooChi2Var(baseName.c_str(),baseName.c_str(),*
this,data,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8) ;
1914 const RooCmdArg* rarg(0) ;
1915 string rcmd =
"RangeWithName" ;
1916 if (arg1.GetName()==rcmd) rarg = &arg1 ;
1917 if (arg2.GetName()==rcmd) rarg = &arg2 ;
1918 if (arg3.GetName()==rcmd) rarg = &arg3 ;
1919 if (arg4.GetName()==rcmd) rarg = &arg4 ;
1920 if (arg5.GetName()==rcmd) rarg = &arg5 ;
1921 if (arg6.GetName()==rcmd) rarg = &arg6 ;
1922 if (arg7.GetName()==rcmd) rarg = &arg7 ;
1923 if (arg8.GetName()==rcmd) rarg = &arg8 ;
1926 RooArgList chi2List ;
1927 const size_t bufSize = strlen(rangeName)+1;
1928 char* buf =
new char[bufSize] ;
1929 strlcpy(buf,rangeName,bufSize) ;
1930 char* token = strtok(buf,
",") ;
1932 RooCmdArg subRangeCmd = RooFit::Range(token) ;
1934 RooAbsReal* chi2Comp =
new RooChi2Var(Form(
"%s_%s",baseName.c_str(),token),
"chi^2",*
this,data,
1935 &arg1==rarg?subRangeCmd:arg1,&arg2==rarg?subRangeCmd:arg2,
1936 &arg3==rarg?subRangeCmd:arg3,&arg4==rarg?subRangeCmd:arg4,
1937 &arg5==rarg?subRangeCmd:arg5,&arg6==rarg?subRangeCmd:arg6,
1938 &arg7==rarg?subRangeCmd:arg7,&arg8==rarg?subRangeCmd:arg8) ;
1939 chi2List.add(*chi2Comp) ;
1940 token = strtok(0,
",") ;
1943 chi2 =
new RooAddition(baseName.c_str(),
"chi^2",chi2List,kTRUE) ;
1945 RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ;
1957 RooAbsReal* RooAbsPdf::createChi2(RooDataSet& data,
const RooLinkedList& cmdList)
1960 RooCmdConfig pc(Form(
"RooAbsPdf::fitTo(%s)",GetName())) ;
1962 pc.defineInt(
"integrate",
"Integrate",0,0) ;
1963 pc.defineObject(
"yvar",
"YVar",0,0) ;
1966 pc.process(cmdList) ;
1967 if (!pc.ok(kTRUE)) {
1972 Bool_t integrate = pc.getInt(
"integrate") ;
1973 RooRealVar* yvar = (RooRealVar*) pc.getObject(
"yvar") ;
1975 string name = Form(
"chi2_%s_%s",GetName(),data.GetName()) ;
1978 return new RooXYChi2Var(name.c_str(),name.c_str(),*
this,data,*yvar,integrate) ;
1980 return new RooXYChi2Var(name.c_str(),name.c_str(),*
this,data,integrate) ;
1990 void RooAbsPdf::printValue(ostream& os)
const
1995 os << evaluate() <<
"/" << _norm->getVal() ;
2006 void RooAbsPdf::printMultiline(ostream& os, Int_t contents, Bool_t verbose, TString indent)
const
2008 RooAbsReal::printMultiline(os,contents,verbose,indent);
2009 os << indent <<
"--- RooAbsPdf ---" << endl;
2010 os << indent <<
"Cached value = " << _value << endl ;
2012 os << indent <<
" Normalization integral: " << endl ;
2013 TString moreIndent(indent) ; moreIndent.Append(
" ") ;
2014 _norm->printStream(os,kName|kAddress|kTitle|kValue|kArgs,kSingleLine,moreIndent.Data()) ;
2023 RooAbsGenContext* RooAbsPdf::binnedGenContext(
const RooArgSet &vars, Bool_t verbose)
const
2025 return new RooBinnedGenContext(*
this,vars,0,0,verbose) ;
2033 RooAbsGenContext* RooAbsPdf::genContext(
const RooArgSet &vars,
const RooDataSet *prototype,
2034 const RooArgSet* auxProto, Bool_t verbose)
const
2036 return new RooGenContext(*
this,vars,prototype,auxProto,verbose) ;
2042 RooAbsGenContext* RooAbsPdf::autoGenContext(
const RooArgSet &vars,
const RooDataSet* prototype,
const RooArgSet* auxProto,
2043 Bool_t verbose, Bool_t autoBinned,
const char* binnedTag)
const
2045 if (prototype || (auxProto && auxProto->getSize()>0)) {
2046 return genContext(vars,prototype,auxProto,verbose);
2049 RooAbsGenContext *context(0) ;
2050 if ( (autoBinned && isBinnedDistribution(vars)) || ( binnedTag && strlen(binnedTag) && (getAttribute(binnedTag)||
string(binnedTag)==
"*"))) {
2051 context = binnedGenContext(vars,verbose) ;
2053 context= genContext(vars,0,0,verbose);
2106 RooDataSet *RooAbsPdf::generate(
const RooArgSet& whatVars,
const RooCmdArg& arg1,
const RooCmdArg& arg2,
2107 const RooCmdArg& arg3,
const RooCmdArg& arg4,
const RooCmdArg& arg5,
const RooCmdArg& arg6)
2110 RooCmdConfig pc(Form(
"RooAbsPdf::generate(%s)",GetName())) ;
2111 pc.defineObject(
"proto",
"PrototypeData",0,0) ;
2112 pc.defineString(
"dsetName",
"Name",0,
"") ;
2113 pc.defineInt(
"randProto",
"PrototypeData",0,0) ;
2114 pc.defineInt(
"resampleProto",
"PrototypeData",1,0) ;
2115 pc.defineInt(
"verbose",
"Verbose",0,0) ;
2116 pc.defineInt(
"extended",
"Extended",0,0) ;
2117 pc.defineInt(
"nEvents",
"NumEvents",0,0) ;
2118 pc.defineInt(
"autoBinned",
"AutoBinned",0,1) ;
2119 pc.defineInt(
"expectedData",
"ExpectedData",0,0) ;
2120 pc.defineDouble(
"nEventsD",
"NumEventsD",0,-1.) ;
2121 pc.defineString(
"binnedTag",
"GenBinned",0,
"") ;
2122 pc.defineMutex(
"GenBinned",
"ProtoData") ;
2123 pc.defineMutex(
"Extended",
"NumEvents");
2126 pc.process(arg1,arg2,arg3,arg4,arg5,arg6) ;
2127 if (!pc.ok(kTRUE)) {
2132 RooDataSet* protoData =
static_cast<RooDataSet*
>(pc.getObject(
"proto",0)) ;
2133 const char* dsetName = pc.getString(
"dsetName") ;
2134 Bool_t verbose = pc.getInt(
"verbose") ;
2135 Bool_t randProto = pc.getInt(
"randProto") ;
2136 Bool_t resampleProto = pc.getInt(
"resampleProto") ;
2137 Bool_t extended = pc.getInt(
"extended") ;
2138 Bool_t autoBinned = pc.getInt(
"autoBinned") ;
2139 const char* binnedTag = pc.getString(
"binnedTag") ;
2140 Int_t nEventsI = pc.getInt(
"nEvents") ;
2141 Double_t nEventsD = pc.getInt(
"nEventsD") ;
2143 Bool_t expectedData = pc.getInt(
"expectedData") ;
2145 Double_t nEvents = (nEventsD>0) ? nEventsD : Double_t(nEventsI);
2153 if (nEvents == 0) nEvents = expectedEvents(&whatVars);
2154 }
else if (nEvents==0) {
2155 cxcoutI(Generation) <<
"No number of events specified , number of events generated is "
2156 << GetName() <<
"::expectedEvents() = " << expectedEvents(&whatVars)<< endl ;
2159 if (extended && protoData && !randProto) {
2160 cxcoutI(Generation) <<
"WARNING Using generator option Extended() (Poisson distribution of #events) together "
2161 <<
"with a prototype dataset implies incomplete sampling or oversampling of proto data. "
2162 <<
"Set randomize flag in ProtoData() option to randomize prototype dataset order and thus "
2163 <<
"to randomize the set of over/undersampled prototype events for each generation cycle." << endl ;
2170 data = generate(whatVars,*protoData,Int_t(nEvents),verbose,randProto,resampleProto) ;
2172 data = generate(whatVars,nEvents,verbose,autoBinned,binnedTag,expectedData, extended) ;
2176 if (dsetName && strlen(dsetName)>0) {
2177 data->SetName(dsetName) ;
2195 RooAbsPdf::GenSpec* RooAbsPdf::prepareMultiGen(
const RooArgSet &whatVars,
2196 const RooCmdArg& arg1,
const RooCmdArg& arg2,
2197 const RooCmdArg& arg3,
const RooCmdArg& arg4,
2198 const RooCmdArg& arg5,
const RooCmdArg& arg6)
2202 RooCmdConfig pc(Form(
"RooAbsPdf::generate(%s)",GetName())) ;
2203 pc.defineObject(
"proto",
"PrototypeData",0,0) ;
2204 pc.defineString(
"dsetName",
"Name",0,
"") ;
2205 pc.defineInt(
"randProto",
"PrototypeData",0,0) ;
2206 pc.defineInt(
"resampleProto",
"PrototypeData",1,0) ;
2207 pc.defineInt(
"verbose",
"Verbose",0,0) ;
2208 pc.defineInt(
"extended",
"Extended",0,0) ;
2209 pc.defineInt(
"nEvents",
"NumEvents",0,0) ;
2210 pc.defineInt(
"autoBinned",
"AutoBinned",0,1) ;
2211 pc.defineString(
"binnedTag",
"GenBinned",0,
"") ;
2212 pc.defineMutex(
"GenBinned",
"ProtoData") ;
2216 pc.process(arg1,arg2,arg3,arg4,arg5,arg6) ;
2217 if (!pc.ok(kTRUE)) {
2222 RooDataSet* protoData =
static_cast<RooDataSet*
>(pc.getObject(
"proto",0)) ;
2223 const char* dsetName = pc.getString(
"dsetName") ;
2224 Int_t nEvents = pc.getInt(
"nEvents") ;
2225 Bool_t verbose = pc.getInt(
"verbose") ;
2226 Bool_t randProto = pc.getInt(
"randProto") ;
2227 Bool_t resampleProto = pc.getInt(
"resampleProto") ;
2228 Bool_t extended = pc.getInt(
"extended") ;
2229 Bool_t autoBinned = pc.getInt(
"autoBinned") ;
2230 const char* binnedTag = pc.getString(
"binnedTag") ;
2232 RooAbsGenContext* cx = autoGenContext(whatVars,protoData,0,verbose,autoBinned,binnedTag) ;
2234 return new GenSpec(cx,whatVars,protoData,nEvents,extended,randProto,resampleProto,dsetName) ;
2244 RooDataSet *RooAbsPdf::generate(RooAbsPdf::GenSpec& spec)
const
2250 Double_t nEvt = spec._nGen == 0 ? expectedEvents(spec._whatVars) : spec._nGen;
2252 RooDataSet* ret = generate(*spec._genContext,spec._whatVars,spec._protoData, nEvt,kFALSE,spec._randProto,spec._resampleProto,
2253 spec._init,spec._extended) ;
2254 spec._init = kTRUE ;
2281 RooDataSet *RooAbsPdf::generate(
const RooArgSet &whatVars, Double_t nEvents, Bool_t verbose, Bool_t autoBinned,
const char* binnedTag, Bool_t expectedData, Bool_t extended)
const
2283 if (nEvents==0 && extendMode()==CanNotBeExtended) {
2284 return new RooDataSet(
"emptyData",
"emptyData",whatVars) ;
2288 RooAbsGenContext *context = autoGenContext(whatVars,0,0,verbose,autoBinned,binnedTag) ;
2290 context->setExpectedData(kTRUE) ;
2293 RooDataSet *generated = 0;
2294 if(0 != context && context->isValid()) {
2295 generated= context->generate(nEvents, kFALSE, extended);
2298 coutE(Generation) <<
"RooAbsPdf::generate(" << GetName() <<
") cannot create a valid context" << endl;
2300 if(0 != context)
delete context;
2310 RooDataSet *RooAbsPdf::generate(RooAbsGenContext& context,
const RooArgSet &whatVars,
const RooDataSet *prototype,
2311 Double_t nEvents, Bool_t , Bool_t randProtoOrder, Bool_t resampleProto,
2312 Bool_t skipInit, Bool_t extended)
const
2314 if (nEvents==0 && (prototype==0 || prototype->numEntries()==0)) {
2315 return new RooDataSet(
"emptyData",
"emptyData",whatVars) ;
2318 RooDataSet *generated = 0;
2321 if (resampleProto) {
2322 randProtoOrder=kTRUE ;
2325 if (randProtoOrder && prototype && prototype->numEntries()!=nEvents) {
2326 coutI(Generation) <<
"RooAbsPdf::generate (Re)randomizing event order in prototype dataset (Nevt=" << nEvents <<
")" << endl ;
2327 Int_t* newOrder = randomizeProtoOrder(prototype->numEntries(),Int_t(nEvents),resampleProto) ;
2328 context.setProtoDataOrder(newOrder) ;
2332 if(context.isValid()) {
2333 generated= context.generate(nEvents,skipInit,extended);
2336 coutE(Generation) <<
"RooAbsPdf::generate(" << GetName() <<
") do not have a valid generator context" << endl;
2366 RooDataSet *RooAbsPdf::generate(
const RooArgSet &whatVars,
const RooDataSet& prototype,
2367 Int_t nEvents, Bool_t verbose, Bool_t randProtoOrder, Bool_t resampleProto)
const
2369 RooAbsGenContext *context= genContext(whatVars,&prototype,0,verbose);
2371 RooDataSet* data = generate(*context,whatVars,&prototype,nEvents,verbose,randProtoOrder,resampleProto) ;
2375 coutE(Generation) <<
"RooAbsPdf::generate(" << GetName() <<
") ERROR creating generator context" << endl ;
2387 Int_t* RooAbsPdf::randomizeProtoOrder(Int_t nProto, Int_t, Bool_t resampleProto)
const
2392 for (i=0 ; i<nProto ; i++) {
2393 l.Add(
new RooInt(i)) ;
2397 Int_t* lut =
new Int_t[nProto] ;
2400 if (!resampleProto) {
2402 for (i=0 ; i<nProto ; i++) {
2403 Int_t iran = RooRandom::integer(nProto-i) ;
2404 RooInt* sample = (RooInt*) l.At(iran) ;
2411 for (i=0 ; i<nProto ; i++) {
2412 lut[i] = RooRandom::integer(nProto);
2431 Int_t RooAbsPdf::getGenerator(
const RooArgSet &, RooArgSet &, Bool_t )
const
2441 void RooAbsPdf::initGenerator(Int_t )
2453 void RooAbsPdf::generateEvent(Int_t )
2466 Bool_t RooAbsPdf::isDirectGenSafe(
const RooAbsArg& arg)
const
2469 if (!findServer(arg.GetName()))
return kFALSE ;
2472 for (
const auto server : _serverList) {
2473 if(server == &arg)
continue;
2474 if(server->dependsOn(arg)) {
2507 RooDataHist *RooAbsPdf::generateBinned(
const RooArgSet& whatVars,
const RooCmdArg& arg1,
const RooCmdArg& arg2,
2508 const RooCmdArg& arg3,
const RooCmdArg& arg4,
const RooCmdArg& arg5,
const RooCmdArg& arg6)
const
2512 RooCmdConfig pc(Form(
"RooAbsPdf::generate(%s)",GetName())) ;
2513 pc.defineString(
"dsetName",
"Name",0,
"") ;
2514 pc.defineInt(
"verbose",
"Verbose",0,0) ;
2515 pc.defineInt(
"extended",
"Extended",0,0) ;
2516 pc.defineInt(
"nEvents",
"NumEvents",0,0) ;
2517 pc.defineDouble(
"nEventsD",
"NumEventsD",0,-1.) ;
2518 pc.defineInt(
"expectedData",
"ExpectedData",0,0) ;
2521 pc.process(arg1,arg2,arg3,arg4,arg5,arg6) ;
2522 if (!pc.ok(kTRUE)) {
2527 Double_t nEvents = pc.getDouble(
"nEventsD") ;
2529 nEvents = pc.getInt(
"nEvents") ;
2532 Bool_t extended = pc.getInt(
"extended") ;
2533 Bool_t expectedData = pc.getInt(
"expectedData") ;
2534 const char* dsetName = pc.getString(
"dsetName") ;
2538 nEvents = (nEvents==0 ? expectedEvents(&whatVars) :nEvents) ;
2539 cxcoutI(Generation) <<
" Extended mode active, number of events generated (" << nEvents <<
") is Poisson fluctuation on "
2540 << GetName() <<
"::expectedEvents() = " << nEvents << endl ;
2545 }
else if (nEvents==0) {
2546 cxcoutI(Generation) <<
"No number of events specified , number of events generated is "
2547 << GetName() <<
"::expectedEvents() = " << expectedEvents(&whatVars)<< endl ;
2551 RooDataHist* data = generateBinned(whatVars,nEvents,expectedData,extended) ;
2554 if (dsetName && strlen(dsetName)>0) {
2555 data->SetName(dsetName) ;
2577 RooDataHist *RooAbsPdf::generateBinned(
const RooArgSet &whatVars, Double_t nEvents, Bool_t expectedData, Bool_t extended)
const
2580 RooDataHist* hist =
new RooDataHist(
"genData",
"genData",whatVars) ;
2584 if (!canBeExtended()) {
2585 coutE(InputArguments) <<
"RooAbsPdf::generateBinned(" << GetName() <<
") ERROR: No event count provided and p.d.f does not provide expected number of events" << endl ;
2591 if (expectedData || extended) {
2592 nEvents = expectedEvents(&whatVars) ;
2594 nEvents = Int_t(expectedEvents(&whatVars)+0.5) ;
2600 fillDataHist(hist,&whatVars,1,kTRUE) ;
2602 vector<int> histOut(hist->numEntries()) ;
2603 Double_t histMax(-1) ;
2604 Int_t histOutSum(0) ;
2605 for (
int i=0 ; i<hist->numEntries() ; i++) {
2610 Double_t w=hist->weight()*nEvents ;
2611 hist->set(w,sqrt(w)) ;
2613 }
else if (extended) {
2616 Double_t w = RooRandom::randomGenerator()->Poisson(hist->weight()*nEvents) ;
2617 hist->set(w,sqrt(w)) ;
2623 if (hist->weight()>histMax) {
2624 histMax = hist->weight() ;
2626 histOut[i] = RooRandom::randomGenerator()->Poisson(hist->weight()*nEvents) ;
2627 histOutSum += histOut[i] ;
2632 if (!expectedData && !extended) {
2637 Int_t nEvtExtra = abs(Int_t(nEvents)-histOutSum) ;
2638 Int_t wgt = (histOutSum>nEvents) ? -1 : 1 ;
2641 while(nEvtExtra>0) {
2643 Int_t ibinRand = RooRandom::randomGenerator()->Integer(hist->numEntries()) ;
2644 hist->get(ibinRand) ;
2645 Double_t ranY = RooRandom::randomGenerator()->Uniform(histMax) ;
2647 if (ranY<hist->weight()) {
2649 histOut[ibinRand]++ ;
2652 if (histOut[ibinRand]>0) {
2653 histOut[ibinRand]-- ;
2663 for (
int i=0 ; i<hist->numEntries() ; i++) {
2665 hist->set(histOut[i],sqrt(1.0*histOut[i])) ;
2668 }
else if (expectedData) {
2673 Double_t corr = nEvents/hist->sumEntries() ;
2674 for (
int i=0 ; i<hist->numEntries() ; i++) {
2676 hist->set(hist->weight()*corr,sqrt(hist->weight()*corr)) ;
2689 RooDataSet* RooAbsPdf::generateSimGlobal(
const RooArgSet& whatVars, Int_t nEvents)
2691 return generate(whatVars,nEvents) ;
2695 void removeRangeOverlap(std::vector<std::pair<double, double>>& ranges) {
2697 std::sort(ranges.begin(), ranges.end());
2699 for (
auto it = ranges.begin(); it != ranges.end(); ++it) {
2700 double& startL = it->first;
2701 double& endL = it->second;
2703 for (
auto innerIt = it+1; innerIt != ranges.end(); ++innerIt) {
2704 const double startR = innerIt->first;
2705 const double endR = innerIt->second;
2707 if (startL <= startR && startR <= endL) {
2709 endL = std::max(endL, endR);
2710 *innerIt = make_pair(0., 0.);
2715 auto newEnd = std::remove_if(ranges.begin(), ranges.end(),
2716 [](
const std::pair<double,double>& input){
2717 return input.first == input.second;
2719 ranges.erase(newEnd, ranges.end());
2799 RooPlot* RooAbsPdf::plotOn(RooPlot* frame, RooLinkedList& cmdList)
const
2804 RooCmdArg* plotRange(0) ;
2805 RooCmdArg* normRange2(0) ;
2806 if (getStringAttribute(
"fitrange") && !cmdList.FindObject(
"Range") &&
2807 !cmdList.FindObject(
"RangeWithName")) {
2808 plotRange = (RooCmdArg*) RooFit::Range(getStringAttribute(
"fitrange")).Clone() ;
2809 cmdList.Add(plotRange) ;
2812 if (getStringAttribute(
"fitrange") && !cmdList.FindObject(
"NormRange")) {
2813 normRange2 = (RooCmdArg*) RooFit::NormRange(getStringAttribute(
"fitrange")).Clone() ;
2814 cmdList.Add(normRange2) ;
2817 if (plotRange || normRange2) {
2818 coutI(Plotting) <<
"RooAbsPdf::plotOn(" << GetName() <<
") p.d.f was fitted in range and no explicit "
2819 << (plotRange?
"plot":
"") << ((plotRange&&normRange2)?
",":
"")
2820 << (normRange2?
"norm":
"") <<
" range was specified, using fit range as default" << endl ;
2824 if (plotSanityChecks(frame))
return frame ;
2827 RooCmdConfig pc(Form(
"RooAbsPdf::plotOn(%s)",GetName())) ;
2828 pc.defineDouble(
"scaleFactor",
"Normalization",0,1.0) ;
2829 pc.defineInt(
"scaleType",
"Normalization",0,Relative) ;
2830 pc.defineObject(
"compSet",
"SelectCompSet",0) ;
2831 pc.defineString(
"compSpec",
"SelectCompSpec",0) ;
2832 pc.defineObject(
"asymCat",
"Asymmetry",0) ;
2833 pc.defineDouble(
"rangeLo",
"Range",0,-999.) ;
2834 pc.defineDouble(
"rangeHi",
"Range",1,-999.) ;
2835 pc.defineString(
"rangeName",
"RangeWithName",0,
"") ;
2836 pc.defineString(
"normRangeName",
"NormRange",0,
"") ;
2837 pc.defineInt(
"rangeAdjustNorm",
"Range",0,0) ;
2838 pc.defineInt(
"rangeWNAdjustNorm",
"RangeWithName",0,0) ;
2839 pc.defineMutex(
"SelectCompSet",
"SelectCompSpec") ;
2840 pc.defineMutex(
"Range",
"RangeWithName") ;
2841 pc.allowUndefined() ;
2844 pc.process(cmdList) ;
2845 if (!pc.ok(kTRUE)) {
2850 ScaleType stype = (ScaleType) pc.getInt(
"scaleType") ;
2851 Double_t scaleFactor = pc.getDouble(
"scaleFactor") ;
2852 const RooAbsCategoryLValue* asymCat = (
const RooAbsCategoryLValue*) pc.getObject(
"asymCat") ;
2853 const char* compSpec = pc.getString(
"compSpec") ;
2854 const RooArgSet* compSet = (
const RooArgSet*) pc.getObject(
"compSet") ;
2855 Bool_t haveCompSel = ( (compSpec && strlen(compSpec)>0) || compSet) ;
2858 TString nameSuffix ;
2859 if (compSpec && strlen(compSpec)>0) {
2860 nameSuffix.Append(
"_Comp[") ;
2861 nameSuffix.Append(compSpec) ;
2862 nameSuffix.Append(
"]") ;
2863 }
else if (compSet) {
2864 nameSuffix.Append(
"_Comp[") ;
2865 nameSuffix.Append(compSet->contentsString().c_str()) ;
2866 nameSuffix.Append(
"]") ;
2870 pc.stripCmdList(cmdList,
"SelectCompSet,SelectCompSpec") ;
2874 RooCmdArg cnsuffix(
"CurveNameSuffix",0,0,0,0,nameSuffix.Data(),0,0,0) ;
2875 cmdList.Add(&cnsuffix);
2876 return RooAbsReal::plotOn(frame,cmdList) ;
2880 Double_t nExpected(1) ;
2881 if (stype==RelativeExpected) {
2882 if (!canBeExtended()) {
2883 coutE(Plotting) <<
"RooAbsPdf::plotOn(" << GetName()
2884 <<
"): ERROR the 'Expected' scale option can only be used on extendable PDFs" << endl ;
2887 nExpected = expectedEvents(frame->getNormVars()) ;
2892 if (frame->getFitRangeNEvt() && stype==Relative) {
2894 Bool_t hasCustomRange(kFALSE), adjustNorm(kFALSE) ;
2896 std::vector<pair<Double_t,Double_t> > rangeLim;
2899 if (pc.hasProcessed(
"Range")) {
2901 Double_t rangeLo = pc.getDouble(
"rangeLo") ;
2902 Double_t rangeHi = pc.getDouble(
"rangeHi") ;
2903 rangeLim.push_back(make_pair(rangeLo,rangeHi)) ;
2904 adjustNorm = pc.getInt(
"rangeAdjustNorm") ;
2905 hasCustomRange = kTRUE ;
2907 coutI(Plotting) <<
"RooAbsPdf::plotOn(" << GetName() <<
") only plotting range ["
2908 << rangeLo <<
"," << rangeHi <<
"]" ;
2909 if (!pc.hasProcessed(
"NormRange")) {
2910 ccoutI(Plotting) <<
", curve is normalized to data in " << (adjustNorm?
"given":
"full") <<
" range" << endl ;
2912 ccoutI(Plotting) << endl ;
2915 nameSuffix.Append(Form(
"_Range[%f_%f]",rangeLo,rangeHi)) ;
2917 }
else if (pc.hasProcessed(
"RangeWithName")) {
2918 for (
const std::string& rangeNameToken : RooHelpers::tokenise(pc.getString(
"rangeName",0,
true),
",")) {
2919 if (!frame->getPlotVar()->hasRange(rangeNameToken.c_str())) {
2920 coutE(Plotting) <<
"Range '" << rangeNameToken <<
"' not defined for variable '"
2921 << frame->getPlotVar()->GetName() <<
"'. Ignoring ..." << std::endl;
2924 const double rangeLo = frame->getPlotVar()->getMin(rangeNameToken.c_str());
2925 const double rangeHi = frame->getPlotVar()->getMax(rangeNameToken.c_str());
2926 rangeLim.push_back(make_pair(rangeLo,rangeHi));
2928 adjustNorm = pc.getInt(
"rangeWNAdjustNorm") ;
2929 hasCustomRange = kTRUE ;
2931 coutI(Plotting) <<
"RooAbsPdf::plotOn(" << GetName() <<
") only plotting range '" << pc.getString(
"rangeName",0,kTRUE) <<
"'" ;
2932 if (!pc.hasProcessed(
"NormRange")) {
2933 ccoutI(Plotting) <<
", curve is normalized to data in " << (adjustNorm?
"given":
"full") <<
" range" << endl ;
2935 ccoutI(Plotting) << endl ;
2938 nameSuffix.Append(Form(
"_Range[%s]",pc.getString(
"rangeName"))) ;
2941 if (pc.hasProcessed(
"NormRange")) {
2943 for (
const auto& rangeNameToken : RooHelpers::tokenise(pc.getString(
"normRangeName",0,
true),
",")) {
2944 if (!frame->getPlotVar()->hasRange(rangeNameToken.c_str())) {
2945 coutE(Plotting) <<
"Range '" << rangeNameToken <<
"' not defined for variable '"
2946 << frame->getPlotVar()->GetName() <<
"'. Ignoring ..." << std::endl;
2949 const double rangeLo = frame->getPlotVar()->getMin(rangeNameToken.c_str());
2950 const double rangeHi = frame->getPlotVar()->getMax(rangeNameToken.c_str());
2951 rangeLim.push_back(make_pair(rangeLo,rangeHi));
2953 adjustNorm = kTRUE ;
2954 hasCustomRange = kTRUE ;
2955 coutI(Plotting) <<
"RooAbsPdf::plotOn(" << GetName() <<
") p.d.f. curve is normalized using explicit choice of ranges '" << pc.getString(
"normRangeName",0,kTRUE) <<
"'" << endl ;
2957 nameSuffix.Append(Form(
"_NormRange[%s]",pc.getString(
"rangeName"))) ;
2961 if (hasCustomRange && adjustNorm) {
2962 const std::size_t oldSize = rangeLim.size();
2963 removeRangeOverlap(rangeLim);
2965 if (oldSize != rangeLim.size()) {
2968 coutE(Plotting) <<
"Requested ranges overlap. For correct plotting, new ranges "
2969 "will be defined." << std::endl;
2970 auto plotVar =
dynamic_cast<RooRealVar*
>(frame->getPlotVar());
2972 std::string rangesNoOverlap;
2973 for (
auto it = rangeLim.begin(); it != rangeLim.end(); ++it) {
2974 std::stringstream rangeName;
2975 rangeName <<
"Remove_overlap_range_" << it - rangeLim.begin();
2976 plotVar->setRange(rangeName.str().c_str(), it->first, it->second);
2977 if (!rangesNoOverlap.empty())
2978 rangesNoOverlap +=
",";
2979 rangesNoOverlap += rangeName.str();
2982 auto rangeArg =
static_cast<RooCmdArg*
>(cmdList.FindObject(
"RangeWithName"));
2984 rangeArg->setString(0, rangesNoOverlap.c_str());
2986 plotRange =
new RooCmdArg(RooFit::Range(rangesNoOverlap.c_str()));
2987 cmdList.Add(plotRange);
2991 Double_t rangeNevt(0) ;
2992 for (
const auto& riter : rangeLim) {
2993 Double_t nevt= frame->getFitRangeNEvt(riter.first, riter.second);
2997 scaleFactor *= rangeNevt/nExpected ;
3000 scaleFactor *= frame->getFitRangeNEvt()/nExpected ;
3002 }
else if (stype==RelativeExpected) {
3003 scaleFactor *= nExpected ;
3004 }
else if (stype==NumEvent) {
3005 scaleFactor /= nExpected ;
3007 scaleFactor *= frame->getFitRangeBinW() ;
3009 frame->updateNormVars(*frame->getPlotVar()) ;
3012 RooCmdArg tmp = RooFit::Normalization(scaleFactor,Raw) ;
3020 RooArgSet branchNodeSet ;
3021 branchNodeServerList(&branchNodeSet) ;
3024 for (
const auto arg : branchNodeSet) {
3025 if (!dynamic_cast<RooAbsReal*>(arg)) {
3026 branchNodeSet.remove(*arg) ;
3031 RooArgSet* dirSelNodes ;
3033 dirSelNodes = (RooArgSet*) branchNodeSet.selectCommon(*compSet) ;
3035 dirSelNodes = (RooArgSet*) branchNodeSet.selectByName(compSpec) ;
3037 if (dirSelNodes->getSize()>0) {
3038 coutI(Plotting) <<
"RooAbsPdf::plotOn(" << GetName() <<
") directly selected PDF components: " << *dirSelNodes << endl ;
3041 plotOnCompSelect(dirSelNodes) ;
3044 coutE(Plotting) <<
"RooAbsPdf::plotOn(" << GetName() <<
") ERROR: component selection set " << *compSet <<
" does not match any components of p.d.f." << endl ;
3046 coutE(Plotting) <<
"RooAbsPdf::plotOn(" << GetName() <<
") ERROR: component selection expression '" << compSpec <<
"' does not select any components of p.d.f." << endl ;
3051 delete dirSelNodes ;
3055 RooCmdArg cnsuffix(
"CurveNameSuffix",0,0,0,0,nameSuffix.Data(),0,0,0) ;
3056 cmdList.Add(&cnsuffix);
3058 RooPlot* ret = RooAbsReal::plotOn(frame,cmdList) ;
3061 if (haveCompSel) plotOnCompSelect(0) ;
3087 RooPlot* RooAbsPdf::plotOn(RooPlot *frame, PlotOpt o)
const
3091 if (plotSanityChecks(frame))
return frame ;
3094 Double_t nExpected(1) ;
3095 if (o.stype==RelativeExpected) {
3096 if (!canBeExtended()) {
3097 coutE(Plotting) <<
"RooAbsPdf::plotOn(" << GetName()
3098 <<
"): ERROR the 'Expected' scale option can only be used on extendable PDFs" << endl ;
3101 nExpected = expectedEvents(frame->getNormVars()) ;
3105 if (o.stype != Raw) {
3107 if (frame->getFitRangeNEvt() && o.stype==Relative) {
3109 o.scaleFactor *= frame->getFitRangeNEvt()/nExpected ;
3110 }
else if (o.stype==RelativeExpected) {
3111 o.scaleFactor *= nExpected ;
3112 }
else if (o.stype==NumEvent) {
3113 o.scaleFactor /= nExpected ;
3115 o.scaleFactor *= frame->getFitRangeBinW() ;
3117 frame->updateNormVars(*frame->getPlotVar()) ;
3119 return RooAbsReal::plotOn(frame,o) ;
3152 RooPlot* RooAbsPdf::paramOn(RooPlot* frame,
const RooCmdArg& arg1,
const RooCmdArg& arg2,
3153 const RooCmdArg& arg3,
const RooCmdArg& arg4,
const RooCmdArg& arg5,
3154 const RooCmdArg& arg6,
const RooCmdArg& arg7,
const RooCmdArg& arg8)
3157 RooLinkedList cmdList;
3158 cmdList.Add(const_cast<RooCmdArg*>(&arg1)) ; cmdList.Add(const_cast<RooCmdArg*>(&arg2)) ;
3159 cmdList.Add(const_cast<RooCmdArg*>(&arg3)) ; cmdList.Add(const_cast<RooCmdArg*>(&arg4)) ;
3160 cmdList.Add(const_cast<RooCmdArg*>(&arg5)) ; cmdList.Add(const_cast<RooCmdArg*>(&arg6)) ;
3161 cmdList.Add(const_cast<RooCmdArg*>(&arg7)) ; cmdList.Add(const_cast<RooCmdArg*>(&arg8)) ;
3164 RooCmdConfig pc(Form(
"RooAbsPdf::paramOn(%s)",GetName())) ;
3165 pc.defineString(
"label",
"Label",0,
"") ;
3166 pc.defineDouble(
"xmin",
"Layout",0,0.50) ;
3167 pc.defineDouble(
"xmax",
"Layout",1,0.99) ;
3168 pc.defineInt(
"ymaxi",
"Layout",0,Int_t(0.95*10000)) ;
3169 pc.defineInt(
"showc",
"ShowConstants",0,0) ;
3170 pc.defineObject(
"params",
"Parameters",0,0) ;
3171 pc.defineString(
"formatStr",
"Format",0,
"NELU") ;
3172 pc.defineInt(
"sigDigit",
"Format",0,2) ;
3173 pc.defineInt(
"dummy",
"FormatArgs",0,0) ;
3174 pc.defineMutex(
"Format",
"FormatArgs") ;
3177 pc.process(cmdList) ;
3178 if (!pc.ok(kTRUE)) {
3182 const char* label = pc.getString(
"label") ;
3183 Double_t xmin = pc.getDouble(
"xmin") ;
3184 Double_t xmax = pc.getDouble(
"xmax") ;
3185 Double_t ymax = pc.getInt(
"ymaxi") / 10000. ;
3186 Int_t showc = pc.getInt(
"showc") ;
3189 const char* formatStr = pc.getString(
"formatStr") ;
3190 Int_t sigDigit = pc.getInt(
"sigDigit") ;
3193 RooArgSet* params =
static_cast<RooArgSet*
>(pc.getObject(
"params")) ;
3195 params = getParameters(frame->getNormVars()) ;
3196 if (pc.hasProcessed(
"FormatArgs")) {
3197 const RooCmdArg* formatCmd =
static_cast<RooCmdArg*
>(cmdList.FindObject(
"FormatArgs")) ;
3198 paramOn(frame,*params,showc,label,0,0,xmin,xmax,ymax,formatCmd) ;
3200 paramOn(frame,*params,showc,label,sigDigit,formatStr,xmin,xmax,ymax) ;
3204 RooArgSet* pdfParams = getParameters(frame->getNormVars()) ;
3205 RooArgSet* selParams =
static_cast<RooArgSet*
>(pdfParams->selectCommon(*params)) ;
3206 if (pc.hasProcessed(
"FormatArgs")) {
3207 const RooCmdArg* formatCmd =
static_cast<RooCmdArg*
>(cmdList.FindObject(
"FormatArgs")) ;
3208 paramOn(frame,*selParams,showc,label,0,0,xmin,xmax,ymax,formatCmd) ;
3210 paramOn(frame,*selParams,showc,label,sigDigit,formatStr,xmin,xmax,ymax) ;
3225 RooPlot* RooAbsPdf::paramOn(RooPlot* frame,
const RooAbsData* data,
const char *label,
3226 Int_t sigDigits, Option_t *options, Double_t xmin,
3227 Double_t xmax ,Double_t ymax)
3229 RooArgSet* params = getParameters(data) ;
3230 TString opts(options) ;
3231 paramOn(frame,*params,opts.Contains(
"c"),label,sigDigits,options,xmin,xmax,ymax) ;
3246 RooPlot* RooAbsPdf::paramOn(RooPlot* frame,
const RooArgSet& params, Bool_t showConstants,
const char *label,
3247 Int_t sigDigits, Option_t *options, Double_t xmin,
3248 Double_t xmax ,Double_t ymax,
const RooCmdArg* formatCmd)
3252 TString opts = options;
3254 Bool_t showLabel= (label != 0 && strlen(label) > 0);
3257 TIterator* pIter = params.createIterator() ;
3259 Double_t ymin(ymax), dy(0.06);
3260 RooRealVar *var = 0;
3261 while((var=(RooRealVar*)pIter->Next())) {
3262 if(showConstants || !var->isConstant()) ymin-= dy;
3265 if(showLabel) ymin-= dy;
3268 TPaveText *box=
new TPaveText(xmin,ymax,xmax,ymin,
"BRNDC");
3270 box->SetName(Form(
"%s_paramBox",GetName())) ;
3271 box->SetFillColor(0);
3272 box->SetBorderSize(1);
3273 box->SetTextAlign(12);
3274 box->SetTextSize(0.04F);
3275 box->SetFillStyle(1001);
3276 box->SetFillColor(0);
3279 while((var=(RooRealVar*)pIter->Next())) {
3280 if(var->isConstant() && !showConstants)
continue;
3282 TString *formatted= options ? var->format(sigDigits, options) : var->format(*formatCmd) ;
3283 box->AddText(formatted->Data());
3287 if(showLabel) box->AddText(label);
3290 frame->addObject(box) ;
3303 Double_t RooAbsPdf::expectedEvents(
const RooArgSet*)
const
3313 void RooAbsPdf::verboseEval(Int_t stat)
3315 _verboseEval = stat ;
3323 Int_t RooAbsPdf::verboseEval()
3325 return _verboseEval ;
3333 void RooAbsPdf::CacheElem::operModeHook(RooAbsArg::OperMode)
3344 RooAbsPdf::CacheElem::~CacheElem()
3348 RooAbsPdf* pdfOwner =
static_cast<RooAbsPdf*
>(_owner) ;
3349 if (pdfOwner->_norm == _norm) {
3350 pdfOwner->_norm = 0 ;
3362 RooAbsPdf* RooAbsPdf::createProjection(
const RooArgSet& iset)
3365 TString name(GetName()) ;
3366 name.Append(
"_Proj[") ;
3367 if (iset.getSize()>0) {
3368 TIterator* iter = iset.createIterator() ;
3370 Bool_t first(kTRUE) ;
3371 while((arg=(RooAbsArg*)iter->Next())) {
3377 name.Append(arg->GetName()) ;
3384 return new RooProjectedPdf(name.Data(),name.Data(),*
this,iset) ;
3400 RooAbsReal* RooAbsPdf::createCdf(
const RooArgSet& iset,
const RooArgSet& nset)
3402 return createCdf(iset,RooFit::SupNormSet(nset)) ;
3422 RooAbsReal* RooAbsPdf::createCdf(
const RooArgSet& iset,
const RooCmdArg& arg1,
const RooCmdArg& arg2,
3423 const RooCmdArg& arg3,
const RooCmdArg& arg4,
const RooCmdArg& arg5,
3424 const RooCmdArg& arg6,
const RooCmdArg& arg7,
const RooCmdArg& arg8)
3427 RooCmdConfig pc(Form(
"RooAbsReal::createCdf(%s)",GetName())) ;
3428 pc.defineObject(
"supNormSet",
"SupNormSet",0,0) ;
3429 pc.defineInt(
"numScanBins",
"ScanParameters",0,1000) ;
3430 pc.defineInt(
"intOrder",
"ScanParameters",1,2) ;
3431 pc.defineInt(
"doScanNum",
"ScanNumCdf",0,1) ;
3432 pc.defineInt(
"doScanAll",
"ScanAllCdf",0,0) ;
3433 pc.defineInt(
"doScanNon",
"ScanNoCdf",0,0) ;
3434 pc.defineMutex(
"ScanNumCdf",
"ScanAllCdf",
"ScanNoCdf") ;
3437 pc.process(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8) ;
3438 if (!pc.ok(kTRUE)) {
3443 const RooArgSet* snset =
static_cast<const RooArgSet*
>(pc.getObject(
"supNormSet",0)) ;
3448 Int_t numScanBins = pc.getInt(
"numScanBins") ;
3449 Int_t intOrder = pc.getInt(
"intOrder") ;
3450 Int_t doScanNum = pc.getInt(
"doScanNum") ;
3451 Int_t doScanAll = pc.getInt(
"doScanAll") ;
3452 Int_t doScanNon = pc.getInt(
"doScanNon") ;
3456 return createIntRI(iset,nset) ;
3459 return createScanCdf(iset,nset,numScanBins,intOrder) ;
3462 RooRealIntegral* tmp = (RooRealIntegral*) createIntegral(iset) ;
3463 Int_t isNum= (tmp->numIntRealVars().getSize()>0) ;
3467 coutI(NumIntegration) <<
"RooAbsPdf::createCdf(" << GetName() <<
") integration over observable(s) " << iset <<
" involves numeric integration," << endl
3468 <<
" constructing cdf though numeric integration of sampled pdf in " << numScanBins <<
" bins and applying order "
3469 << intOrder <<
" interpolation on integrated histogram." << endl
3470 <<
" To override this choice of technique use argument ScanNone(), to change scan parameters use ScanParameters(nbins,order) argument" << endl ;
3473 return isNum ? createScanCdf(iset,nset,numScanBins,intOrder) : createIntRI(iset,nset) ;
3478 RooAbsReal* RooAbsPdf::createScanCdf(
const RooArgSet& iset,
const RooArgSet& nset, Int_t numScanBins, Int_t intOrder)
3480 string name = string(GetName()) +
"_NUMCDF_" + integralNameSuffix(iset,&nset).Data() ;
3481 RooRealVar* ivar = (RooRealVar*) iset.first() ;
3482 ivar->setBins(numScanBins,
"numcdf") ;
3483 RooNumCdf* ret =
new RooNumCdf(name.c_str(),name.c_str(),*
this,*ivar,
"numcdf") ;
3484 ret->setInterpolationOrder(intOrder) ;
3495 RooArgSet* RooAbsPdf::getAllConstraints(
const RooArgSet& observables, RooArgSet& constrainedParams, Bool_t stripDisconnected)
const
3497 RooArgSet* ret =
new RooArgSet(
"AllConstraints") ;
3499 std::unique_ptr<RooArgSet> comps(getComponents());
3500 for (
const auto arg : *comps) {
3501 auto pdf =
dynamic_cast<const RooAbsPdf*
>(arg) ;
3502 if (pdf && !ret->find(pdf->GetName())) {
3503 std::unique_ptr<RooArgSet> compRet(pdf->getConstraints(observables,constrainedParams,stripDisconnected));
3505 ret->add(*compRet,kFALSE) ;
3517 RooNumGenConfig* RooAbsPdf::defaultGeneratorConfig()
3519 return &RooNumGenConfig::defaultConfig() ;
3527 RooNumGenConfig* RooAbsPdf::specialGeneratorConfig()
const
3529 return _specGeneratorConfig ;
3540 RooNumGenConfig* RooAbsPdf::specialGeneratorConfig(Bool_t createOnTheFly)
3542 if (!_specGeneratorConfig && createOnTheFly) {
3543 _specGeneratorConfig =
new RooNumGenConfig(*defaultGeneratorConfig()) ;
3545 return _specGeneratorConfig ;
3555 const RooNumGenConfig* RooAbsPdf::getGeneratorConfig()
const
3557 const RooNumGenConfig* config = specialGeneratorConfig() ;
3558 if (config)
return config ;
3559 return defaultGeneratorConfig() ;
3568 void RooAbsPdf::setGeneratorConfig(
const RooNumGenConfig& config)
3570 if (_specGeneratorConfig) {
3571 delete _specGeneratorConfig ;
3573 _specGeneratorConfig =
new RooNumGenConfig(config) ;
3582 void RooAbsPdf::setGeneratorConfig()
3584 if (_specGeneratorConfig) {
3585 delete _specGeneratorConfig ;
3587 _specGeneratorConfig = 0 ;
3594 RooAbsPdf::GenSpec::~GenSpec()
3596 delete _genContext ;
3602 RooAbsPdf::GenSpec::GenSpec(RooAbsGenContext* context,
const RooArgSet& whatVars, RooDataSet* protoData, Int_t nGen,
3603 Bool_t extended, Bool_t randProto, Bool_t resampleProto, TString dsetName, Bool_t init) :
3604 _genContext(context), _whatVars(whatVars), _protoData(protoData), _nGen(nGen), _extended(extended),
3605 _randProto(randProto), _resampleProto(resampleProto), _dsetName(dsetName), _init(init)
3613 void RooAbsPdf::setNormRange(
const char* rangeName)
3616 _normRange = rangeName ;
3618 _normRange.Clear() ;
3622 _normMgr.sterilize() ;
3630 void RooAbsPdf::setNormRangeOverride(
const char* rangeName)
3633 _normRangeOverride = rangeName ;
3635 _normRangeOverride.Clear() ;
3639 _normMgr.sterilize() ;