Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooSimGenContext.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * @(#)root/roofitcore:$Id$
5 * Authors: *
6 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8 * *
9 * Copyright (c) 2000-2005, Regents of the University of California *
10 * and Stanford University. All rights reserved. *
11 * *
12 * Redistribution and use in source and binary forms, *
13 * with or without modification, are permitted according to the terms *
14 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15 *****************************************************************************/
16
17/**
18\file RooSimGenContext.cxx
19\class RooSimGenContext
20\ingroup Roofitcore
21
22Efficient implementation of the generator context
23specific for RooSimultaneous PDFs when generating more than one of the
24component pdfs.
25It runs in two modes:
26- Proto data with category entries are given: An event from the same category as
27in the proto data is created.
28- No proto data: A category is chosen randomly.
29\note This requires that the PDFs are extended, to determine the relative probabilities
30that an event originates from a certain category.
31**/
32
33#include "RooSimGenContext.h"
34#include "RooSimultaneous.h"
35#include "RooRealProxy.h"
36#include "RooDataSet.h"
37#include "Roo1DTable.h"
38#include "RooCategory.h"
39#include "RooMsgService.h"
40#include "RooRandom.h"
41#include "RooGlobalFunc.h"
42
43#include <iostream>
44#include <string>
45
46
47////////////////////////////////////////////////////////////////////////////////
48/// Constructor of specialized generator context for RooSimultaneous p.d.f.s. This
49/// context creates a dedicated context for each component p.d.f.s and delegates
50/// generation of events to the appropriate component generator context
51
53 const RooDataSet *prototype, const RooArgSet* auxProto, bool verbose) :
54 RooAbsGenContext(model,vars,prototype,auxProto,verbose), _pdf(&model)
55{
56 // Determine if we are requested to generate the index category
57 RooAbsCategoryLValue const& idxCat = model.indexCat();
58 RooArgSet pdfVars(vars) ;
59
60 RooArgSet allPdfVars(pdfVars) ;
61 if (prototype) allPdfVars.add(*prototype->get(),true) ;
62
63 RooArgSet catsAmongAllVars;
64 allPdfVars.selectCommon(model.flattenedCatList(), catsAmongAllVars);
65
66 if(catsAmongAllVars.size() != model.flattenedCatList().size()) {
67 oocoutE(_pdf,Generation) << "RooSimGenContext::ctor(" << GetName() << ") ERROR: This context must"
68 << " generate all components of the index category" << std::endl ;
69 _isValid = false ;
70 _numPdf = 0 ;
71 _haveIdxProto = false ;
72 return ;
73 }
74
75 // We must either have the prototype or extended likelihood to determined
76 // the relative fractions of the components
77 _haveIdxProto = prototype ? true : false ;
78 _idxCatName = idxCat.GetName() ;
79 if (!_haveIdxProto && !model.canBeExtended()) {
80 oocoutE(_pdf,Generation) << "RooSimGenContext::ctor(" << GetName() << ") ERROR: Need either extended mode"
81 << " or prototype data to calculate number of events per category" << std::endl ;
82 _isValid = false ;
83 _numPdf = 0 ;
84 return ;
85 }
86
87 // Initialize fraction threshold array (used only in extended mode)
88 _numPdf = model._pdfProxyList.GetSize() ;
89 _fracThresh.resize(_numPdf+1);
90 _fracThresh[0] = 0 ;
91
92 // Generate index category and all registered PDFS
93 _allVarsPdf.add(allPdfVars) ;
94 Int_t i(1) ;
95 for(auto * proxy : static_range_cast<RooRealProxy*>(model._pdfProxyList)) {
96 auto* pdf = static_cast<RooAbsPdf*>(proxy->absArg());
97 RooArgSet genVars{pdfVars};
98 if (prototype) {
99 genVars.add(*prototype->get(), true);
100 }
101 pdf = RooSimultaneous::resolveSwitchMode(pdf, genVars);
102 if (!pdf) {
103 oocoutE(_pdf,Generation) << "RooSimGenContext::ctor(" << GetName() << ") ERROR: the nested RooSimultaneous for the state "
104 << proxy->name() << " has no pdf for its selected state" << std::endl ;
105 _isValid = false ;
106 _numPdf = 0 ;
107 return ;
108 }
109
110 // Name the context after the associated state and add to list
111 _gcList.emplace_back(pdf->genContext(pdfVars,prototype,auxProto,verbose)) ;
112
113 // Create generator context for this PDF
114 _gcList.back()->SetName(proxy->name()) ;
115
116 _gcIndex.push_back(idxCat.lookupIndex(proxy->name()));
117
118 // Fill fraction threshold array
119 _fracThresh[i] = _fracThresh[i-1] + (_haveIdxProto?0:pdf->expectedEvents(&allPdfVars)) ;
120 i++ ;
121 }
122
123 // Normalize fraction threshold array
124 if (!_haveIdxProto) {
125 for(i=0 ; i<_numPdf ; i++)
127 }
128
129
130 // Clone the index category
131 _idxCatSet = std::make_unique<RooArgSet>();
132 RooArgSet(model.indexCat()).snapshot(*_idxCatSet, true);
133 if (!_idxCatSet) {
134 oocoutE(_pdf,Generation) << "RooSimGenContext::RooSimGenContext(" << GetName() << ") Couldn't deep-clone index category, abort," << std::endl ;
135 throw std::string("RooSimGenContext::RooSimGenContext() Couldn't deep-clone index category, abort") ;
136 }
137
138 _idxCat = static_cast<RooAbsCategoryLValue*>(_idxCatSet->find(model.indexCat().GetName()));
139}
140
142
143////////////////////////////////////////////////////////////////////////////////
144/// Attach the index category clone to the given event buffer
145
147{
148 if (_idxCat->isDerived()) {
150 }
151
152 // Forward initGenerator call to all components
153 for(auto& item : _gcList) {
154 item->attach(args) ;
155 }
156
157}
158
159
160////////////////////////////////////////////////////////////////////////////////
161/// Perform one-time initialization of generator context
162
164{
165 // Attach the index category clone to the event
166 if (_idxCat->isDerived()) {
168 } else {
169 _idxCat = static_cast<RooAbsCategoryLValue*>(theEvent.find(_idxCat->GetName())) ;
170 }
171
172 // Update fractions reflecting possible new parameter values
174
175 // Forward initGenerator call to all components
176 for(auto& item : _gcList) {
177 item->initGenerator(theEvent) ;
178 }
179
180}
181
182
183////////////////////////////////////////////////////////////////////////////////
184/// Create an empty dataset to hold the events that will be generated
185
186RooDataSet* RooSimGenContext::createDataSet(const char* name, const char* title, const RooArgSet& obs)
187{
188
189 // If the observables do not contain the index, make a plain dataset
190 if (!obs.contains(*_idxCat)) {
191 return new RooDataSet(name,title,obs) ;
192 }
193
194 if (!_protoData) {
195 std::map<std::string,RooAbsData*> dmap ;
196 for (const auto& nameIdx : *_idxCat) {
197 RooAbsPdf* slicePdf = _pdf->getPdf(nameIdx.first.c_str());
198 std::unique_ptr<RooArgSet> sliceObs{slicePdf->getObservables(obs)};
199 std::string sliceName = name + ("_slice_" + nameIdx.first);
200 std::string sliceTitle = title + (" (index slice " + nameIdx.first + ")");
201 dmap[nameIdx.first] = new RooDataSet(sliceName,sliceTitle,*sliceObs);
202 }
203 using namespace RooFit;
204 _protoData = std::make_unique<RooDataSet>(name, title, obs, Index(static_cast<RooCategory&>(*_idxCat)), Link(dmap), OwnLinked()) ;
205 }
206
207 return new RooDataSet(*_protoData,name) ;
208}
209
210
211
212
213
214////////////////////////////////////////////////////////////////////////////////
215/// Generate event appropriate for current index state.
216/// The index state is taken either from the prototype
217/// or is generated from the fraction threshold table.
218
220{
221 if (_haveIdxProto) {
222
223 // Lookup pdf from selected prototype index state
224 Int_t gidx(0);
225 Int_t cidx = _idxCat->getCurrentIndex();
226 for (Int_t i=0 ; i<(Int_t)_gcIndex.size() ; i++) {
227 if (_gcIndex[i]==cidx) { gidx = i ; break ; }
228 }
229 RooAbsGenContext* cx = _gcList[gidx].get();
230 if (cx) {
231 cx->generateEvent(theEvent,remaining) ;
232 } else {
233 oocoutW(_pdf,Generation) << "RooSimGenContext::generateEvent: WARNING, no PDF to generate event of type " << cidx << std::endl ;
234 }
235
236
237 } else {
238
239 // Throw a random number and select PDF from fraction threshold table
240 double rand = RooRandom::uniform() ;
241 Int_t i=0 ;
242 for (i=0 ; i<_numPdf ; i++) {
243 if (rand>_fracThresh[i] && rand<_fracThresh[i+1]) {
244 RooAbsGenContext* gen=_gcList[i].get();
245 gen->generateEvent(theEvent,remaining) ;
246 //Write through to sub-categories because they might be written to dataset:
248 return ;
249 }
250 }
251
252 }
253}
254
255
256
257////////////////////////////////////////////////////////////////////////////////
258/// No action needed if we have a proto index
259
261{
262 if (_haveIdxProto) return ;
263
264 // Generate index category and all registered PDFS
265 Int_t i(1) ;
266 for(auto * proxy : static_range_cast<RooRealProxy*>(_pdf->_pdfProxyList)) {
267 auto* pdf = static_cast<RooAbsPdf*>(proxy->absArg());
268
269 // Fill fraction threshold array
270 _fracThresh[i] = _fracThresh[i-1] + (_haveIdxProto?0:pdf->expectedEvents(&_allVarsPdf)) ;
271 i++ ;
272 }
273
274 // Normalize fraction threshold array
275 if (!_haveIdxProto) {
276 for(i=0 ; i<_numPdf ; i++)
278 }
279
280}
281
282
283
284////////////////////////////////////////////////////////////////////////////////
285/// Set the traversal order of the prototype data to that in the
286/// given lookup table. This information is passed to all
287/// component generator contexts
288
290{
292
293 for (auto& item : _gcList) {
294 item->setProtoDataOrder(lut) ;
295 }
296}
297
298
299////////////////////////////////////////////////////////////////////////////////
300/// Detailed printing interface
301
302void RooSimGenContext::printMultiline(std::ostream &os, Int_t content, bool verbose, TString indent) const
303{
304 RooAbsGenContext::printMultiline(os,content,verbose,indent) ;
305 os << indent << "--- RooSimGenContext ---" << std::endl ;
306 os << indent << "Using PDF ";
308 os << indent << "List of component generators" << std::endl ;
309
310 TString indent2(indent) ;
311 indent2.Append(" ") ;
312
313 for (auto& item : _gcList) {
314 item->printMultiline(os,content,verbose,indent2);
315 }
316}
#define oocoutW(o, a)
#define oocoutE(o, a)
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
static void indent(ostringstream &buf, int indent_level)
char name[80]
Definition TGX11.cxx:142
bool recursiveRedirectServers(const RooAbsCollection &newSet, bool mustReplaceAll=false, bool nameChange=false, bool recurseInNewSet=true)
Recursively replace all servers with the new servers in newSet.
RooFit::OwningPtr< RooArgSet > getObservables(const RooArgSet &set, bool valueOnly=true) const
Given a set of possible observables, return the observables that this PDF depends on.
virtual bool isDerived() const
Does value or shape of this arg depend on any other arg?
Definition RooAbsArg.h:98
Abstract base class for objects that represent a discrete value that can be set from the outside,...
virtual bool setIndex(value_type index, bool printError=true)=0
Change category state by specifying the index code of the desired state.
virtual value_type getCurrentIndex() const
Return index number of current state.
value_type lookupIndex(const std::string &stateName) const
Find the index number corresponding to the state name.
bool contains(const char *name) const
Check if collection contains an argument with a specific name.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Storage_t::size_type size() const
RooAbsArg * find(const char *name) const
Find object with given name in list.
Abstract base class for generator contexts of RooAbsPdf objects.
void printMultiline(std::ostream &os, Int_t contents, bool verbose=false, TString indent="") const override
Interface for multi-line printing.
virtual void generateEvent(RooArgSet &theEvent, Int_t remaining)=0
bool _isValid
Is context in valid state?
virtual void setProtoDataOrder(Int_t *lut)
Set the traversal order of prototype data to that in the lookup tables passed as argument.
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:32
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
RooArgSet * snapshot(bool deepCopy=true) const
Use RooAbsCollection::snapshot(), but return as RooArgSet.
Definition RooArgSet.h:159
RooArgSet * selectCommon(const RooAbsCollection &refColl) const
Use RooAbsCollection::selecCommon(), but return as RooArgSet.
Definition RooArgSet.h:154
Object to represent discrete states.
Definition RooCategory.h:28
Container class to hold unbinned data.
Definition RooDataSet.h:32
const RooArgSet * get(Int_t index) const override
Return RooArgSet with coordinates of event 'index'.
virtual void printStream(std::ostream &os, Int_t contents, StyleOption style, TString indent="") const
Print description of object on ostream, printing contents set by contents integer,...
static double uniform(TRandom *generator=randomGenerator())
Return a number uniformly distributed from (0,1)
Definition RooRandom.cxx:77
RooAbsCategoryLValue * _idxCat
Clone of index category.
void initGenerator(const RooArgSet &theEvent) override
Perform one-time initialization of generator context.
std::unique_ptr< RooDataSet > _protoData
! Prototype dataset
void printMultiline(std::ostream &os, Int_t content, bool verbose=false, TString indent="") const override
Detailed printing interface.
std::unique_ptr< RooArgSet > _idxCatSet
Owner of index category components.
RooArgSet _allVarsPdf
All pdf variables.
void setProtoDataOrder(Int_t *lut) override
Set the traversal order of the prototype data to that in the given lookup table.
void updateFractions()
No action needed if we have a proto index.
std::vector< std::unique_ptr< RooAbsGenContext > > _gcList
List of component generator contexts.
const RooSimultaneous * _pdf
Original PDF.
RooSimGenContext(const RooSimultaneous &model, const RooArgSet &vars, const RooDataSet *prototype=nullptr, const RooArgSet *auxProto=nullptr, bool _verbose=false)
Constructor of specialized generator context for RooSimultaneous p.d.f.s.
RooDataSet * createDataSet(const char *name, const char *title, const RooArgSet &obs) override
Create an empty dataset to hold the events that will be generated.
TString _idxCatName
Name of index category.
void generateEvent(RooArgSet &theEvent, Int_t remaining) override
Generate event appropriate for current index state.
Int_t _numPdf
Number of generated PDFs.
std::vector< double > _fracThresh
[_numPdf] Fraction threshold array
std::vector< int > _gcIndex
Index value corresponding to component.
void attach(const RooArgSet &params) override
Attach the index category clone to the given event buffer.
~RooSimGenContext() override
bool _haveIdxProto
Flag set if generation of index is requested.
Facilitates simultaneous fitting of multiple PDFs to subsets of a given dataset.
TList _pdfProxyList
List of PDF proxies (named after applicable category state)
RooAbsPdf * getPdf(RooStringView catName) const
Return the p.d.f associated with the given index category name.
static RooAbsPdf * resolveSwitchMode(RooAbsPdf *pdf, RooArgSet const &vars)
For the generator contexts: a component that is a RooSimultaneous whose index category is not among t...
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
Basic string class.
Definition TString.h:137
TString & Append(const char *cs)
Definition TString.h:582
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Definition CodegenImpl.h:73