54 using namespace RooFit;
58 ClassImp(RooStats::ToyMCSampler);
67 void NuisanceParametersSampler::NextPoint(RooArgSet& nuisPoint, Double_t& weight) {
70 if (fIndex >= fNToys) {
76 nuisPoint = *fPoints->get(fIndex++);
77 weight = fPoints->weight();
80 if(fPoints->weight() == 0.0) {
81 oocoutI((TObject*)NULL,Generation) <<
"Weight 0 encountered. Skipping." << endl;
82 NextPoint(nuisPoint, weight);
92 void NuisanceParametersSampler::Refresh() {
94 if (!fPrior || !fParams)
return;
96 if (fPoints)
delete fPoints;
100 oocoutI((TObject*)NULL,InputArguments) <<
"Using expected nuisance parameters." << endl;
106 TIter it2 = fParams->createIterator();
108 while ((myarg2 = dynamic_cast<RooRealVar*>(it2.Next()))) {
109 myarg2->setBins(nBins);
113 fPoints = fPrior->generate(
119 if(fPoints->numEntries() != fNToys) {
120 fNToys = fPoints->numEntries();
121 oocoutI((TObject*)NULL,InputArguments) <<
122 "Adjusted number of toys to number of bins of nuisance parameters: " << fNToys << endl;
138 oocoutI((TObject*)NULL,InputArguments) <<
"Using randomized nuisance parameters." << endl;
140 fPoints = fPrior->generate(*fParams, fNToys);
144 Bool_t ToyMCSampler::fgAlwaysUseMultiGen = kFALSE ;
148 void ToyMCSampler::SetAlwaysUseMultiGen(Bool_t flag) { fgAlwaysUseMultiGen = flag ; }
153 ToyMCSampler::ToyMCSampler() : fSamplingDistName(
"SD"), fNToys(1)
157 fParametersForTestStat = NULL;
158 fPriorNuisance = NULL;
159 fNuisancePars = NULL;
161 fGlobalObservables = NULL;
165 fGenerateBinned = kFALSE;
166 fGenerateBinnedTag =
"";
167 fGenerateAutoBinned = kTRUE;
168 fExpectedNuisancePar = kFALSE;
171 fMaxToys = RooNumber::infinity();
172 fAdaptiveLowLimit = -RooNumber::infinity();
173 fAdaptiveHighLimit = RooNumber::infinity();
178 fNuisanceParametersSampler = NULL;
187 RooMsgService::instance().getStream(1).removeTopic(RooFit::NumIntegration);
189 fUseMultiGen = kFALSE ;
194 ToyMCSampler::ToyMCSampler(TestStatistic &ts, Int_t ntoys) : fSamplingDistName(ts.GetVarName().Data()), fNToys(ntoys)
197 fParametersForTestStat = NULL;
198 fPriorNuisance = NULL;
199 fNuisancePars = NULL;
201 fGlobalObservables = NULL;
205 fGenerateBinned = kFALSE;
206 fGenerateBinnedTag =
"";
207 fGenerateAutoBinned = kTRUE;
208 fExpectedNuisancePar = kFALSE;
211 fMaxToys = RooNumber::infinity();
212 fAdaptiveLowLimit = -RooNumber::infinity();
213 fAdaptiveHighLimit = RooNumber::infinity();
218 fNuisanceParametersSampler = NULL;
227 RooMsgService::instance().getStream(1).removeTopic(RooFit::NumIntegration);
229 fUseMultiGen = kFALSE ;
231 AddTestStatistic(&ts);
236 ToyMCSampler::~ToyMCSampler() {
237 if(fNuisanceParametersSampler)
delete fNuisanceParametersSampler;
246 Bool_t ToyMCSampler::CheckConfig(
void) {
247 bool goodConfig =
true;
249 if(fTestStatistics.size() == 0 || fTestStatistics[0] == NULL) { ooccoutE((TObject*)NULL,InputArguments) <<
"Test statistic not set." << endl; goodConfig =
false; }
250 if(!fObservables) { ooccoutE((TObject*)NULL,InputArguments) <<
"Observables not set." << endl; goodConfig =
false; }
251 if(!fParametersForTestStat) { ooccoutE((TObject*)NULL,InputArguments) <<
"Parameter values used to evaluate the test statistic are not set." << endl; goodConfig =
false; }
252 if(!fPdf) { ooccoutE((TObject*)NULL,InputArguments) <<
"Pdf not set." << endl; goodConfig =
false; }
270 RooArgList* ToyMCSampler::EvaluateAllTestStatistics(RooAbsData& data,
const RooArgSet& poi) {
271 DetailedOutputAggregator detOutAgg;
272 const RooArgList* allTS = EvaluateAllTestStatistics(data, poi, detOutAgg);
273 if (!allTS)
return 0;
275 return dynamic_cast<RooArgList*
>(allTS->snapshot());
280 const RooArgList* ToyMCSampler::EvaluateAllTestStatistics(RooAbsData& data,
const RooArgSet& poi, DetailedOutputAggregator& detOutAgg) {
281 RooArgSet *allVars = fPdf ? fPdf->getVariables() :
nullptr;
282 RooArgSet *saveAll = allVars ? allVars->snapshot() :
nullptr;
283 for(
unsigned int i = 0; i < fTestStatistics.size(); i++ ) {
284 if( fTestStatistics[i] == NULL )
continue;
285 TString name( TString::Format(
"%s_TS%u", fSamplingDistName.c_str(), i) );
286 std::unique_ptr<RooArgSet> parForTS(poi.snapshot());
287 RooRealVar ts( name, fTestStatistics[i]->GetVarName(), fTestStatistics[i]->Evaluate( data, *parForTS ) );
289 detOutAgg.AppendArgSet(&tset);
290 if (
const RooArgSet* detOut = fTestStatistics[i]->GetDetailedOutput()) {
292 detOutAgg.AppendArgSet(detOut, name);
294 if (saveAll) *allVars = *saveAll;
298 return detOutAgg.GetAsArgList();
303 SamplingDistribution* ToyMCSampler::GetSamplingDistribution(RooArgSet& paramPointIn) {
304 if(fTestStatistics.size() > 1) {
305 oocoutW((TObject*)NULL, InputArguments) <<
"Multiple test statistics defined, but only one distribution will be returned." << endl;
306 for(
unsigned int i=0; i < fTestStatistics.size(); i++ ) {
307 oocoutW((TObject*)NULL, InputArguments) <<
" \t test statistic: " << fTestStatistics[i] << endl;
311 RooDataSet* r = GetSamplingDistributions(paramPointIn);
312 if(r == NULL || r->numEntries() == 0) {
313 oocoutW((TObject*)NULL, Generation) <<
"no sampling distribution generated" << endl;
317 SamplingDistribution* samp =
new SamplingDistribution( r->GetName(), r->GetTitle(), *r );
325 RooDataSet* ToyMCSampler::GetSamplingDistributions(RooArgSet& paramPointIn)
330 return GetSamplingDistributionsSingleWorker(paramPointIn);
334 oocoutE((TObject*)NULL, InputArguments)
335 <<
"Bad COnfiguration in ToyMCSampler "
343 oocoutW((TObject*)NULL, InputArguments)
344 <<
"Adaptive sampling in ToyMCSampler is not supported for parallel runs."
349 Int_t totToys = fNToys;
350 fNToys = (int)ceil((
double)fNToys / (double)fProofConfig->GetNExperiments());
353 ToyMCStudy* toymcstudy =
new ToyMCStudy ;
354 toymcstudy->SetToyMCSampler(*
this);
355 toymcstudy->SetParamPoint(paramPointIn);
356 toymcstudy->SetRandomSeed(RooRandom::randomGenerator()->Integer(TMath::Limits<unsigned int>::Max() ) );
359 RooWorkspace w(fProofConfig->GetWorkspace());
360 RooStudyManager studymanager(w, *toymcstudy);
361 studymanager.runProof(fProofConfig->GetNExperiments(), fProofConfig->GetHost(), fProofConfig->GetShowGui());
363 RooDataSet* output = toymcstudy->merge();
380 RooDataSet* ToyMCSampler::GetSamplingDistributionsSingleWorker(RooArgSet& paramPointIn)
389 oocoutE((TObject*)NULL, InputArguments)
390 <<
"Bad COnfiguration in ToyMCSampler "
397 RooArgSet *paramPoint = (RooArgSet*) paramPointIn.snapshot();
398 RooArgSet *allVars = fPdf->getVariables();
399 RooArgSet *saveAll = (RooArgSet*) allVars->snapshot();
402 DetailedOutputAggregator detOutAgg;
406 Double_t toysInTails = 0.0;
408 for (Int_t i = 0; i < fMaxToys; ++i) {
410 if (toysInTails >= fToysInTails && i+1 > fNToys)
break;
413 if ( i% 500 == 0 && i>0 ) {
414 oocoutP((TObject*)0,Generation) <<
"generated toys: " << i <<
" / " << fNToys;
415 if (fToysInTails) ooccoutP((TObject*)0,Generation) <<
" (tails: " << toysInTails <<
" / " << fToysInTails <<
")" << std::endl;
416 else ooccoutP((TObject*)0,Generation) << endl;
422 Double_t valueFirst = -999.0, weight = 1.0;
427 RooAbsData* toydata = GenerateToyData(*paramPoint, weight);
428 if (i == 0 && !fPdf->canBeExtended() &&
dynamic_cast<RooSimultaneous*
>(fPdf)) {
429 const RooArgSet* toySet = toydata->get();
430 if (std::none_of(toySet->begin(), toySet->end(), [](
const RooAbsArg* arg){
431 return dynamic_cast<const RooAbsCategory*
>(arg) !=
nullptr;
433 oocoutE((TObject*)
nullptr, Generation) <<
"ToyMCSampler: Generated toy data didn't contain a category variable, although"
434 " a simultaneous PDF is in use. To generate events for a simultaneous PDF, all components need to be"
435 " extended. Otherwise, the number of events to generate per component cannot be determined." << std::endl;
438 *allVars = *fParametersForTestStat;
440 const RooArgList* allTS = EvaluateAllTestStatistics(*toydata, *fParametersForTestStat, detOutAgg);
441 if (allTS->getSize() > Int_t(fTestStatistics.size()))
442 detOutAgg.AppendArgSet( fGlobalObservables,
"globObs_" );
443 if (RooRealVar* firstTS = dynamic_cast<RooRealVar*>(allTS->first()))
444 valueFirst = firstTS->getVal();
449 if(valueFirst != valueFirst) {
450 oocoutW((TObject*)NULL, Generation) <<
"skip: " << valueFirst <<
", " << weight << endl;
454 detOutAgg.CommitSet(weight);
457 if (valueFirst <= fAdaptiveLowLimit || valueFirst >= fAdaptiveHighLimit) {
458 if(weight >= 0.) toysInTails += weight;
459 else toysInTails += 1.;
469 return detOutAgg.GetAsDataSet(fSamplingDistName, fSamplingDistName);
474 void ToyMCSampler::GenerateGlobalObservables(RooAbsPdf& pdf)
const {
477 if(!fGlobalObservables || fGlobalObservables->getSize()==0) {
478 ooccoutE((TObject*)NULL,InputArguments) <<
"Global Observables not set." << endl;
483 if (fUseMultiGen || fgAlwaysUseMultiGen) {
487 RooSimultaneous* simPdf =
dynamic_cast<RooSimultaneous*
>( &pdf );
489 RooDataSet *one = pdf.generate(*fGlobalObservables, 1);
491 const RooArgSet *values = one->get(0);
493 _allVars = pdf.getVariables();
500 if (_pdfList.size() == 0) {
501 RooCategory& channelCat = (RooCategory&)simPdf->indexCat();
502 int nCat = channelCat.numTypes();
503 for (
int i=0; i < nCat; ++i){
504 channelCat.setIndex(i);
505 RooAbsPdf* pdftmp = simPdf->getPdf(channelCat.getLabel());
507 RooArgSet* globtmp = pdftmp->getObservables(*fGlobalObservables);
508 RooAbsPdf::GenSpec* gs = pdftmp->prepareMultiGen(*globtmp, NumEvents(1));
509 _pdfList.push_back(pdftmp);
510 _obsList.push_back(globtmp);
511 _gsList.push_back(gs);
515 list<RooArgSet*>::iterator oiter = _obsList.begin();
516 list<RooAbsPdf::GenSpec*>::iterator giter = _gsList.begin();
517 for (list<RooAbsPdf*>::iterator iter = _pdfList.begin(); iter != _pdfList.end(); ++iter, ++giter, ++oiter) {
519 RooDataSet* tmp = (*iter)->generate(**giter);
520 **oiter = *tmp->get(0);
529 RooDataSet* one = pdf.generateSimGlobal( *fGlobalObservables, 1 );
530 const RooArgSet *values = one->get(0);
531 RooArgSet* allVars = pdf.getVariables();
546 RooAbsData* ToyMCSampler::GenerateToyData(RooArgSet& paramPoint,
double& weight, RooAbsPdf& pdf)
const {
549 ooccoutE((TObject*)NULL,InputArguments) <<
"Observables not set." << endl;
554 RooArgSet* allVars = fPdf->getVariables();
555 *allVars = paramPoint;
559 if(!fNuisanceParametersSampler && fPriorNuisance && fNuisancePars) {
560 fNuisanceParametersSampler =
new NuisanceParametersSampler(fPriorNuisance, fNuisancePars, fNToys, fExpectedNuisancePar);
561 if ((fUseMultiGen || fgAlwaysUseMultiGen) && fNuisanceParametersSampler )
562 oocoutI((TObject*)NULL,InputArguments) <<
"Cannot use multigen when nuisance parameters vary for every toy" << endl;
566 RooArgSet observables(*fObservables);
567 if(fGlobalObservables && fGlobalObservables->getSize()) {
568 observables.remove(*fGlobalObservables);
569 GenerateGlobalObservables(pdf);
574 const RooArgSet* saveVars = (
const RooArgSet*)allVars->snapshot();
576 if(fNuisanceParametersSampler) {
585 RooArgSet allVarsMinusParamPoint(*allVars);
586 allVarsMinusParamPoint.remove(paramPoint, kFALSE, kTRUE);
589 fNuisanceParametersSampler->NextPoint(allVarsMinusParamPoint, weight);
596 RooAbsData *data = Generate(pdf, observables);
600 *allVars = *saveVars;
614 RooAbsData* ToyMCSampler::Generate(RooAbsPdf &pdf, RooArgSet &observables,
const RooDataSet* protoData,
int forceEvents)
const {
617 protoData = fProtoData;
618 forceEvents = protoData->numEntries();
621 RooAbsData *data = NULL;
622 int events = forceEvents;
623 if(events == 0) events = fNEvents;
626 bool useMultiGen = (fUseMultiGen || fgAlwaysUseMultiGen) && !fNuisanceParametersSampler;
629 if (pdf.canBeExtended() && pdf.expectedEvents(observables) > 0) {
630 if(fGenerateBinned) {
631 if(protoData) data = pdf.generate(observables, AllBinned(), Extended(), ProtoData(*protoData,
true,
true));
632 else data = pdf.generate(observables, AllBinned(), Extended());
636 if (!_gs2) { _gs2 = pdf.prepareMultiGen(observables, Extended(), AutoBinned(fGenerateAutoBinned), GenBinned(fGenerateBinnedTag), ProtoData(*protoData,
true,
true)) ; }
637 data = pdf.generate(*_gs2) ;
639 data = pdf.generate (observables, Extended(), AutoBinned(fGenerateAutoBinned), GenBinned(fGenerateBinnedTag), ProtoData(*protoData,
true,
true));
643 if (!_gs1) { _gs1 = pdf.prepareMultiGen(observables, Extended(), AutoBinned(fGenerateAutoBinned), GenBinned(fGenerateBinnedTag) ) ; }
644 data = pdf.generate(*_gs1) ;
646 data = pdf.generate (observables, Extended(), AutoBinned(fGenerateAutoBinned), GenBinned(fGenerateBinnedTag) );
652 oocoutE((TObject*)0,InputArguments)
653 <<
"ToyMCSampler: Error : pdf is not extended and number of events per toy is zero"
657 if (fGenerateBinned) {
658 if(protoData) data = pdf.generate(observables, events, AllBinned(), ProtoData(*protoData,
true,
true));
659 else data = pdf.generate(observables, events, AllBinned());
663 if (!_gs3) { _gs3 = pdf.prepareMultiGen(observables, NumEvents(events), AutoBinned(fGenerateAutoBinned), GenBinned(fGenerateBinnedTag), ProtoData(*protoData,
true,
true)); }
664 data = pdf.generate(*_gs3) ;
666 data = pdf.generate (observables, NumEvents(events), AutoBinned(fGenerateAutoBinned), GenBinned(fGenerateBinnedTag), ProtoData(*protoData,
true,
true));
670 if (!_gs4) { _gs4 = pdf.prepareMultiGen(observables, NumEvents(events), AutoBinned(fGenerateAutoBinned), GenBinned(fGenerateBinnedTag)); }
671 data = pdf.generate(*_gs4) ;
673 data = pdf.generate (observables, NumEvents(events), AutoBinned(fGenerateAutoBinned), GenBinned(fGenerateBinnedTag));
691 SamplingDistribution* ToyMCSampler::AppendSamplingDistribution(
692 RooArgSet& allParameters,
693 SamplingDistribution* last,
697 fNToys = additionalMC;
698 SamplingDistribution* newSamples = GetSamplingDistribution(allParameters);
702 last->Add(newSamples);
714 void ToyMCSampler::ClearCache() {
716 if (_gs1)
delete _gs1;
718 if (_gs2)
delete _gs2;
720 if (_gs3)
delete _gs3;
722 if (_gs4)
delete _gs4;
726 if (_pdfList.size() > 0) {
727 std::list<RooArgSet*>::iterator oiter = _obsList.begin();
728 for (std::list<RooAbsPdf::GenSpec*>::iterator giter = _gsList.begin(); giter != _gsList.end(); ++giter, ++oiter) {
738 if (_allVars)
delete _allVars;